写在前面:由于这次问题以出乎意料的方式自行消失了,这篇文章可能仅仅为你提供一份排查思路。


问题

最近在项目中遇到了一个问题:TCP建立连接后,只能传输固定有限N条(常量)报文。

发送服务的代码已经久经使用,可以信赖。但是建立连接,发送N条数据后,发现收不到对方的响应。


排查

  1. 在重启发送服务的过程中发现,每次服务整体重启,或是TCP连接超时断开重连,新发送的前N条TCP报文都有响应。
  2. 之后,调整了发送报文的频率,发现高频率下发送报文的数量N不变,看起来像是短时间内把报文发送的额度“用尽”了。反过来说,在TCP连接建立后,先等待一段时间内不发送数据,之后也能发送N条有响应的报文。
  3. 最后使用tcpdump工具抓包,观测到:在发送报文前的TCP三次握手正常,前N条报文正常,第N+1条报文会以毫秒级快速多次重发,且首次重发时间极短,大约在首次发送报文的几十毫秒内就会开始重发。
  4. 此外,在非内网环境下,对方平台正常响应。

初步结论

①每次重新建立TCP连接,可发送数据量重置。
②时间窗口不是影响发送数据量的主要因素,数据量才是。
③并非对方不发送响应,而是我方的数据发送不过去,很可能与网络环境有关。


继续排查

接下来为了控制网络环境这一变量,选择将服务部署在新服务器上测试。但由于服务器群部署在内网上,申请权限耽搁了几天。

测试结果出乎意料:不仅新服务器上的服务可以正常使用,原服务器上的服务也恢复正常了。而且,临时写的TCP报文发送器也表现得一切正常。

懵了呀。


问题出在哪儿?

事实上,对于这种像是小精灵一样消失的问题,现在也没办法确定问题到底出在哪儿。只能靠目前的信息,做出推测:

根据前面多次控制变量的结果,很有可能是防火墙协议权限带来的问题。

公司内网的防火墙需要权限申请才能通过,而在申请时,需要选择TCP、UDP、HTTP协议中的一项。假设开通人员搞错了协议内容,那么根据DPI (Deep Packet Inspection) 深度包检测技术,防火墙可能对非HTTP协议的流量进行拦截。

这解释了为什么第N+1条报文会以毫秒级快速多次重发——因为它在本地防火墙就被拦截,这个失败速度是非常快的。

另外,为什么有N条报文可以发送?一个可能的解释是:HTTP连接需要TCP进行三次握手,而防火墙为三次握手设计了一些容忍度,这些容忍度体现为可以发送出去的N条报文。

那为什么隔了几天以后两台服务器都恢复正常了?这个问题大概是没法得到一个确切答案了,只能做一个推测:防火墙管理人员在看到第二张权限申请单后,意识到第一张开错了协议,偷偷改正了……

事后总结

  1. 在排查中,控制变量法是有力的工具,可以从最有可能的地方开始控制变量,提高排查效率。
  2. 合适的重启可以抓到问题的“刷新点”,帮助定位问题。
  3. 如果失败时间较短,考虑本地限制因素
  4. 大胆怀疑,小心求证。

禹安
4 声望0 粉丝

热爱技术本身。