运维 关于 机器 TIME_WAIT 过多的问题的请教

jicheng1014 · March 18, 2019 · Last by jicheng1014 replied at March 19, 2019 · 6635 hits

正在跑一个 puma 进程,主要是根据业务进行 302 跳转

puma 我使用的是 workers 的方式 使用常规配置 workers threads 2,16

本身跑的速度还行,newrelic 的数据 action 响应在 10ms 以内,rpm 4k 上下

但是发现机器里大概几千个 TIME_WAIT , 感觉这跟 established 差的也太远了吧

  67 ESTABLISHED
   7 LISTEN
2187 TIME_WAIT

跟着网上说的调整了下内核参数,稍微调整了下,发现没有什么变化

net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_fin_timeout=30
# 内核不支持修改 tcp_tw_recycle 

回头看 nginx 日志里的 request_time,好像也都比较正常

查了下资料 发现其实我这个量还比较小,端口号够用就行

那么到底我是否该关注这个指标呢?

如果需要关注,那么如何解决这个问题呢?

主要都是 puma 端口上的 TIME_WAIT

tcp        0      0 172.16.0.13:3001        172.16.0.13:58594       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:34790       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:57166       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:34378       TIME_WAIT
tcp        0      0 172.16.0.13:46242       172.16.0.12:3000        TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:60220       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:32940       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:59416       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:57810       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:35356       TIME_WAIT
tcp        0      0 172.16.0.13:33226       172.16.0.13:3001        TIME_WAIT
tcp        0      0 172.16.0.13:443         223.104.94.24:53306     TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:35066       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:58744       TIME_WAIT
tcp        0      0 172.16.0.13:46138       172.16.0.12:3000        TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:60702       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:35518       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:60944       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:57132       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:60464       TIME_WAIT
tcp        0      0 172.16.0.13:47050       172.16.0.12:3000        TIME_WAIT
tcp        0      0 172.16.0.13:443         117.136.63.83:14588     TIME_WAIT
tcp        0      0 172.16.0.13:50070       172.16.0.12:3000        TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:34458       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:33596       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:35192       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:60730       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:59854       TIME_WAIT
tcp        0      0 172.16.0.13:3001        172.16.0.13:59854       TIME_WAIT

看这个 TIME_WAIT 是 nginx 和 puma 之间的连接,试试设置 nginx upstream keepalive 应该能解决这个问题。

这个开过,开过常用的 16 和 500 没有什么明显的效果似乎

把 Nginx 配置贴上来看看?

upstream api_production {
  server 172.16.0.13:3001 fail_timeout=0;
  server 172.16.0.12:3001 fail_timeout=0;
  keepalive 500;
}

server {
  listen 80;

  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "Upgrade";
  proxy_set_header X-Forwarded-Proto http;

  listen 443 ssl;
  ssl_certificate         /root/.acme.sh/fullchain.cer;
  ssl_certificate_key     /root/.acme.sh/key;
  add_header Strict-Transport-Security "max-age=31536000";


  root /var/www/api/current/public;
  try_files $uri/index.html $uri;

location /api {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_redirect off;

    proxy_pass http://api_production;

  }

  location / {
    rewrite ^/(.*)$ /api/$1 last;
    proxy_pass  http://api_production;
  }

你在 location 里面添加这 2 个试试看,具体说明请参考 nginx 的文档:

proxy_http_version 1.1;
proxy_set_header Connection "";

两千多个挺正常的,你 nginx 和 puma 是跑在同一台机器上的,nginx 每次转发请求实际上都会创建新的 TCP 连接,连接没有被复用后面就 timewait 了。如果并发量高的话确实会出问题,upstream 就会连不上,sourceIP:Port -> DesIp:Port 耗尽了。

一般有几个解决方案:

  • 把可用随机端口调大 net.ipv4.ip_local_port_range
  • 后端多搞几个 upstream
  • Nginx 在 upstream 中用长连接
  • 开 tcp_tw_reuse 和时间戳 并且限制 timewait 的总数量,当触发上限时就会剔除旧的
  • nginx 和 puma 在同一台机器上时可以用 unix socket 避开 tcp 协议栈
Reply to early

有两台机器实际上,A 和 B 都有 Puma, A 有 nginx

A 的 nginx 的 upstream 分别到 A 和 B 的 PUMA 上

我也觉得 2000 多还好,

local_port 不改也有 2w-3w, 目前肯定是够用

主要还是怂

因为这个项目的业务逻辑关系,流量特别不稳定,经常瞬发 10x 平日流量,我怕到瓶颈再想办法就比较麻烦了

其实我觉得开一下 tcp_tw_reuse 应该问题不是太大,就算占满了都有解

总之 感谢 @early @quakewang

You need to Sign in before reply, if you don't have an account, please Sign up first.