配置Nginx 的 Keepalive 提升每秒查询率(QPS)

Nginx 的 Keepalive 功能通过复用已经建立的 TCP 连接来处理多个 HTTP 请求,避免了为每个请求都重新建立连接的巨大开销,从而显著提升了每秒查询率(QPS)。

其性能提升主要源于避免了以下两个耗时的过程:

  1. 避免 TCP 三次握手

    • 没有 Keepalive:每个 HTTP 请求都需要经历一次完整的 TCP 三次握手(SYN, SYN-ACK, ACK),这会引入至少一个网络往返时间(RTT)的延迟。
    • 启用 Keepalive:在第一个请求完成后,TCP 连接会保持打开状态。后续的请求可以直接复用这个"空闲"的连接,省去了重复的握手过程。
  2. 避免 TLS 握手(针对 HTTPS)

    • 如果服务是 HTTPS,每次新建 TCP 连接后还需要进行一次昂贵的 TLS 握手,这个过程涉及复杂的加密计算,会消耗大量的 CPU 资源。
    • 启用 Keepalive 后,TLS 会话也可以被复用,极大地降低了 CPU 负载和请求延迟。

简单来说,Keepalive 将"建立连接 → 发送请求 → 关闭连接 "的模式,变成了"建立连接 → 发送多个请求 → 关闭连接",大大减少了系统资源的消耗和请求的等待时间。

🔧 Nginx Keepalive 详解与配置

Nginx 的 Keepalive 配置分为两部分:客户端到 NginxNginx 到后端服务器(Upstream)

1. 客户端 ↔ Nginx 的长连接

这部分控制 Nginx 如何处理来自浏览器等客户端的连接。

  • keepalive_timeout : 定义 Nginx 与客户端的空闲连接保持打开的时长。
    • 示例 : keepalive_timeout 65; (保持65秒)
  • keepalive_requests : 定义在一个长连接上最多可以处理多少个请求,超过后连接会被关闭。这可以防止单个连接占用资源过久。
    • 示例 : keepalive_requests 1000;

配置位置 : 通常放在 http 块中。

复制代码
http {
   # ... 其他配置 ...
    keepalive_timeout 65;
    keepalive_requests 1000;
}
2. Nginx ↔ 后端服务器 (Upstream) 的长连接

这部分是提升 QPS 的关键,它控制 Nginx 作为反向代理时,如何与后端的 Java、Python、Go 等应用服务器复用连接。

  • keepalive : 在 upstream 块中定义,表示 Nginx 为每个工作进程保留的、与后端服务器的空闲连接池大小。
    • 示例 : keepalive 32; (建议从 16-64 开始调优)
  • proxy_http_version : 在 location 块中,必须设置为 1.1,因为 HTTP/1.1 默认支持长连接。
    • 示例 : proxy_http_version 1.1;
  • proxy_set_header Connection "" : 这是最关键的一步!它的作用是清空请求头中的 Connection 字段。如果不设置,Nginx 可能会将客户端的 Connection: close 头传递给后端,导致后端在处理完一个请求后就关闭连接,使得 keepalive 配置失效。

配置位置 : upstream 块和 location 块协同配置。

复制代码
# 定义后端服务器组
upstream my_backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
    keepalive 32; # 启用长连接池,大小为32
}

server {
    listen 80;

    location / {
        proxy_pass http://my_backend;
        
        # 启用 upstream keepalive 的关键配置
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        
        # 其他代理配置...
        proxy_set_header Host $host;
    }
}

TCP 连接的唯一性

一个 TCP 连接是由一个唯一的"四元组"来标识的:

  • 源 IP 地址 (Source IP)
  • 源端口号 (Source Port)
  • 目标 IP 地址 (Destination IP)
  • 目标端口号 (Destination Port)

只要这四个值中任何一个不同,就代表一个全新的、独立的 TCP 连接。

当两个不同的客户端(例如,两个不同的浏览器,或者两台不同的电脑)访问同一个 Nginx 服务器时,它们的源 IP 地址必然是不同的。因此,它们与 Nginx 建立的 TCP 连接从一开始就是两个完全独立的连接,物理上就不可能复用。

一个形象的比喻

您可以将 Nginx 服务器想象成一个餐厅,而 TCP 连接就是餐桌。

  • Keepalive (长连接) :指的是同一位客人(同一个客户端) 在吃完一道菜(完成一个HTTP请求)后,不必离开餐厅,可以坐在**同一张餐桌(同一个TCP连接)**上继续点下一道菜。这节省了重新找位、带位的时间。
  • 不同客户端 :指的是两位不同的客人(两个不同的客户端)。他们不可能也不应该坐在同一张餐桌上吃饭。餐厅(Nginx)会为每一位新来的客人提供一张新的、独立的餐桌(建立一个新的TCP连接)。

所以,Keepalive 优化的是"一位客人"的用餐体验,而不是让"所有客人"挤在一张桌子上。

Nginx 的实际工作机制

Nginx 作为高性能服务器,其核心能力之一就是高并发处理。它会为每一个 incoming 的客户端连接创建一个独立的上下文来处理请求。

  1. 客户端 A 向 Nginx 发起请求,Nginx 接受后,会建立一个 TCP 连接(我们称之为 连接A)。
  2. 客户端 B 也向 Nginx 发起请求,Nginx 会接受并建立另一个全新的 TCP 连接(我们称之为 连接B)。
  3. 如果客户端 A 启用了 Keepalive,那么它在短时间内发起的第二个、第三个请求,会继续使用 连接A
  4. 同样,客户端 B 的后续请求也会复用 连接B

连接A连接B 在 Nginx 内部是完全隔离的,它们的数据流、状态和生命周期都互不干扰。

Nginx 反向代理Upstream Keepalive

  • 客户端 → Nginx :这个阶段,连接是一对一的,不同客户端的连接绝对不能复用。
  • Nginx → 后端服务器 (Upstream) :这个阶段,Nginx 会维护一个连接池 。为了高效地与后端应用服务器(如 Tomcat, Gunicorn)通信,Nginx 会预先建立一批长连接放在池子里。
    • 来自客户端A 的请求,经过 Nginx 处理后,可能会通过连接池中的 连接1 转发给后端。
    • 紧接着,来自客户端B 的请求,也可能会通过连接池中的 连接1 转发给后端。

在这种情况下,是 Nginx 在复用它与后端服务器之间的连接 ,来服务不同的客户端。但请注意,对于客户端来说,它们各自与 Nginx 的连接依然是独立的。这个复用过程对客户端是完全透明的。

特性 Nginx Keepalive (长连接)
作用层面 网络层 (TCP 连接)
核心目的 复用 TCP 连接,减少网络握手开销
解决的问题 提升 QPS,降低网络延迟
必要性 必要。优化所有 HTTP 请求的基础设施。
相关推荐
吴文周11 分钟前
告别重复劳动:一套插件让 AI 替你写代码、修Bug、做测试、上生产
前端·后端·ai编程
Mh37 分钟前
我决定写一个 3D 地球仪来记录下我要去的地方
前端·javascript·动效
yaoxin5211231 小时前
390. Java IO API - WatchDir 示例
java·前端·python
懒狗小前端1 小时前
做了一个 codex 的中文文档网站,做的不好可以随便喷
前端·后端
. . . . .2 小时前
ref、useRef 和 forwardRef
前端·javascript·react.js
energy_DT2 小时前
2026年海上钻井平台数字孪生平台:引领海洋能源数字化转型
前端
Eric_见嘉3 小时前
在职前端 Agent 配置分享
前端·后端·agent
柚子8163 小时前
break跳出语句块的神奇技巧
前端·javascript
ejinxian4 小时前
Rust GUI框架Azul与Electron、WebView2
前端·javascript·electron
IT_陈寒5 小时前
Vue的v-for里用index当key,我被自己坑惨了
前端·人工智能·后端