keepalive 连接池如何配合轮询策略工作
nginx 的 keepalive 模块通过维护一个长连接池,让上游服务器复用 tcp 连接,从而减少握手开销。在轮询(round robin)模式下,nginx 会从池中取出空闲连接分配给请求,如果池中没有可用连接或连接已失效,则新建连接并尝试放回池中。这种机制要求上游服务器支持 http/1.1 或 http/2,且 nginx 配置中必须显式声明 keepalive 指令以激活该功能。

upstream backend {
server 192.168.1.10:80;
server 192.168.1.11:80;
keepalive 32;
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
上述配置中,keepalive 32 指定每个 worker 进程保留的空闲连接数上限。proxy_http_version 1.1 和 proxy_set_header Connection "" 是必须的,因为默认 HTTP/1.0 会在响应后关闭连接,而空 Connection 头告诉上游服务器保持连接活跃。当多个请求并发时,Nginx 会优先从这 32 个空闲连接中选取,若选中的连接属于某个上游服务器,后续请求可能继续使用该连接,直到达到最大复用次数或连接超时。
轮询策略下连接分配的负载均衡效果
在标准的轮询策略中,新建立的连接会均匀分布到各个上游服务器。然而,启用 keepalive 后,由于连接被缓存,后续的请求可能会重复使用之前分配给同一服务器的连接,导致负载分布出现偏差。这种偏差不是由轮询算法本身引起的,而是由连接复用的局部性导致的。为了缓解这一问题,可以结合 least_conn 或其他更复杂的负载均衡算法,或者调整 keepalive 的大小以适应流量模式。

# 对比:不使用 keepalive 的情况
upstream backend_no_keepalive {
server 192.168.1.10:80;
server 192.168.1.11:80;
}
server {
location / {
proxy_pass http://backend_no_keepalive;
# 默认使用 HTTP/1.0,每次请求新建连接
}
}
在没有 keepalive 的情况下,每个请求都会创建一个新的 TCP 连接到上游服务器,Nginx 严格按照轮询顺序将请求分发给 192.168.1.10 和 192.168.1.11。而在启用 keepalive 后,如果第一个请求建立了与 192.168.1.10 的连接并被缓存,接下来的几个请求很可能继续使用这个连接,即使轮询算法本应将其分发给 192.168.1.11。这种行为在高并发场景下可能导致某些上游服务器负载过高,而其他服务器连接闲置。
连接池满或连接失效时的回退行为
当 keepalive 连接池已满或所有缓存的连接都不可用时,Nginx 会自动回退到新建连接的行为。具体来说,如果当前空闲连接数达到 keepalive 设定的上限,新的空闲连接将被丢弃;如果缓存的连接因超时、错误或被上游服务器关闭而失效,Nginx 会忽略这些无效连接并创建新的连接。这种回退机制确保了服务的可用性,但可能会暂时增加延迟和 CPU 开销。

# 监控连接状态的示例命令
# 在 Nginx 中启用 stub_status 模块
location /nginx_status {
stub_status;
}
通过访问 /nginx_status 端点,可以查看当前的活动连接数和空闲连接数。如果观察到空闲连接数长期为 0,说明 keepalive 池可能过小或连接复用率不高。此时可以增加 keepalive 的值,例如从 32 增加到 64 或更高,以容纳更多的并发连接。同时,检查上游服务器的 keepalive_timeout 设置,确保其与 Nginx 的配置相匹配,避免因超时不一致导致连接提前关闭。











