Nginx优化-服务响应时间长排查及优化

前言

建立一个连接如下几个阶段

image-20251117125555646

连接阶段

  • 资源计划(这个阶段时间长,一般是前端代码导致访问阻塞了)
  • 连接开始(这个要查看DNS配置和Nginx相关配置)
  • 请求响应(这个要查看Nginx和后端服务的问题)

如图 初始连接的时间特别长 可能原因如下

层面 具体原因
Nginx 自身配置 1. 未启用 TCP 长连接(Keep-Alive),每次请求都重建 TCP 连接;
2. 工作进程(worker_processes)或连接数(worker_connections)不足;
3. 启用了不必要的模块(如 gzip、ssl_session_cache 未配置);
4. DNS 解析慢(Nginx 转发时用域名指向后端,未配置 DNS 缓存)。
后端服务层面 1. 后端服务启动后初始化慢(加载缓存、连接池耗时);
2. 后端服务连接池满(如 Tomcat maxConnections 耗尽),拒绝新连接;
3. 后端服务健康检查失败,Nginx 反复重试无效节点。
网络层面 1. 客户端→Nginx 或 Nginx→后端的网络路由跳转多、延迟高;
2. 防火墙 / 安全组拦截,导致 TCP 握手超时重试;
3. SSL/TLS 握手耗时久(未启用 TLS 复用、未配置会话缓存)。
其他 Nginx 日志输出阻塞(如同步写日志到远程服务器)、系统资源不足(CPU / 内存占用高)。

排查连接长原因

先排查两个连接的时长

测试 客户端→Nginx 的连接耗时

本地测试连接服务器

1
curl -o /dev/null -s -w "TCP Connect Time: %{time_connect}s\n" https://api2.xhkjedu.com/

测试 Nginx→后端服务 的连接耗时

Nginx所在服务器上测试连接后端

1
curl -o /dev/null -s -w "TCP Connect Time: %{time_connect}s\n" http://192.168.1.12:3000

优化

排查域名映射

在阿里云或其他DNS解析上,查看二级域名解析的IP是不是唯一的,我这最终排查到的竟然是添加了两个解析记录导致的,按理说应该是添加不上的。

启用TCP长连接

启用 TCP 长连接,避免重复握手

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 1. 启用Nginx→后端服务的长连接(关键!)
upstream backend_api2 {
server 192.168.1.12:3000; # 后端服务IP:端口(优先用IP,避免DNS解析)
keepalive 32; # 每个Nginx工作进程与后端保持32个长连接
keepalive_timeout 180s; # Nginx→后端长连接超时时间
}

server {
listen 80;
server_name your_domain.com;

location / {
proxy_pass http://backend_api2;

# 2. 优化客户端→Nginx的长连接(默认已开,调整参数)
keepalive_timeout 60s; # 长连接超时时间(客户端无请求60秒断开)(推荐60-90s)
keepalive_requests 500; # 单个长连接最大请求数(推荐100-500)(避免连接老化)
keepalive_disable msie6; # 禁用老旧浏览器的长连接

# 3. 必须配置以下参数,才能启用后端长连接
proxy_http_version 1.1; # 长连接依赖HTTP/1.1(默认是1.0,不支持)
proxy_set_header Connection ""; # 清空客户端的Connection头,避免后端关闭连接
proxy_connect_timeout 8s; # 连接超时设为8秒,避免无限等待
}
}

必须在server下的配置

1
2
client_header_timeout 10s;    # 接收请求头超时(推荐5-10s)
client_body_timeout 15s; # 接收请求体超时(推荐10-15s)

location下配置

1
2
3
4
5
6
7
8
# 浏览器-Nginx的长连接
keepalive_timeout 90s; # 长连接空闲超时(推荐60-90s)
keepalive_requests 200; # 单个长连接最大请求数(推荐100-500)

# Nginx-后端的长连接
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_connect_timeout 8s; # 连接超时设为8秒,避免无限等待

前两个是浏览器和Nginx连接的参数

  1. 超时时间(keepalive_timeout)越长越好?

    不是!设为 120 秒以上会导致 Nginx 占用大量空闲连接,服务器资源浪费,60-90 秒是兼顾 “复用效果” 和 “资源占用” 的最优区间。

  2. 请求数(keepalive_requests)越多越好?

    不是!超过 500 次后,长连接的稳定性可能下降(比如内存泄漏风险),除非有实际压测数据支撑,否则不建议盲目调大。

Nginx连接数优化

根据服务器 CPU 核心数调整,确保 Nginx 能处理足够的并发连接:

查看Nginx配置连接数

1
grep -r "worker_connections" /etc/nginx/

查看实际使用的连接数

1
2
3
4
5
# 统计 80/443 端口各状态连接数(用 ss,推荐)
ss -tan | grep -E ":80|:443" | awk '{print $1}' | sort | uniq -c

# 若用 netstat
netstat -tan | grep -E ":80|:443" | awk '{print $6}' | sort | uniq -c

输出示例

1
2
3
4
256 ESTABLISHED  # 已建立的有效连接(正在处理请求)
32 TIME_WAIT # 连接已关闭,等待回收(正常状态)
4 SYN_RECV # 正在握手(若过多可能是SYN洪水攻击)
1 LISTEN # Nginx 监听端口的状态

优化 SSL(若启用 HTTPS)

1
2
3
4
5
6
7
8
9
10
server {
listen 443 ssl;
ssl_certificate /etc/nginx/cert/xhkjedu.pem;
ssl_certificate_key /etc/nginx/cert/xhkjedu.key;

ssl_protocols TLSv1.2 TLSv1.3; # 禁用老旧TLS版本
ssl_prefer_server_ciphers on; # 优先使用服务器端加密套件
ssl_session_cache shared:SSL:10m; # 共享SSL会话缓存(10MB,约缓存1万+会话)
ssl_session_timeout 1d; # SSL会话超时1天(复用会话,避免重复握手)
}

DNS解析优化

如果 upstream 中用域名(如server backend.service.com:8080),Nginx 默认每次转发都会重新解析 DNS,导致延迟。

注意

如果upstream中使用的是IP,则不用考虑这个配置。

解决方案:

  • 优先改用后端服务 IP(彻底避免 DNS 解析)。
  • 若必须用域名,配置 Nginx DNS 缓存。

Nginx

1
2
3
4
http {
resolver 223.5.5.5 223.6.6.6 valid=300s; # DNS服务器+缓存5分钟
resolver_timeout 5s; # DNS解析超时时间(避免阻塞)
}