TCP 40ms延迟问题通俗分析

     我们先看一段网上大神的解释 :

    ”TCP是一个复杂的协议,每个机制在带来优势的同时也会引入其他的问题。 Nagel算法和delay ack机制是减少发送端和接收端包量的两个机制, 可以有效减少网络包量,避免拥塞。但是,在特定场景下, Nagel算法要求网络中只有一个未确认的包, 而delay ack机制需要等待更多的数据包, 再发送ACK回包, 导致发送和接收端等待对方发送数据, 造成死锁, 只有当delay ack超时后才能解开死锁,进而导致应用侧对外的延时高。“


       我知道很多人看了这段话还是一脸懵逼,下面我来详细通俗地解释下。

       先看Nagel机制和delay ack机制     

  1. 如果发送内容大于1个MSS, 立即发送;
  2. 如果之前没有包未被确认, 立即发送;
  3. 如果之前有包未被确认, 缓存发送内容;
  4. 如果收到ack, 立即发送缓存的内容

  1. 如果收到的数据内容大于一个MSS, 发送ACK;
  2. 如果收到了接收窗口以为的数据, 发送ACK;
  3. 如果处于quick mode, 发送ACK;
  4. 如果收到乱序的数据, 发送ACK;
  5. 其他, 延迟发送ACK

    不要慌  下面来详细描述下这个通常延迟40ms的场景 也就是我最近遇到的 

 如图所示客户端128向服务端115发送http请求,我把一个请求放在两个包里发送,第一次send159字节后,服务端收到,但是159小于一个MSS同时也未收到第二个包(也就是上面窗口以为的数据或者在这里是一次完整的http请求),所以触发服务端delay40ms发送ACK,40ms后客户端收到ACK才开始发第二个包也就是前面http请求的下半个包。还没理解?

没关系,下面通俗点:

    A和B商量好,A说我给你发几个东西,发了一个后你收到了要给我说下确保你收到了我才发下一个,要是你一直不给我说,我这里也不是仓库,等我这里的东西堆到了一个MSS那么多,我就把这里的所有直接打包一次发给你。

    服务端B说,你一次发的东西要发完整啊,只发个脑壳的话我是不会马上回你的,等40ms你还没发第二个的话我再回你,要是东西实在太大你先发一半就超过了MSS我也仗义回你下。

   

好 ,现在的情况就是A不长记性非要拆开发,先发头,B收到头后很生气,这么小你也拆散往我这里发?老子等40ms再回你,慢慢等着。 毕竟拖太久影响业务,40ms后B回A说,头我收到了,可以发身体了,然后这时A才开始发身体,B收到身体后由于头和身体都完整了就马上回A:OK,这个充气娃娃我收到了。




解决办法:


  我今天是写的客户端,所以就是关闭 Nagel机制,使用TCP套接字选项TCP_NODELAY可以关闭套接字选项。但是通常不建议,还是一个请求尽量只发一次好,可以使用writev,也可以把两次写操作的数据复制到单个缓冲区,然后对缓冲区调用一次write;





猜你喜欢

转载自blog.csdn.net/anliayx/article/details/78564288