惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 司徒正美
The GitHub Blog
The GitHub Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Apple Machine Learning Research
Apple Machine Learning Research
L
LangChain Blog
GbyAI
GbyAI
博客园_首页
V
Visual Studio Blog
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园 - 叶小钗
腾讯CDC
博客园 - Franky
IT之家
IT之家
Google DeepMind News
Google DeepMind News
Microsoft Azure Blog
Microsoft Azure Blog
D
Docker
大猫的无限游戏
大猫的无限游戏
Recent Announcements
Recent Announcements
小众软件
小众软件
博客园 - 三生石上(FineUI控件)
B
Blog
酷 壳 – CoolShell
酷 壳 – CoolShell

博客园 - fengjian1585

麒麟linx v10 sp3 cgroup v1 变更为cgroup v2 k8s Gateway API 详解 linux 挂载点覆盖清理原数据 coze 入门学习 手机安装 openclaw 关闭ingress 8443 端口 tomcat 设置 catalina.out 按天切割 Harbor 启用 Trivy 禁用 MinIO 的 Web Console 重定向功能 堆设置了8G,java进程却占用了12G内存 k8s优化选项 pod启动后一直containerCreating状态解决 Kubernetes Cilium网络组件和CoreDNS配置 mkfs对磁盘设置标签 K8S的CoreDns配置文件添加域名解析 nginx代理两套k8s ingress 不同域名 pip 搭建源 使用 kubectl debug 创建临时调试容器 openvpn server证书过期处理 - fengjian1585 Harbor Swagger接口泄露漏洞处理 "too many open files" 文件句柄 Kafka 常见故障及解决方案 华为昇腾 910B GPU debian libc.musl-x86_64.so.1 => not found
Nginx与Upstream之间产生大量TIME_WAIT连接的解决办法
fengjian1585 · 2024-11-20 · via 博客园 - fengjian1585

1. 现象

Nginx反向代理了一个Java服务,QPS大概是200,问题发生时的Nginx配置:

location / {
    proxy_pass http://192.168.3.4:18600;
}

在上游Java服务器上可以观察到大量(约2000个)的TIME_WAIT状态的网络连接

 从Nginx的error日志中还发现与Java服务器建立连接偶发失败的情况:

[error] 9208#0: *32907 connect() failed (111: Connection refused) while connecting to upstream, client: **.**.**.**, server: localhost, request: "POST /api HTTP/1.1", upstream: "http://**.**.**.**:18600/api", host: "**.**.**.**:8080"

2. 原因
由于QPS较高,Nginx与上游Java服务器建立的都是Http短连接,需要不停的创建和关闭TCP连接。而主动关闭TCP连接的一方需要等2MSL之后才会真正释放TCP连接,在2MSL之前连接的状态都是TIME_WAIT。

参考:TIME_WAIT状态产生的原因、过多的危害_爱吃芝麻球的博客-CSDN博客_time_wait连接过多的原因

由于每次上游Java服务在发送完响应报文后主动关闭了连接,所以作为主动关闭连接的一方,当并发量较高时就会产生大量的TIME_WAIT状态的连接。

3. 解决办法
解决的办法就是让Nginx与上游Java服务器之间通过Http 1.1的 Keepalive协议重用TCP连接,减少TCP连接数量
第一步: 修改location模块,添加http 1.1 协议头

location / {
    proxy_pass http://192.168.3.4:18600;
    
    # 添加http 1.1 协议头,这样上游Java服务就会启用keepalive,不会主动关闭TCP连接了
   proxy_http_version 1.1;
   proxy_set_header Connection "";
}

修改nginx配置重新生效后,发现上游Java服务器上的TIME_WAIT连接少了,但是Nginx服务器到上游Java服务器的TIME_WAIT连接却变多了。

原因在于Nginx自身没有复用到上游Java服务器的TCP连接,每次收到完整的响应报文之后就关闭连接了。

而这一次Nginx服务作为主动关闭TCP连接的一方,所以从Nginx服务器上TIME_WAIT的连接变多了。

第二步: 让Nginx主动重用TCP连接
Nginx的upstream模块中也有一个keepalive参数,但是这个参数与http协议中的keepalive参数的意义完全不同,upstream中的keepalive参数表示与上游服务建立的连接可以空闲的最大数量。

即如果在upstream模块中配置了keepalive参数,那么Nginx与上游服务之间建立的TCP连接就有了一个缓冲的池子,不再是用完立即释放了,而是可以有一个缓冲的池子可以放进去。keepalive参数的含义就是这个缓冲池子的最大值
参考:长连接 · Nginx 学习笔记 (gitbooks.io)

所以单独提取出一个upstream模块,并设置keepalive参数

upstream java_server {
    server 192.168.3.4:18600;
    
    # 设置可复用的tcp连接的空闲数量的最大值
    keepalive 50;
}

location / {
    proxy_pass http://java_server;
    
    # 添加http 1.1 协议头,这样上游Java服务就会启用keepalive,不会主动关闭TCP连接了
   proxy_http_version 1.1;
   proxy_set_header Connection "";
}

————————————————

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/weixin_45145848/article/details/128854094