在排查一个超时问题的时候,又再一次遇到了 tcp_tw_recycle 在遇到 NAT 的场景下,可能导致丢包的问题, 掉进同一个坑两次,因此做一次记录; 特别是手抽改过系统tcp参数的应用,需要注意
现象
不同主机C1,C2上的相同模块(开启timestamp),通过NAT网关(1个出口ip)访问同一服务S,主机C1 connect成功,而主机C2 connect失败
故障模型
在以下架构的时候,需要特别留意这个问题
调用方/客户端(一般为多台机器) --> 客户端proxy/出口(一般为单个IP)–> 被调用方/服务端(单台/集群)
调用方/客户端(一般为多台机器) --> 客户端proxy/出口(一般为单个IP)–> 服务端负载均衡器 --> 被调用方/服务端(单台/集群)
图示:
解决方法
服务器端不要将tcp_tw_recycle字段和tcp_timestamps字段同时设为1; 对于服务提供方,建议使用,主动权在服务端,可控性强
1
2
3
4
5
6
7
8
9
## 修改 /etc/sysctrl.conf
## 其实系统默认就是这两个值
net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_timestamps = 1
##酌情加上
net.ipv4.tcp_max_tw_buckets = 36000
sysctl -p
- 客户端把tcp_timestamps字段设0,这样不会发送TCP选项字段中的timestamps选项;需要和客户端沟通做配置修改
建议关闭tcp_tw_recycle选项,而不是timestamp;因为 在tcp timestamp关闭的条件下,开启tcp_tw_recycle是不起作用的;而tcp timestamp可以独立开启并起作用。
分析
根据现象上述问题明显和tcp timestmap有关;查看linux 2.6.32内核源码,发现tcp_tw_recycle/tcp_timestamps都开启的条件下,60s(timewai时间)内同一源ip主机的socket connect请求中的timestamp必须是递增的。
网上随便搜都有源码分析,就不贴了
已知场景
客户端 | 负载均衡器 | 处理方案 | 例子 | 备注 |
---|---|---|---|---|
任意 | aws ELB | 不处理 | ELB有避免该情况的措施 | |
aws NLB | 待测试 | |||
aws ALB | 待测试 | |||
阿里云SLB | 待测试 | |||
服务器,合作方调用 | LVS/单机环境 | 必须处理 | 很多时候,对方都会在出口使用proxy | |
一般终端用户(手机、电脑) | LVS | 建议处理 |
net.ipv4.tcp_tw_recycle的去留
net.ipv4.tcp_tw_recycle 快速回收time_wait有很好的效果;个人认为两类场景可以配置net.ipv4.tcp_tw_recycle=1
- 高并发内部调用,一般不存在客户端proxy
- 自己对上下游应用有较强的可控性
refer
http://blog.sina.com.cn/s/blog_781b0c850100znjd.html
https://colobu.com/2014/09/18/linux-tcpip-tuning/
http://blog.51cto.com/myfuture/876566
https://zhuanlan.zhihu.com/p/35684094
http://perthcharles.github.io/2015/08/27/timestamp-NAT/ ##这篇解释和引申比较透彻