6. 连接断开@tcp调优
参数 - 连接断开相关
tw-reuse: TIME-WAIT的socket能不能直接拿来用
tw-recycle: TIME-WAIT的socket要不要快速回收
timestamps: tcp包里会不会带上时间戳
tw-buckets: 最多能保持多少个TIMEWAIT多了直接清
fin-timeout: 默认的TimeOut时间
我们先说前三个, 这三个是同一个话题下的, 首先说一下基础知识, TIMEWAIT(后文用tw表示) 只会出现在 主动断开连接的一方. 时长为2MSL, 换句话说, 如果你很确定是对方会主动断开连接, 那这个参数跟你就没什么关系
Introduction
我们说如果没有遇到瓶颈, 那么你不需要去折腾操心这些参数, 遇到了瓶颈, 这个tips也不能保证你的问题就能解决, 这只能给你提供一种思路, 你可以通过这种方式观察一下自己现在有多少tw:
几千个tw吓不吓人? 跟几千个CLOSE_WAIT一比还是不吓人的, 因为如果出现了几千个CLOSE_WAIT说明你的程序没有正确的关闭连接. 不要打太极了, 几千个tw到底会不会带来什么影响:
TL;DR 有肯定有, 但是不大. tw会占用你的端口, 同时也在内核里占据一定内存, 一个socket在内核里通过一个五元组 src_ip#port + target_ip#port + tcp/udp 的方式唯一确定, 但是一万个tw可能也就消耗1M左右内存, 其实影响并不大. 因此结论就是, 杀死tw也不能解决你网慢问题. 而更快的回收/复用tw连接能一定程度上的加速.
回收/复用参数
[reuse的场景] 假设一个客户端连接服务器, 然后客户端主动断开连接(此时客户端进入tw), 过了没一会儿他又想连接服务器了, 此时他就可以直接复用这个tw的连接. 换句话说, 如果一个人频繁的断开连接以后又想建立连接, 那么适合reuse
连接复用以后就进入了一段新的会话了, 那就说明你不需要等待2MSL就可以直接使用了, 一个问题是如果上一个会话的包进入了这段会话了怎么处理? 因此我们需要timestamp的协助, 我们一旦有timestamp在包头就能做到两件事:
判断出这个包的发出时间
判断出这段会话的开始时间
因此如果这个包的发出时间小于会话的开始时间, 很明显这个包不属于这个会话, 直接drop掉就好了
[recycle] 这个参数如果被设置成1, 那么回收一个tw的时间就从2MSL(一分钟)缩短成一个RTO, RTO是判断丢包的重要参数, 经过几轮往返动态计算出的值, 在tcp里如果一个包经过rto还没到, 就会被判定成丢包情况. 因此把tw缩短成RTO也是一个合理的设置. 同样的, 我们仍然需要通过timestamp来保证上一个会话的包不会进入这个会话
这种机制可能会引起一个recycle常见的坑: 如果客户端在NAT中, 即该NAT下所有客户端都显示为同一个IP, 如果一个人断开连接很快另一个人又要求重新建立连接, 如果这个时间差小于RTO, 那么完全可能出现五元组完全match的现象. 在服务器看来他会认为这就是同一个人, 于此同时因为我们开启了timestamp, 那么时间戳小的包会被直接丢弃
Last updated
Was this helpful?