如何解决大量HTTP请求引发的CLOSE_WAIT连接堆积问题?
嗨,碰到CLOSE_WAIT堆积这种问题确实挺闹心的,尤其是你这儿上千个Python脚本同时跑,每个都在打8088端口的请求。先给你理清楚:CLOSE_WAIT状态本质是客户端这边没主动关闭TCP连接——服务器已经发了关闭请求(FIN包),但客户端进程还没调用close()释放连接,导致连接一直挂在那儿。结合你的场景,咱们从几个层面来解决:
一、优化Python Requests的连接使用方式
你的脚本里直接用requests.get(),默认情况下requests会用urllib3的连接池,但如果每个脚本跑完就退出,或者没正确处理响应,连接就容易留在CLOSE_WAIT状态。试试这几个调整:
1. 使用Session对象复用连接
单个脚本里用requests.Session()代替直接调用requests.get(),Session会自动复用TCP连接,减少频繁创建/关闭连接的次数,从根源减少CLOSE_WAIT的产生。修改你的脚本示例:
import socket import requests def get_yarn_details(state='RUNNING'): state_suffix = '' if state == '' else "?states=" + state yarn_apps = "http://{0}:8088/ws/v1/cluster/apps" + state_suffix local_fqdn = socket.getfqdn(socket.gethostname()) yarn_apps_url = yarn_apps.format(local_fqdn) # 使用Session复用连接 with requests.Session() as session: try: with session.get(yarn_apps_url) as response: response.raise_for_status() apps = response.json().get('apps', {}).get('app', []) for app in apps: print(app['id']) except requests.exceptions.RequestException as e: print(f"Error fetching YARN details: {e}") # Example usage get_yarn_details()
这里用了两层with:Session的with会自动关闭会话,get的with会自动关闭响应连接,确保连接被正确释放。
2. 显式设置连接超时
给请求加上超时时间,避免请求卡住导致连接长期占用:
# 在get请求里加timeout参数,比如5秒超时 with session.get(yarn_apps_url, timeout=5) as response:
二、减少脚本的并发数量
你现在是上千个独立脚本在跑,每个脚本启动后创建新的进程,每个进程的连接池是独立的,根本没法复用连接,反而会产生大量一次性连接。试试这些优化:
- 批量请求合并:把多个脚本的逻辑整合到一个脚本里,用多线程/多进程批量处理请求,而不是每个请求启动一个独立脚本。
- 改用定时任务调度:比如用cron或者Celery来集中调度请求,减少同时运行的进程数,让连接池能真正发挥复用作用。
三、调整RHEL系统的TCP参数
如果上面的应用层优化还不够,咱们从系统层面加快CLOSE_WAIT连接的回收:
1. 缩短CLOSE_WAIT的超时时间
默认情况下,Linux的tcp_fin_timeout是60秒,也就是CLOSE_WAIT状态的连接会保留60秒才回收。咱们把它调小,比如15秒:
# 临时生效 sysctl -w net.ipv4.tcp_fin_timeout=15 # 永久生效,写入/etc/sysctl.conf文件 echo "net.ipv4.tcp_fin_timeout=15" >> /etc/sysctl.conf sysctl -p
2. 开启连接复用参数
开启tcp_tw_reuse和tcp_tw_recycle(注意:如果你的机器在NAT网络环境下,tcp_tw_recycle可能会导致连接异常,谨慎开启):
# 临时生效 sysctl -w net.ipv4.tcp_tw_reuse=1 sysctl -w net.ipv4.tcp_tw_recycle=1 # 永久生效 echo "net.ipv4.tcp_tw_reuse=1" >> /etc/sysctl.conf echo "net.ipv4.tcp_tw_recycle=1" >> /etc/sysctl.conf sysctl -p
3. 调整最大TIME_WAIT连接数
如果连接堆积严重,可以适当增大tcp_max_tw_buckets的值,避免系统因为连接数过多拒绝新请求:
sysctl -w net.ipv4.tcp_max_tw_buckets=65536 echo "net.ipv4.tcp_max_tw_buckets=65536" >> /etc/sysctl.conf sysctl -p
四、检查YARN ResourceManager的配置
偶尔也可能是服务器端的问题:比如RM的HTTP服务设置了过短的连接超时,主动关闭了连接,但客户端没及时响应。可以检查RM的yarn.resourcemanager.webapp.address相关配置,看看是否有异常的超时设置,或者是否有连接泄漏的情况。
先从应用层的优化入手(用Session、合并脚本),这是最根本的解决办法,系统参数调优作为辅助。按这个步骤来,应该能大幅减少CLOSE_WAIT的数量。
备注:内容来源于stack exchange,提问作者jessica




