业务经过CLB出现概率性timeout

2019-12-13 18:10:58 浏览数 (1)

场景:两个内网负载均衡CLB(10.128.227.245 port:4668-->RS:10.148.16.231和10.128.217.146 port:4394-->RS:10.148.16.231 )后端关联到同一台RS上。

访问异常时的拓扑图:

问题现象1:

监控发现部分容器客户端同时调用两个不同CLB的服务出现概率性超时,curl测试两个CLB随机性的只有一个CLB可以访问,另一个无法正常访问,telnet端口也不通。

访问逻辑:cip(容器)->host(物理机)->clb->rs :经过CLB出现timeout,复现概率很高。

将后端RS从CLB解绑后可以正常访问。

访问逻辑:cip(容器)->host->rs: 不经过CLB业务恢复正常。

1.在业务方确认最近没有做过任何调整后,检查client和RS端防火墙规则,路由表,侦听端口都正常;

防火墙规则正常,没有丢弃对应业务的报文防火墙规则正常,没有丢弃对应业务的报文

2.需要抓包定位,抓包发现CLB正常转发了syn报文到RS,但是RS收到syn报文后没有正常回复syn ack,业务侧希望切走业务先恢复,将业务切到正常RS:10.126.201.77,然后在异常RS抓包定位;

RS收到syn报文后没有响应RS收到syn报文后没有响应

3.切走业务后,curl发现通过CLB访问异常RS的端口恢复正常访问,之前抓包所有复现的流都是丢syn报文,怀疑业务侧启用过快速回收参数,同时系统默认启用时间戳导致丢弃syn报文,通过命令netstat -s | grep passive 查看因为时间戳导致的被动拒绝会话;

发现有大量连接拒绝因为时间戳发现有大量连接拒绝因为时间戳

通过上述现象基本确认是因为时间戳问题导致连接无法建立导致业务超时,通过系统内命令cat /proc/sys/net/ipv4/tcp_tw_recycle确认发现这两个系统参数确实启用;

时间戳和tw快速回收时间戳和tw快速回收

后来业务再次确认后在最近有人开启了时间戳和快速回收机制来解决TW太高的问题,有了明确的怀疑方向,但是需要实锤才能安心;

4.这里还有一个疑问,为什么时间戳和快速回收机制开启后同一个client通过两个CLB访问同一个RS的不同端口会出现超时?(经验告诉我们这种时间戳拒绝连接问题经常出现在NAT场景,虽然client用的容器但是该环境中没有NAT,之前通过切走业务恢复了,问题根因可以仔细复现后排查。)

问题现象2:

业务已经切换到新RS:10.126.201.77,通过client端模拟业务脚本测试发现业务通过直接访问该RS正常(时间戳和快速回收依然是开启的),但是模拟测试通过CLB访问该RS对应的业务CLB:10.128.227.245 port:4668发现依然超时;

1.现象比较诡异,同一个client业务直接访问RS正常,绕CLB访问超时,通过CLB模拟访问的流量并不大;

2.通过最后的测试方案用以下命令进行抓包分析:(业务高峰期不允许抓包,低峰时期才能正常抓包)

选三个client用脚本同时测试10000次分别访问CLB和直接访问RS,以及后台运行while true收集会话信息。抓包点client,CLB和RS,业务按我们协商的时间点发包即可。现场环境只能保留最后30分钟,17:30业务要修改回原有参数,确保国庆期间的业务稳定。

client抓包:tcpdump -i any host 10.128.227.245 -w client.pcap

RS抓包:tcpdump -i any host 10.128.227.245 or host 10.128.219.239 or host 10.128.219.240 or host 10.128.219.241 or host 10.128.219.242 -s 0 -w rs.cap (第一个是CLB地址,后面这些是CLB底层集群的服务器地址)

抓包发现也是经过CLB的syn报文到了RS,但是RS没有响应,并且通过netstat -s | grep timestamp查看因为时间戳导致拒绝连接的数量在不断增长;

3.这个现象的疑问是,为什么业务直接访问RS一样的流量,一样的参数访问正常,同一时间模拟业务测试通过CLB访问就会超时?

最后解释现象1和2的疑问:

(1)现象1的疑问,为什么时间戳和快速回收机制开启后同一个client通过两个CLB访问同一个RS的不同端口会出现超时?

两个业务只有一个可以正常访问两个业务只有一个可以正常访问

开启时间戳和快速回收机制后,根据现象上述问题明显和tcp timestmap有关;查看linux 2.6.32内核源码,发现tcp_tw_recycle/tcp_timestamps都开启的条件下(Linux 从4.12内核版本开始移除了 tcp_tw_recycle 配置),60s内同一源ip主机的socket connect请求中的timestamp必须是递增的。

源码函数:tcp_v4_conn_request(),该函数是tcp层三次握手syn包的处理函数(服务端);

源码片段:

if (tmp_opt.saw_tstamp &&

tcp_death_row.sysctl_tw_recycle &&

(dst = inet_csk_route_req(sk, req)) != NULL &&

(peer = rt_get_peer((struct rtable *)dst)) != NULL &&

peer->v4daddr == saddr) {

if (get_seconds() < peer->tcp_ts_stamp TCP_PAWS_MSL &&

(s32)(peer->tcp_ts - req->ts_recent) >

TCP_PAWS_WINDOW) {

NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);

goto drop_and_release;

}

}

tmp_opt.saw_tstamp:该socket支持tcp_timestamp

sysctl_tw_recycle:本机系统开启tcp_tw_recycle选项

TCP_PAWS_MSL:60s,该条件判断表示该源ip(不关心端口)的上次tcp通讯发生在60s内

TCP_PAWS_WINDOW:1,该条件判断表示该源ip的上次tcp通讯的timestamp 大于本次tcp;

问题现象1总结:client通过两个LB访问同一个RS,由于timestamp时间为系统启动到当前的时间,经过LB1和LB2的timestamp不相同;根据上述syn包处理源码,在tcp_tw_recycle和tcp_timestamps同时开启的条件下,timestamp大的访问成功,而timestmap小的syn报文被丢弃;

(2)现象2的疑问,为什么时间戳和快速回收机制开启后,经过CLB就会出现不响应syn,而直接访问RS就正常?

TGW就是CLB的底层集群名称TGW就是CLB的底层集群名称

开启时间戳和快速回收机制后的变化不在解释,现象1中原理一样;

问题现象2总结:client直接访问RS的业务连接一直在,而绕CLB到RS的syn包总是要晚于直接访问的报文,这就解释通了直接访问RS业务正常,而经过CLB访问RS一定会被丢弃syn报文;

最终总结:如果出现同一个源IP(不是必须NAT场景)通过不同路径访问到同一个RS的情况,一定不能开启时间戳和快速回收机制。类似场景包括但不限于多个client通过nat转换同一个源IP访问到同一个服务器,以及这次的同一个client通过多个LB访问到同一个RS等。优化建议当有云上业务部署多个CLB绑定同一组RS时,切记不能启用时间戳和快速回收机制。

提示:Linux 从4.12内核版本开始移除了 tcp_tw_recycle 配置,因为这个系统参数开启带来的未知风险太大。觉得有用请帮忙点赞,谢谢!

0 人点赞