TCP协议缺陷不完全记录

原文转自:http://itindex.net/detail/53400-tcp-%E5%AE%8C%E5%85%A8

零。前言

TCP自从1974年被发明出来之后,历经30多年发展,目前成为最重要的互联网基础协议。有线网络环境下,TCP表现的如虎添翼,但在移动互联网和物联网环境下,稍微表现得略有不足。

移动互联网突出特性不稳定:信号不稳定,网络连接不稳定。虽然目前发展到4G,手机网络带宽有所增强,但因其流动特性,信号也不是那么稳定:坐长途公交车,或搭乘城铁时,或周边上网密集时等环境,现实环境很复杂。

以下讨论基于Linux服务器环境,假定环境为移动互联网环境。记录我目前所知TCP的一些不足,有所偏差,请给与指正。

一。三次握手

在确定传递数据之前需要三次握手,显然有些多余,业界提出了TCP Fast Open (TFO)扩展机制,两次握手之后就可以发送正常业务数据了。但这需要客户端和服务器端内核层面都支持才行: Linux内核3.6客户端,3.7支持服务器端。

进阶阅读: TCP Fast Open: expediting web services

二。慢启动

一次的HTTP请求,应用层发送较大HTML页面的数据,需要经过若干个往返循环时间(Round-Trip Time)之后,拥塞窗口才能够扩展到最大适合数值,中间过程颇为冗余。这个参数直接关系着系统吞吐量,吞吐量大了,系统延迟小了。但设置成多大,需要根据业务进行抉择。

3.0内核之前初始化拥塞窗口(initcwnd)大小为3。一个已建立连接初始传输数据时可传递3个MSS,若1个MSS为1400那么一次性可传递4K的数据,若为10,一次性可传递13K的数据。

谷歌经过调研,建议移动互联网WEB环境下建议initcwnd设置成10,linux内核3.0版本之后默认值为10。遇到较低内核,需要手动进行设置。

若是局域网环境有类似大数据或文件的传输需求,可以考虑适当放宽一些。

若长连接建立之后传输的都是小消息,每次传输二进制不到4K,那么慢启动改动与否都是无关紧要的事情了。

进阶阅读:

三。线头阻塞(Head-of-line blocking, HOL)

TCP协议数据传输需要按序传输,可以理解为FIFO先进先出队列,当前面数据传输丢失后,后续数据单元只能等待,除非已经丢失的数据被重传并确认接收以后,后续数据包才会被交付给客户端设备,这就是所谓的线头(HOL,head-of-line blocking)阻塞。比较浪费服务器带宽又降低了系统性能,不高效。

1. 多路复用不理想

HTTP/2提出的业务层面多路复用,虽然在一定程度上解决了HTTP/1.*单路传输问题,但依然受制于所依赖的TCP本身线头阻塞的缺陷。构建于TCP上层协议的多路复用,一旦发生出现线头阻塞,需要小心对待多路的业务数据发送失败问题。

2. TCP Keepalive机制失效

理论上TCP的Keepalive保活扩展机制,在出现线头阻塞的时候,发送不出去被一直阻塞,完全失效。

类似于NFS文件系统,一般采用双向的TCP Keepalive保活机制,用以规避某一端因线头阻塞出现导致Keepalive无效的问题,及时感知一端存活情况。

3. 线头阻塞超时提示

数据包发送了,启动接收确认定时器,超时后会重发,重发依然无确认,后续数据会一直堆积到待发送队列中,这里会有一个阻塞超时,算法很复杂。上层应用会接收到来自内核协议栈的汇报"No route to host"的错误信息,默认不大于16分钟时间。在服务器端(没有业务心跳支持的情况下)发送数据前把终端强制断线,顺便结合TCPDUMP截包,等15分钟左右内核警告"EHOSTUNREACH"错误,应用层面就可以看到"No route to host"的通知。

四。四次摆手

两端连接成功建立之后,需要关闭时,需要产生四次交互,这在移动互联网环境下,显得有些多余。快速关闭,快速响应,冗余交互导致网络带宽被占用。

五。确认机制通知到上层应用?

这是一个比较美好的愿望,上层应用在调用内核层接口发送大段数据,内核完成发送并且收到对方完整确认,然后通知上层应用已经发送成功,那么在一些环境下,可以节省不少业务层面交互步骤。

六。NAT网关超时

IPV4有限,局域网环境借助于NAT路由设备扩展了接入终端设备的数量。当建立一个TCP长连接时,NAT设备需要维护一个内部终端连接外部服务器所使用的内部IP:PORT与出去的IP:PORT映射对应关系。这个关系需要维护,比较耗费内存资源,有超时定时器清理,否则会导致内存撑爆。

不同NAT设备超时值不一样,因此才需要心跳辅助,确保经过NAT设备的连接一直保持,避免因过长的时间被踢掉。比如针对中国移动网络连接持久时间一般设置为不超过5分钟。各种网络略有差异,引入智能心跳机制比较合适。

七。终端IP漫游

手机终端经常在2G/3G/4G和WIFI之间切换,导致IP地址频繁发生改变。这样造成的后果就是已有的网络请求-响应被放弃和终止,需要人工干预或重新发起请求,存在资源浪费现象。

支持Multipath TCP的终端设备,可以同时利用 2G/3G/4G 和 WiFi 建立Mutlpath连接,通过多点优化网络下载,且互为备份。可以很好解决多个网络共存的情况下,一个网络中断不会导致全局请求处理中断,在设备的连接稳定和可靠性方面有所增强。

当然,服务器之间也可以利用Multipath TCP的多个网络增强网络吞吐量。

现状是:

  1. 目前只有IOS 7以及后续版本支持
  2. Linux kernel 3.10实验分支上可以看到其支持身影,但何时合并到主分支上,暂时未知

进阶阅读: A closer look at the scientific literature on Multipath TCP

八。TCP缓存膨胀

当路由器接收到的数据包超越其队列长度时,一般会随机丢包,以减少膨胀。针对上层应用程序而言,延迟增加,或误认为数据丢失,或连接丢失等。

遇到这种情况,一般建议快速发包,以避免丢失的数据部分。内核层面今早升级到最新版,不低于3.6即可。

进阶阅读: Bufferbloat

九。TCP不是绝对可靠的

  1. IP和TCP协议在头部都会有check sum错误校验和机制,16位表示,反码相加,结果求反,具体可参考 TCP校验和的原理和实现。一般错误很轻松可检测出来,但遇到两个16位数字相加后结果不变的情况就一筹莫展了
  2. 以太网帧CRC32校验一般情况下都很OK,但可能遇到两端隔离多个路由器情况下,就有可能出现问题,比如陈硕老师提供的一张图:

    上图中Client向Server发了一个TCP segment,这个segment先被封装成一个IP packet,再被封装成ethernet frame,发送到路由器(图中消息a)。Router收到ethernet frame (b),转发到另一个网段(c),最后Server收到d,通知应用程序。Ethernet CRC能保证a和b相同,c和d相同;TCP header check sum的强度不足以保证收发payload的内容一样。另外,如果把Router换成NAT,那么NAT自己会构造c(替换掉源地址),这时候a和d的payload不能用tcp header checksum校验。

  3. 路由器可能偶然出现硬件/内存故障导致收发IP报文出现多bit/单bit的反转或双字节交换,这个反转如果发生在payload区,那么无法用链路层、网络层、传输层的check sum查出来,只能通过应用层的check sum来检测。因此建议应用层要设法添加校验数据功能。
  4. 大文件下载添加校验保证数据完整性,一般采用MD5,也用于防止安全篡改

参考资料:

十。小结

在这个满世界都是TCP的环境下,要想对TCP动大手术,这个是不太可能的,因为它已经固化到已有的系统内核和固件中。比如升级终端(比如Android/IOS等)系统/固件,Linux服务器内核,中间设备/中介设备(如路由器等),这是一个浩大工程,目前看也不现实。

TCP位于系统内核层,内核空间的升级、修复,最为麻烦。服务器端升级还好说一些,用户终端系统的升级那叫一个难。用户空间/用户核的应用升级、改造相对比来说可控性强,基于此Google专家们直接在UDP协议上进行构建、并且运行在用户空间的QUIC协议,综合了UDP的轻量和TCP的可靠性,是一个比较新颖的方向。

若是对以后底层传输协议有所期望的话:

  • 在用户空间(用户核)出现可以定制的协议,类似于QUIC
  • 传统的TCP/UDP可以运行在用户空间,直接略过内核
  • 完整协议栈以静态链接库形式提供给上层应用
  • 上层应用可以在编译、打包的时包含其所依赖协议栈静态链接库so文件
  • dpdk/netmap等Packet IO框架 + 用户空间协议堆栈,数据将从网卡直接送达上层应用
  • Linux内核重要性降低,常规的SSH系统维护

虽然TCP存在这样、那样的问题,但目前还是无法绕过的网络基础设施,但稍微明白一些不足的地方,或许会对我们当前使用的现状有所帮助。

时间: 2024-10-26 11:37:06

TCP协议缺陷不完全记录的相关文章

为什么说TCP协议是可靠的

问题背景 日常面试时,几乎所有学过计算机的都知道,TCP协议是可靠的,UDP协议不可靠的.为什么TCP协议是可靠的?它用什么机制保证可靠呢? 提出问题 由于IP 数据包的 MTU 有长度限制, TCP报文段过大时,需要切割.切割之后发送出去,由于网络链路的不确定性,接收端接收到包的次序和发送次序很大概率是不一致的.接收端如何把接收到的"同一批"TCP报文段数据拼接成预期的二进制数据? 发送方发送了一个TCP报文,怎么样确认接收方接收到了这个报文? 发送方发送了一个TCP报文,接收端如何

loadrunner测试TCP协议服务器性能

最近对服务器的性能感兴趣,于是开始研究了一阵子loadrunner如何做采用TCP协议交互的服务器的性能测试,对loadrunner不是很熟悉,所以一开始也走了一些弯路,现将学习的过程记录下来,为以后做参考吧. TCP协议的服务器的性能测试,我想大家都会选择loadrunner的winsocket协议进行测试,我也是采用此种方式.下面将逐一记录如何使用此协议做性能测试. 1.采用DLL文件方式进行测试 由于与服务器连接的客户端的DLL文件我手头有,同时其对应的头文件也有,所以一开始试想的是采用l

TCP 协议中的 Window Size与吞吐量

原地址:http://blog.sina.com.cn/s/blog_c5c2d6690102wpxl.html TCP协议中影响实际业务流量的参数很多,这里主要分析一下窗口的影响. ?TCP窗口目的 为了获得最优的连接速率,使用TCP窗口来控制流速率(flow control),滑动窗口就是一种主要的机制.这个窗口允许源端在给定连接传送数据分段而不用等待目标端返回ACK,一句话描述:窗口的大小决定在不需要对端响应(acknowledgement)情况下传送数据的数量.?官方定义:"The am

udp/tcp协议及三次四次握手

用户数据报协议(UDP) UDP是一个简单的传输层协议(RFC 768). 进程往一个UDP套接字写入一个消息,该消息随后被封装(encapsulating)到一个UDP数据报,该UDP数据报进而又被封装到一个IP数据报,然后发送到目的地. (1) UDP的几个"不保证" [1] 不保证UDP数据报会到达其最终目的地: [2] 不保证各个数据报的先后顺序跨网络后保持不变: [3] 不保证每个数据报只到达一次: -- 总之,UDP不提供可靠性,其本身不提供确认.序列号.RTT估算.超时.

TCP协议与Web服务基础

TCP协议工作在OSI模型的传输层,提供一个可靠的面向连接的服务,其可靠性在于,通信的双方要建立一个端到端的虚电路,通过三次握手建立通信,断开通信需要四次握手.其连接模型如下: 1.建立连接协议(三次握手) (1)客户端发送一个带SYN标志的TCP报文到服务器.(报文1) (2) 服务器端回应客户端的一个同时带ACK标志和SYN标志的TCP报文.(报文2).表示对刚才客户端SYN报文的回应:同时又标志SYN给客户端,询问客户端是否准备好进行数据通讯. (3) 客户再次回应服务器端一个带ACK标志

IP协议和TCP协议的分析

一,TCP/IP协议栈的概述 TCP/IP协议栈是由美国国防部(DoD)在20世纪60年代创建的(比OSI模型还早),是一种具体实现标准. 分为4层:网络接入层(链路层),Internet层(网络层),主机到主机层(传输层),应用层 由于TCP/IP协议栈涉及的知识点很多,而其中最主要的协议是IP协议和TCP协议,故本文主要是针对IP和TCP协议来分析,其他的知识点后续补上. 二,IP协议 IP(Internet Protocol,网际协议)是TCP/IP协议栈中最重要的协议(位于网络层),用于

TCP协议中的计时器

说明:  本文仅供学习交流,转载请标明出处,欢迎转载! 本文是以下文献相关内容的总结 [1] <TCP/IP详解 卷1:协议> [2] <TCP/IP协议族 第4版> [3] <计算机网络 第5版> TCP协议通常包括4种计时器:重传计时器.持续计时器.保活计时器和时间等待计时器. 重传计时器:Retransmission Timer,该计时器用于整个连接期间,用于处理RTO(重传超时).当一个报文从发送队列发出去后,就启动该计时器.若在RTO之内收到了该报文的ACK,

TCP协议解析

本文摘抄自:http://www.kuqin.com/shuoit/20141018/342719.html 本文描述了TCP协议,首先简单介绍了TCP完成了一些什么功能:介绍了TCP报文格式,以及典型报文的数据格式:接着从链路控制和数据传输两个方面进行了介绍,在TCP中链路控制和数据传输是通过同一个通道进行的,并没有区分控制通道和数据通道:在网络中传输数据(控制或真实数据),网络可能发生拥堵,因此接下来简单描述了主机端进行拥塞控制所采取的方法,也简单提及了中间路由器/交换机进行拥塞避免所采取的

TCP协议中RTO的计算

说明:  本文仅供学习交流,转载请标明出处,欢迎转载! 本文是以下文献相关内容的总结 [1] <TCP/IP详解 卷1:协议> [2] <TCP/IP协议族 第4版> [3] <计算机网络 第5版> TCP协议中经常会发生超时重传的情况,我们知道超时重传中的"时"是即RTO.RTO是Retransmission Time-OutD的缩写,该时间决定了发送方在发送数据后,在多长时间内如果没有收到ACK,就重置重传计时器,并重传上次发送失败的报文.那么R