Nginx Keepalive 详解:作用、原理与配置指南
Nginx 作为高性能的 Web 服务器和反向代理,其性能优化是许多系统管理员和开发者关注的重点。在 Nginx 的众多优化机制中,keepalive 连接是一个至关重要的特性,它能够显著减少网络延迟、提高资源利用率和整体吞吐量。本文将深入探讨 Nginx keepalive 的作用、工作原理以及详细的配置方法。
1. Nginx Keepalive 的作用
keepalive 连接(也称为持久连接或长连接)是指客户端和服务器之间在完成一次请求-响应周期后不立即关闭 TCP 连接,而是保持连接打开状态,以便在后续的请求中复用该连接。对于 Nginx 而言,keepalive 主要体现在以下两个层面:
-
客户端到 Nginx 的
keepalive(HTTP Keepalive)- 减少 TCP 握手开销: 每次建立新的 TCP 连接都需要经过三次握手,这会增加延迟和服务器的资源消耗。
keepalive允许在同一连接上发送多个 HTTP 请求,避免了重复的握手过程。 - 减少慢启动(Slow Start)的影响: TCP 的慢启动机制在连接建立初期会限制数据传输速率。
keepalive连接的持续存在使得连接能够更快地达到其最大传输速率。 - 提高请求响应速度: 客户端无需等待新的 TCP 连接建立即可发送下一个请求,显著缩短了整体的请求响应时间。
- 降低服务器资源消耗: 尽管连接保持开放,但服务器无需频繁创建和销毁连接,减少了 CPU 和内存的开销。
- 减少 TCP 握手开销: 每次建立新的 TCP 连接都需要经过三次握手,这会增加延迟和服务器的资源消耗。
-
Nginx 到上游服务器的
keepalive(Backend Keepalive)- 当 Nginx 作为反向代理时,它不仅与客户端建立连接,还会与后端的应用服务器(如 Tomcat, Node.js 应用等)建立连接。在这种场景下,Nginx 也可以通过
keepalive机制与后端服务器保持持久连接。 - 减轻后端服务器压力: 类似于客户端到 Nginx 的情况,后端服务器也无需频繁处理 TCP 握手和连接关闭,降低了其资源消耗。
- 提高代理转发效率: Nginx 向后端转发请求时,可以直接复用已有的连接,减少了延迟,提高了数据传输效率。
- 优化连接池管理: Nginx 内部维护一个与后端服务器的
keepalive连接池,智能地管理和复用这些连接。
- 当 Nginx 作为反向代理时,它不仅与客户端建立连接,还会与后端的应用服务器(如 Tomcat, Node.js 应用等)建立连接。在这种场景下,Nginx 也可以通过
2. Nginx Keepalive 的原理
keepalive 连接的核心原理是利用 HTTP/1.1 协议的特性。在 HTTP/1.1 中,默认所有连接都是 keepalive 的,除非请求头中明确指定 Connection: close。
工作流程简述:
-
客户端到 Nginx:
- 客户端发起第一个 HTTP 请求,并在请求头中带上
Connection: keep-alive(HTTP/1.1 默认行为)。 - Nginx 接收请求并处理,在响应头中也带上
Connection: keep-alive。 - 客户端收到响应后,不关闭 TCP 连接,而是等待一定时间内是否需要发送下一个请求。
- 如果客户端在指定时间内发送了新请求,Nginx 会复用现有连接进行处理。
- 如果客户端在指定时间内没有发送新请求,或者请求次数达到上限,Nginx 会主动关闭连接。
- 客户端发起第一个 HTTP 请求,并在请求头中带上
-
Nginx 到上游服务器:
- 当 Nginx 收到客户端请求需要转发到后端时,Nginx 会检查其与后端服务器的
keepalive连接池。 - 如果连接池中有可用的空闲连接,Nginx 会直接复用该连接将请求转发给后端。
- 如果连接池中没有可用连接,Nginx 会建立新的连接并将其加入连接池。
- 后端服务器处理请求并返回响应给 Nginx。
- Nginx 收到后端响应后,将连接标记为空闲,以便后续请求复用。
- Nginx 会根据配置的超时时间和最大请求数来管理这些后端
keepalive连接的生命周期。
- 当 Nginx 收到客户端请求需要转发到后端时,Nginx 会检查其与后端服务器的
3. Nginx Keepalive 的配置指南
Nginx 的 keepalive 配置主要分为两个部分:针对客户端的 keepalive 和针对后端服务器的 keepalive。
3.1 客户端到 Nginx 的 Keepalive 配置
这些配置通常放在 http 块、server 块或 location 块中。
-
keepalive_timeout- 语法:
keepalive_timeout timeout [header_timeout]; - 默认值:
keepalive_timeout 75s; - 作用: 客户端
keepalive连接在 Nginx 侧的超时时间。如果在这个时间内客户端没有发送新的请求,Nginx 将关闭该连接。header_timeout是可选的,用于设置响应头中Keep-Alive: timeout=time的值,现代浏览器通常会忽略此值,主要参考 Nginx 实际的timeout。 - 建议: 通常设置为
60s到120s。过短会增加连接建立开销,过长会占用过多服务器资源。
- 语法:
-
keepalive_requests- 语法:
keepalive_requests number; - 默认值:
keepalive_requests 100; - 作用: 在一个
keepalive连接上可以处理的最大请求数量。达到这个数量后,Nginx 会关闭连接,即使keepalive_timeout尚未过期。 - 建议: 默认值
100对于大多数情况是足够的。如果你的应用请求量非常大且频繁,可以适当调高,例如1000或更高,但这也会增加单个连接的资源占用时间。
- 语法:
-
send_timeout- 语法:
send_timeout time; - 默认值:
send_timeout 60s; - 作用: Nginx 向客户端发送响应的超时时间。如果在指定的
time内,客户端没有接收到任何数据(包括响应头或响应体),Nginx 将关闭连接。这个超时仅在两个连续的写入操作之间起作用,而不是整个传输过程。 - 注意: 这个超时与
keepalive_timeout不同,它关注的是数据传输的活跃性。
- 语法:
示例配置:
“`nginx
http {
keepalive_timeout 65s;
keepalive_requests 200;
send_timeout 60s;
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend_servers;
# ... 其他配置
}
}
}
“`
3.2 Nginx 到上游服务器的 Keepalive 配置 (反向代理)
这部分配置主要在 http 块、server 块的 location 块中,并且需要配合 upstream 块使用。
首先,在 http 块中定义 upstream 负载均衡组:
“`nginx
http {
upstream backend_servers {
server 192.168.1.100:8080;
server 192.168.1.101:8080;
keepalive 64; # 定义与上游服务器的keepalive连接数
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend_servers;
# ... Nginx 到上游服务器的 keepalive 关键配置
proxy_http_version 1.1;
proxy_set_header Connection ""; # 清除或设置为空,防止后端关闭连接
# 或者 proxy_set_header Connection "keep-alive"; 明确指定
# proxy_connect_timeout 5s; # 与后端建立连接的超时时间
# proxy_send_timeout 60s; # Nginx 向后端发送请求的超时时间
# proxy_read_timeout 60s; # Nginx 从后端接收响应的超时时间
}
}
}
“`
-
keepalive(在upstream块中)- 语法:
keepalive connections; - 默认值: 无
- 作用: 设置每个 worker 进程为上游服务器保留的
keepalive连接的最大数量。当连接空闲时,它们会被 Nginx 保留在缓存中。 - 建议: 这个值不宜设置过大,通常是
32到128之间。过大可能会导致后端服务器连接数过多而无法处理新连接。需要注意的是,这个keepalive是针对每个 worker 进程的,而不是全局的。 如果你有 4 个 worker 进程,那么总共可能会有4 * connections个keepalive连接。
- 语法:
-
proxy_http_version- 语法:
proxy_http_version 1.0 | 1.1; - 默认值:
proxy_http_version 1.0; - 作用: Nginx 作为代理时,向后端服务器发送请求使用的 HTTP 协议版本。要启用 Nginx 到后端的
keepalive,必须将其设置为1.1。 - 重要: 这是启用后端
keepalive的关键配置。
- 语法:
-
proxy_set_header Connection- 语法:
proxy_set_header Connection "";或proxy_set_header Connection "keep-alive"; - 作用: Nginx 代理请求时,如何处理
Connection请求头。proxy_set_header Connection "";(推荐):这是最常见的做法。Nginx 会删除或清空原始客户端请求中的Connection头,然后根据proxy_http_version 1.1自身决定与后端服务器的连接策略。这防止了客户端的Connection: close指令传递给后端,从而破坏 Nginx 与后端的keepalive。proxy_set_header Connection "keep-alive";: 明确告诉后端服务器保持连接。但通常情况下,proxy_http_version 1.1已经隐含了keep-alive,所以这种方式不如清除原始Connection头灵活。
- 注意: 对于
WebSocket或其他需要升级协议的场景,Connection头需要设置为upgrade。
- 语法:
-
proxy_connect_timeout- 语法:
proxy_connect_timeout time; - 默认值:
proxy_connect_timeout 60s; - 作用: Nginx 与后端服务器建立连接的超时时间。
- 语法:
-
proxy_send_timeout- 语法:
proxy_send_timeout time; - 默认值:
proxy_send_timeout 60s; - 作用: Nginx 向后端服务器发送请求的超时时间。如果在指定时间内 Nginx 没有向后端发送数据,则关闭连接。
- 语法:
-
proxy_read_timeout- 语法:
proxy_read_timeout time; - 默认值:
proxy_read_timeout 60s; - 作用: Nginx 从后端服务器接收响应的超时时间。如果在指定时间内 Nginx 没有从后端接收到任何数据,则关闭连接。
- 语法:
4. 总结与注意事项
正确配置 Nginx keepalive 是提升 Web 应用性能的关键一步。
- 客户端
keepalive减少了客户端到 Nginx 的连接开销,提高了用户体验。 - 后端
keepalive减少了 Nginx 到上游服务器的连接开销,降低了后端服务器的压力,提高了代理效率。
重要注意事项:
- 平衡资源与性能:
keepalive_timeout和keepalive_requests的值需要根据你的应用流量模式、客户端行为和服务器资源进行权衡。过长或过多的keepalive连接会占用服务器资源,可能导致其他新连接无法建立。 - 后端服务器支持: 确保你的后端应用服务器也支持
keepalive连接。大多数现代 Web 框架和服务器(如 Java Tomcat, Node.js Express, Python Gunicorn/uWSGI 等)都默认支持。 - 负载均衡器(LB)与
keepalive: 如果你的 Nginx 前面还有一层硬件负载均衡器或云服务 LB,需要确保这些 LB 也配置了适当的keepalive策略,以避免它们在 Nginx 期望连接保持时过早关闭连接。 proxy_set_header Connection ""的重要性: 这一步在反向代理场景中非常关键,它确保 Nginx 能够独立管理与后端服务器的keepalive连接,而不受客户端Connection头的影响。- 监控与调整: 部署后,密切监控 Nginx 和后端服务器的连接数、CPU、内存使用情况,根据实际性能表现和瓶颈进行调整。
通过精细化配置 Nginx keepalive,你可以为你的 Web 服务构建一个更高效、更稳定的网络层。