跳转至主要内容
"这个应用已经运行好几年了,上周网络升级,我们从100 mbps转到了千兆。现在一些消息中的最后一半数据是垃圾。网络人员发誓这不是网络的问题--但这是唯一改变的事情。"

 

好消息是,昂贵的网络升级并没有破坏应用。

 

坏消息是,这个应用程序已经坏了,而且一直都是坏的。很多*编写TCP应用程序的人没有意识到的是,TCP是一个字节流,而不是消息流。一个应用程序发送了两个1000字节的消息,并不意味着发送的TCP栈会发送两个1000字节的TCP段。应用消息可以根据接收方宣传的最大段大小或发送方的一些配置限制而被分割成更小的片段。重传也可以对应用消息进行组合和分割。即使发送方TCP协议栈实际发送了两个1000字节的TCP段,也不能保证接收方TCP协议栈会给接收方应用两个1000字节的消息。例如,如果应用程序的缓冲区只有500字节,这就是TCP堆栈将返回的全部内容。另一方面,如果缓冲区是1500字节,并且两个1000字节的段都已经到达,TCP栈将在第一次调用中返回1500字节,在第二次调用中返回500字节。应用程序要把字节流正确地解析回消息。

 

这和升级网络有什么关系?OpenVOS服务器和Linux客户端在不同的子网中,所以OpenVos系统的广告最大分段大小为536字节。客户端发送的应用程序消息是1000字节,所以消息被分割成两部分。在升级之前,似乎两个段都是在应用程序发布接收之前到达OpenVOS服务器的,所以所有的1000字节都是通过调用接收函数来读取的。升级后,段的时间发生了变化,因此在某些时候,当应用程序发布其receive时,只有第一个段是可用的。应用程序缓冲区的最后464(1000 - 536)个字节没有被TCP堆栈填满,而是包含了receive被发布之前的任何垃圾。

 

在这种情况下,有一个简单的快速修复方法,将OpenVOS的广告MSS值增加到1460(参见An easy way to improve TCP throughput across subnets)。然而,这实际上只是一个止境。真正的解决方法是重写代码,将TCP字节流正确地解析为应用消息,而不是仅仅假设1个receive call将返回1个消息。

© 2024Stratus Technologies.