当时忙是旁边小哥遇到处理的,但是最后问题原理 他也没说不明白 问题情形: 一个应用要使用 3006 端口,发现端口已被占用,使用 netstat -atnlp |grep 3006,发现一直 3006 端口的 TIME_WAITE。 是 4 次挥手时,Client 端等待 2ML 时间的等待。 原来是这里的某些服务需要连接另外一台 Redis 服务器,这边 Client 端打开打端口恰好打开了 3006,然后 netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'一查,TIME_WAITE 有 3 万多个,而且持续观察 2 个小时内 3006 端口一直是 TIME_WAITE
处理:旁边小哥先是调了内核参数 net.ipv4.tcp_tw_reuse = 1 net.ipv4.tcp_syncookies = 1 都不行之后,加了一个限制 TIME_WAITE 的参数 net.ipv4.tcp_max_tw_buckets = 1024 ###原默认值很大,具体忘了 ###这里 TIME_WAITE 多于该数值,会被抛弃
我的猜测是,服务器 Client 端这边有大量请求需要主动连接 redis,3006 端口刚 TIME_WAITE 结束又进入新的 TIME_WAITE,而不是“一直” TIME_WAITE
问题: 1.上面描述的这种情形的原理是什么? 2.处理方法( net.ipv4.tcp_max_tw_buckets = 1024 )会有什么坑留下?
1
90928yao 2018-12-18 10:03:58 +08:00
兄弟 出现 time wait,close wait 一般都是自己代码写得有问题 不是内核参数问题
|
2
EchoUtopia 2018-12-18 10:08:03 +08:00 via Android
用连接池吧
|
4
a663 OP @EchoUtopia 代码里面的连接池么?
|
6
liuxu 2018-12-18 10:18:46 +08:00
快速释放 time_wait 设置这 2 个参数:
net.ipv4.tcp_timestamps=1 net.ipv4.tcp_tw_recycle=1 |
7
meik2333 2018-12-18 10:18:48 +08:00
坑的话就是如果正好有阻塞的包在连接结束后又发送到了的话,可能会发生混乱。
网络环境越好出现概率越低,要同时满足:主动关闭一端已经结束、有包被阻塞在途中且最后成功被送达、正好有同样端口的新连接这几个条件,才会出现混乱。 |
8
a663 OP @liuxu 关闭本机的 timestamps 是为了避免 recycle NAT 后的坑吧?但是这样子不会对本机带来什么坑么?
|
10
SilentHill 2018-12-18 10:42:40 +08:00
@liuxu 代码问题,time_wait 是由于主动关闭连接方引起的,client 有大量的 time_wait,说明 client 频繁的开关连接,要么使用连接池,要么在同一个连接做尽可能多的事情,避免频繁开关
|
11
goofool 2018-12-18 10:43:46 +08:00
改了这些参数问题解决了吗,端口还是会被占用吧。
|
12
liuxu 2018-12-18 10:54:30 +08:00
@SilentHill 高负载的时候肯定会有大量 time_wait 吧,特别是做活动某一时间段有高峰流量的时候,新来的 client 远远大于连接池数量的时候
|
13
bolide2005 2018-12-18 11:12:30 +08:00 2
client 主动断开产生 time wait,这是再正常不过的情况,tcp 协议就是这么规定的,楼上一些同学说连接池之类的,还是没有抓住问题的关键,关键在于 3006 是某个应用要监听的端口,但是被 tcp 自动分配的连接给占用了,这种情况,即便使用连接池也无法完全规避,万一(1/(65536-1024))连接池正好占用了 3006 呢?
即便按楼主的方案修改和 time wait 相关的内核参数,也不能完全规避,最多只能把冲突时间降低。我给的建议是修改 /proc/sys/net/ipv4/ip_local_port_range 文件,把 tcp 自动分配的 port range 提高,比如分配范围在 20000~60000,这样一些知名软件预留端口就基本都避开了。 |
14
hcymk2 2018-12-18 11:17:35 +08:00
/proc/sys/net/ipv4/ip_local_port_range 这个一般都是很高的吧,除非有人修改过了
|
15
Orzpls 2018-12-18 11:19:59 +08:00 via Android
@liuxu 提醒各位,不要开这两个参数,开了有反作用,一大堆 RESET,关了就好了,生产环境曾经开过的人留。
|
16
xi2008wang 2018-12-18 11:21:00 +08:00
不要随便设置 tcp_tw_reuse,基本没啥用,
还会导致 NAT 环境下用户访问你的服务 时不时丢包导致异常 |
17
liuxu 2018-12-18 11:30:40 +08:00
@bolide2005
@hcymk2 @Orzpls 默认最小 32768,楼主 client 能分到 3006,肯定是改过的。 这个很难办,我曾经遇到过这个问题,我司线上服务器默认最小 32768,但也遇到了大量 time_wait 没释放导致无法新开连接的情况,高峰会持续 30-60 分钟,php 日志频繁报“ Cannot assign requested address ”,所以加了那 2 个参数 |
18
nekoyaki 2018-12-18 11:32:09 +08:00 3
楼上有几位提到了 net.ipv4.tcp_timestamps、net.ipv4.tcp_tw_recycle、tcp_tw_reuse,但是这三个参数需要根据实际环境决定是否开启,不能乱开。网上很多二手资料非常误导人。
1、如果开启了 timestamps,但相关机器时间不一致的话,开启 tcp_timestamps 会导致网络连接出现问题,当且仅当你们确定内网涉及到的相关机器都有 ntp 同步时间才能打开。 2、如果关闭 timestamps,recycle 和 reuse 都不生效。网上有的二手垃圾资料教你关闭 timestamps 开启 recycle 和 reuse,没用的。 3、如果确实有 ntp,那么开启 timestamps 和 reuse 就可以了,不要开启 recycle。recycle 是有问题的,新版本内核(4.12)已经废弃了这个参数,reuse 更安全。 |
19
fxxkgw 2018-12-18 11:51:20 +08:00 1
系统内核参数不要乱改,尤其是在 NAT 环境下,网上关于 TIME_WAIT 的资料满天飞,但是绝大多数都是没用的。
1,优化代码,各种 socket 主动关闭 2,最好的办法就是扩容资源。 |
20
90928yao 2018-12-18 15:05:16 +08:00
@liuxu 是有啊 但是大量出现这种状态 90%的情况下 是自己代码写得有问题 哈哈,我自己遇到几次了 都是自己代码问题
|
22
petelin 2018-12-18 16:32:00 +08:00
基本上服务端总是主动断掉链接, 都是代码没写好 /库有问题, 链接服务, 都是 http 长链接之类的吧, 那会创建一个请求一下,然后关掉(我能想到的只有及特殊的爬虫会这样).
|