Nginx 性能调优:HTTP 处理和配置

12 分钟阅读 - 2026年5月26日

hero section cover
目录
  • Nginx HTTP 处理流程:配置调优
  • Nginx 如何处理 HTTP 请求
  • 工作进程与连接
  • 超时与保持活动
  • 缓冲区大小
  • 负载均衡与上游保持活动
  • 测试与监控
分享

调整 Nginx 工作进程、缓冲区、keepalive 和负载平衡,以便在单个服务器上每秒处理 50,000 多个请求。

Nginx HTTP 处理流程:配置调优

Nginx 的默认配置侧重兼容性而非性能。通过适当调优,单台服务器每秒可处理 50,000 至 80,000 次请求。本指南涵盖了最重要的设置:工作进程、连接、保持活动、缓冲、负载均衡,以及如何通过基准测试验证您的更改。

Nginx 如何处理 HTTP 请求

Nginx 通过不同的阶段处理请求,每个阶段都会消耗系统资源。了解这一流程有助于您针对性地调整设置。

该流程始于内核层。传入的连接进入 SYN 和 ACCEPT 队列,由 Nginx 工作进程进行处理。一旦接受连接,工作进程便会从内核缓冲区解析 HTTP 请求。对于 TLS 流量,此步骤将消耗更多 CPU 资源。

接下来,Nginx 会根据 Host 头部以及 IP/端口组合将请求匹配到虚拟服务器,然后通过前缀或正则表达式匹配将 URI 解析为 location 块。

对于动态内容,Nginx 将请求转发至后端(FastCGI、代理)。这一上游通信阶段极大受益于持久连接。若无上游 keepalive 机制,Nginx 将为每个请求建立新的 TCP 连接,从而增加延迟和 CPU 开销。

如果 proxy_buffering 启用该功能,Nginx 会在将响应交付给客户端之前,将完整的上游响应读入内存。这使得工作进程能够立即处理新的请求。最后,在输出交付过程中,启用 sendfile 可实现零拷贝传输,从而将吞吐量从约 6 Gbps 提升至 30 Gbps。

每个阶段都会消耗内存缓冲区、文件描述符和 CPU 周期。以下各节将针对每个瓶颈进行优化。

工作进程与连接

请从 worker_processes auto; 。这将使工作进程数与您的 CPU 核心数匹配。在核心数有限的 VPS 上,请手动设置该数值(例如 worker_processes 2;)。若工作负载对内存需求较高,请考虑减少工作进程数量,以避免内存超额分配。

启用 worker_cpu_affinity auto; 以将每个 worker 绑定到特定核心。这可减少缓存未命中和上下文切换。自 Nginx 1.9.10 起可用。

连接限制

worker_connections 指令用于设置每个 worker 可处理的并发连接数。总容量为 worker_processes × worker_connections。默认值 512 或 1,024 对于生产环境而言过低。对于高流量网站,应将每个 worker 的值设置为 2,048 或 4,096。

每个连接至少需要一个文件描述符。在反向代理配置中,每个连接会占用两个(一个用于客户端,一个用于上游)。将 worker_rlimit_nofile 的值至少为 worker_connections 值,并预留余量。对于 worker_connections 4096;,请使用 worker_rlimit_nofile 10000; 或更高版本。

在系统层面,将 fs.file-max 的值 /etc/sysctl.conf 至至少 500,000,并将 systemd 的 LimitNOFILE=65535.

最后,在 multi_accept on; ,以便 worker 进程能一次性接受所有待处理连接,而非逐个处理。

超时与保持活动

客户端保持活动

keepalive_timeout 指令控制闲置客户端连接保持打开的时间。对于高流量服务器,30 到 65 秒的效果很好。请使用双参数形式:

keepalive_timeout 65s 60s;

第一个值是服务器端的超时时间。第二个值用于向客户端发送 Keep-Alive: timeout=60 标头。将客户端超时值设置得略低,可避免浏览器试图复用 Nginx 已关闭的连接所导致的竞争条件。

keepalive_requests 指令限制单个连接在关闭前处理的请求数量。默认值为 1,000(在 1.19.10 版本中从 100 提高)。对于稳定的后端,可将此值提高到 10,000 以减少连接波动。

代理超时

proxy_connect_timeout 用于设置 Nginx 等待与后端建立连接的时间。默认值为 60 秒。若需快速故障转移,请将其缩短至 5 至 10 秒。

proxy_read_timeout 定义 Nginx 在连续从上游读取数据之间等待的时间。请将其与后端的执行超时时间保持一致。如果 PHP-FPM 的 request_terminate_timeout 为 120 秒,请将 proxy_read_timeout 该值至少设为120秒,以避免过早触发504错误。

proxy_send_timeout 控制向上游连续写入之间的间隔。默认值 60 秒通常足够,除非您发送的是大型请求主体。

通常, proxy_connect_timeout 应始终是这三者中最短的。

缓冲区大小

client_body_buffer_size 控制 Nginx 在内存中保留多少传入请求正文的数据。默认值 8k 或 16k 可处理简单的表单提交,但文件上传会溢出到磁盘。对于中小型上传,请将其增加到 128k。如果用户上传较大文件,请将 client_max_body_size 若用户上传大文件,请将该值从默认的 1M 调高。

proxy_buffer_size 该参数将响应头与响应主体分开处理。默认值 4k 或 8k 通常适用,但使用大型 Set-Cookie (常见于电子商务)可能会超出此限制,导致 502 错误。请测量实际的头部大小:

curl -s -w '%{size_header}' -o /dev/null http://your-upstream-url

将其向上取整至最接近的 4k 增量。

proxy_buffers 用于设置响应正文缓冲区的数量和大小。默认值(8 个 4k 或 8k 的缓冲区,总计 32k 至 64k)无法容纳大型 JSON 响应。请测量您最大的典型响应大小, curl ,并配置足够的缓冲区以将其完全保存在内存中。

代理缓冲行为

proxy_buffering on (默认值),Nginx 会在将响应发送给客户端之前,将完整的上游响应读入内存。这使得后端服务器能够立即处理新的请求。

proxy_busy_buffers_size 为至少 proxy_buffer_size 加上一个缓冲区,但小于您的总缓冲区池。对于 proxy_buffers 8 16k (总计 128k),请将 proxy_busy_buffers_size 小于 112k。

对于服务器发送事件(SSE)或长轮询等实时端点,请通过 proxy_buffering off 在特定位置的代码块中禁用缓冲。请有选择地将此设置应用于 /stream/events 路径上,而非全局应用。

负载均衡与上游保持活动

默认情况下,Nginx 会为每个代理请求建立新的 TCP 连接。每次握手都会增加 10 到 100 毫秒的延迟,而 TLS 还会额外增加 10 到 50 毫秒。上游保持活动功能通过维护一组持久连接来消除这种开销。

需要配置以下三项设置:

upstream backend {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    keepalive 128;
}
 
server {
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

keepalive 参数用于设定每个 worker 的最大空闲连接数。计算最佳连接池大小公式如下: (workers × target concurrency) / upstream nodes.

将上游 keepalive_timeout 设置为 60 到 120 秒,以匹配后端设置并应对流量峰值。

负载均衡策略

Nginx 支持多种负载均衡方法。轮询(默认)按顺序分配请求。 least_conn 将请求路由至活动连接最少的服务器,这适用于请求持续时间不固定的负载。 ip_hash 通过将同一客户端 IP 路由到同一后端,提供会话保持功能。

当服务器容量不同时,请使用 weight 参数:

upstream backend {
    least_conn;
    server 10.0.1.10:8080 weight=3;
    server 10.0.1.11:8080;
    server 10.0.1.12:8080 backup;
    keepalive 128;
}

加权服务器接收三倍的流量。 backup 仅当所有主服务器均不可用时,该服务器才会激活。配置 max_failsfail_timeout 用于被动健康检查,并使用 max_conns 来限制每个后端的服务器的并发连接数。

测试与监控

在进行任何更改之前,务必先测量基准性能。每次更改后,请重新进行基准测试。每次仅进行一项更改。

在重新加载前,请使用 nginx -t 进行验证。请在独立机器上运行基准测试,以避免资源竞争。

wrk 是 HTTP 负载测试的标准工具:

wrk -t4 -c200 -d30s http://your-server.com/

跟踪每秒请求数、平均延迟、最大延迟和传输速率。Apache Bench 适用于更简单的测试:

ab -n 50000 -c 40 http://your-server.com/

持续监控

启用 stub_status 模块,通过 curl http://localhost/nginx_status.

在日志格式中添加计时变量,以识别延迟发生的位置:

  • $request_time 用于记录总请求时长
  • $upstream_connect_time 用于后端连接时间
  • $upstream_response_time 用于后端总处理时间

检查错误日志以排查缓冲区问题 journalctl -u nginx --no-pager | grep "temporary file"。如果响应涉及磁盘读写,说明您的 proxy_buffers 缓冲区过小。查找“打开的文件过多”错误,这表明 worker_rlimit_nofile 需要增加。

通过缓冲日志记录减少日志 I/O:

access_log /var/log/nginx/access.log combined buffer=64k flush=5s;

ss -tn state established dst [backend_ip] 在负载测试中验证连接是否被复用,且未在 TIME_WAIT 状态中堆积。

关于针对高性能工作负载进行优化的专用服务器和VPS托管,请参阅FDC服务器

博客

本周特色

更多文章
为什么必须拥有功能强大且不计量的 VPS

为什么必须拥有功能强大且不计量的 VPS

需要可靠的性能和无限的流量?功能强大的非计量 VPS 可提供您所需的速度、可扩展性和带宽,而无需担心使用限制。

3 分钟阅读 - 2025年5月9日

如何优化 Linux 上的存储空间

15 分钟阅读 - 2026年5月22日

更多文章