Nginx keepalive 详解:作用、原理与配置指南 – wiki基地

Nginx Keepalive 详解:作用、原理与配置指南

Nginx 作为高性能的 Web 服务器和反向代理,其性能优化是许多系统管理员和开发者关注的重点。在 Nginx 的众多优化机制中,keepalive 连接是一个至关重要的特性,它能够显著减少网络延迟、提高资源利用率和整体吞吐量。本文将深入探讨 Nginx keepalive 的作用、工作原理以及详细的配置方法。

1. Nginx Keepalive 的作用

keepalive 连接(也称为持久连接或长连接)是指客户端和服务器之间在完成一次请求-响应周期后不立即关闭 TCP 连接,而是保持连接打开状态,以便在后续的请求中复用该连接。对于 Nginx 而言,keepalive 主要体现在以下两个层面:

  1. 客户端到 Nginx 的 keepalive (HTTP Keepalive)

    • 减少 TCP 握手开销: 每次建立新的 TCP 连接都需要经过三次握手,这会增加延迟和服务器的资源消耗。keepalive 允许在同一连接上发送多个 HTTP 请求,避免了重复的握手过程。
    • 减少慢启动(Slow Start)的影响: TCP 的慢启动机制在连接建立初期会限制数据传输速率。keepalive 连接的持续存在使得连接能够更快地达到其最大传输速率。
    • 提高请求响应速度: 客户端无需等待新的 TCP 连接建立即可发送下一个请求,显著缩短了整体的请求响应时间。
    • 降低服务器资源消耗: 尽管连接保持开放,但服务器无需频繁创建和销毁连接,减少了 CPU 和内存的开销。
  2. Nginx 到上游服务器的 keepalive (Backend Keepalive)

    • 当 Nginx 作为反向代理时,它不仅与客户端建立连接,还会与后端的应用服务器(如 Tomcat, Node.js 应用等)建立连接。在这种场景下,Nginx 也可以通过 keepalive 机制与后端服务器保持持久连接。
    • 减轻后端服务器压力: 类似于客户端到 Nginx 的情况,后端服务器也无需频繁处理 TCP 握手和连接关闭,降低了其资源消耗。
    • 提高代理转发效率: Nginx 向后端转发请求时,可以直接复用已有的连接,减少了延迟,提高了数据传输效率。
    • 优化连接池管理: Nginx 内部维护一个与后端服务器的 keepalive 连接池,智能地管理和复用这些连接。

2. Nginx Keepalive 的原理

keepalive 连接的核心原理是利用 HTTP/1.1 协议的特性。在 HTTP/1.1 中,默认所有连接都是 keepalive 的,除非请求头中明确指定 Connection: close

工作流程简述:

  1. 客户端到 Nginx:

    • 客户端发起第一个 HTTP 请求,并在请求头中带上 Connection: keep-alive (HTTP/1.1 默认行为)。
    • Nginx 接收请求并处理,在响应头中也带上 Connection: keep-alive
    • 客户端收到响应后,不关闭 TCP 连接,而是等待一定时间内是否需要发送下一个请求。
    • 如果客户端在指定时间内发送了新请求,Nginx 会复用现有连接进行处理。
    • 如果客户端在指定时间内没有发送新请求,或者请求次数达到上限,Nginx 会主动关闭连接。
  2. Nginx 到上游服务器:

    • 当 Nginx 收到客户端请求需要转发到后端时,Nginx 会检查其与后端服务器的 keepalive 连接池。
    • 如果连接池中有可用的空闲连接,Nginx 会直接复用该连接将请求转发给后端。
    • 如果连接池中没有可用连接,Nginx 会建立新的连接并将其加入连接池。
    • 后端服务器处理请求并返回响应给 Nginx。
    • Nginx 收到后端响应后,将连接标记为空闲,以便后续请求复用。
    • Nginx 会根据配置的超时时间和最大请求数来管理这些后端 keepalive 连接的生命周期。

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
    • 建议: 通常设置为 60s120s。过短会增加连接建立开销,过长会占用过多服务器资源。
  • 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 保留在缓存中。
    • 建议: 这个值不宜设置过大,通常是 32128 之间。过大可能会导致后端服务器连接数过多而无法处理新连接。需要注意的是,这个 keepalive 是针对每个 worker 进程的,而不是全局的。 如果你有 4 个 worker 进程,那么总共可能会有 4 * connectionskeepalive 连接。
  • 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 到上游服务器的连接开销,降低了后端服务器的压力,提高了代理效率。

重要注意事项:

  1. 平衡资源与性能: keepalive_timeoutkeepalive_requests 的值需要根据你的应用流量模式、客户端行为和服务器资源进行权衡。过长或过多的 keepalive 连接会占用服务器资源,可能导致其他新连接无法建立。
  2. 后端服务器支持: 确保你的后端应用服务器也支持 keepalive 连接。大多数现代 Web 框架和服务器(如 Java Tomcat, Node.js Express, Python Gunicorn/uWSGI 等)都默认支持。
  3. 负载均衡器(LB)与 keepalive 如果你的 Nginx 前面还有一层硬件负载均衡器或云服务 LB,需要确保这些 LB 也配置了适当的 keepalive 策略,以避免它们在 Nginx 期望连接保持时过早关闭连接。
  4. proxy_set_header Connection "" 的重要性: 这一步在反向代理场景中非常关键,它确保 Nginx 能够独立管理与后端服务器的 keepalive 连接,而不受客户端 Connection 头的影响。
  5. 监控与调整: 部署后,密切监控 Nginx 和后端服务器的连接数、CPU、内存使用情况,根据实际性能表现和瓶颈进行调整。

通过精细化配置 Nginx keepalive,你可以为你的 Web 服务构建一个更高效、更稳定的网络层。

滚动至顶部