客户端明明发送SYN,但服务端不响应ACK

公司最近上线的app出现一种奇怪的问题:调用api会出现网络延迟报错,而同一套api在pc端调用却很正常,而且问题出现是间歇性的,一定会出现,不确定下次啥时候出现,但是调用其他api却很正常。开始接到app开发童鞋和运营童鞋反馈该问题的时候,我的第一反映这这么可能,pc端的api用的好好的,咋到app里面调用问题就来了,想当然觉得肯定是网络问题。

但是该app是来给客人验证票据的,实时性要求很高,出现这种问题是不能容忍的,app童鞋还专门搞了一个测试网络的app,里面整了三个按钮分别调用三个不同的接口,其中两个我们这边的api,另外一个是另一个部门童鞋负责的api(服务跑在windows上面),结果很诧异,我负责的这两个api网络延迟失败率很高,大概20次就出现异常,而且后面的请求会连续失败,事实证明我们这边的api有问题!

排除法搞了一轮:代码用pc端访问没出现过类似问题,排除代码的问题;换服务之后问题依然在,显然不是服务器的问题;查看nginx日志,发现出现网络延迟的时候,居然没有写入nginx日志,最后唯一的可能就是tcp 三次握手失败了,必须要抓包分析了!

跟另外一位app开发人员一起用wireshare分析从服务器上dump下来的日志,问题出来了:客户端明明发送SYN,但服务端就是不响应ACK包。google了一番:

关于内核参数的详细介绍,可以参考 官方文档 。我们这里简要说明一下tcp_tw_recycle参数。它用来快速回收TIME_WAIT连接,不过如果在NAT环境下会引发问题。

RFC1323 中有如下一段描述:

An additional mechanism could be added to the TCP, a per-hostcache of the last timestamp received from any connection.This value could then be used in the PAWS mechanism to rejectold duplicate segments from earlier incarnations of theconnection, if the timestamp clock can be guaranteed to haveticked at least once since the old connection was open. Thiswould require that the TIME-WAIT delay plus the RTT togethermust be at least one tick of the sender’s timestamp clock.Such an extension is not part of the proposal of this RFC.

大概意思是说TCP有一种行为,可以缓存每个连接最新的时间戳,后续请求中如果时间戳小于缓存的时间戳,即视为无效,相应的数据包会被丢弃。

执行下面命令:

netstat -s | grep timestamp

发现服务器已经拒绝了不少包,问题慢慢清晰,客户端发送完tcp syn报文之后,服务器并没有回应ack包,直接drop掉了! 
看了些博客,最后修改了linux 内核参数问题得到解决:

 net.ipv4.tcp_timestamps=0 net.ipv4.tcp_tw_recycle=1

tcp_tw_recycle/tcp_timestamps都开启的条件下,60s内同一源ip主机的socket connect请求中的timestamp必须是递增的,感谢下面的作者提供思路: 
http://blog.csdn.net/caianye/article/details/38540867 

http://serverfault.com/questions/235965/why-would-a-server-not-send-a-syn-ack-packet-in-response-to-a-syn-packet

发表评论

邮箱地址不会被公开。 必填项已用*标注