丨如何提升tcp四次挥手的性能_第1页
丨如何提升tcp四次挥手的性能_第2页
丨如何提升tcp四次挥手的性能_第3页
丨如何提升tcp四次挥手的性能_第4页
丨如何提升tcp四次挥手的性能_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

四次挥手中你可以用netstat命令观察到6种状态。其中,你多半看到过TIME_WAIT状态。网上有许多文章介绍怎样减少TIME_WAIT状态连接的数量,也有文章说TIME_WAITLinux为四次挥手提供了很多控制参数,有些参数的名称与含义并不相符。例如tcp_orphan_retries参数中有orphan孤儿,却同时对非孤儿连接也生效。而且,错误地配置这些参数,不只无法针对高并发场景提升性能,还会降低资源的使用效率,甚至数这一讲,基于四次挥手的流程,介绍Linux下的优化方法你想没想过,为什么建立连接是三次握手,而关闭连接需要四次挥手这是因为TCP不允许连接处于半打开状态时就单向传输数据,所以在三次握手建立连接时,服务器会把ACKSYN在一起发给客户端,其中,ACK来打开客户端的发送通道,SYN用来打开服务器的发送通道。这样,原本的四次握手就降为三次握手了。但是当连接处于半关闭状态时,TCP是允许单向传输数据的。为便于下文描述,接下来我们把先关闭连接的一方叫做主动方,后关闭连接的一方叫做方。当主动方关闭连接时,方仍然可以在不调用lose函数的状态下,长时间发送数据,此时连接处于半关闭状态。这一特性是TCP的双向通道互相独立所致,却也使得关闭连接必须通过四次挥手才能做到。互联网中往往服务器才是主动关闭连接的一方。这是因为,HTTP消息是单向传输协议,服务器接收完请求才能生成响应,发送完响应后就会立刻关闭TCP连接,这样及时释放了资这就使得服务器的优化策略变得复杂起来。一方面,由于方有多种应对策略,从而增加了主动方的处理分支。另一方面,服务器同时为成千上万个用户服务,任何错误都会被庞大的用户数放大。所以对主动方的关闭连接参数调整时,需要格外。了解了这一点之后,我们再来看四次挥手其实四次挥手只涉及两种报文:FINACK。FIN是Finish束连接的意思,谁发出FIN报文,就表示它将不再发送任何数据,关闭这一方向的传输通道。ACK是Acknowledge确认的意思,它用来通知对方:你方的发送通道已经关闭。当主动方关闭连接时,会发送FIN报文,此时主动方的连接状态由ESTABLISHED变为FIN_WAIT1。当方收到FIN报文后,内核自动回复ACK报文,连接状态由ESTABLISHED变为CLOSE_WAIT,顾名思义,它在等待进程调用close函数关闭连接。当主动方接收到这个ACK报文后,连接状态由FIN_WAIT1变为FIN_WAIT2,主动方的再来看方的发送通道是如何关闭的。当方进入CLOSE_WAIT状态时,进程的read函数会返回0,这样开发人员就会有针对性地调用close函数,进而触发内核发送FIN报文,此时方连接的状态变为LAST_ACK。当主动方收到这个FIN报文时,内核会自动回复ACK,同时连接的状态由FIN_WAIT2变为TIME_WAIT,Linux系统下大约1分钟后TIME_WAIT状态的连接才会彻底关闭。而方收到ACK报文后,连接就会关关闭连接有多种方式,比如进程异常退出时,针对它打开的连接,内核就会发送RST报文来关闭。RST的全称是Reset复位的意思,它可以不走四次挥手强行关闭连接,但当报文延安全关闭连接的方式必须通过四次挥手,它由进程调用close或者shutdown函数发起,这二者都会向对方发送FIN报文(shutdown参数须传入SHUT_WR或者SHUT_RDWR才会发送FIN),区别在于close调用后,哪怕对方在半关闭状态下发送的数据到达主动此时,这个连接叫做孤儿连接,如果你用netstatp命令,会发现连接对应的进程空。而shutdown函数调用后,即使连接进入了FIN_WAIT1或者FIN_WAIT2状态,它也不是孤儿连接,进程仍然可以继续接收数据。关于孤儿连接的概念,下文调优参数时还会主动方发送FIN报文后,连接就处于FIN_WAIT1状态下,该状态通常应在数十毫秒内转为FIN_WAIT2。只有迟迟收不到对方返回的ACK时,才能用netstat命令观察到FIN_WAIT1状态。此时,内核会定时重发FIN报文,其中重发次数由tcp_orphan_retries参数控制(注意,orphan虽然是孤儿的意思,该参数却不只对孤儿连接有效,事实上,它对所有FIN_WAIT1状态下的连接都有效),默认值是0,特指81net.ipv4.tcp_orphan_retries=如果FIN_WAIT1态连接有很多,你就需要考虑降低tcp_orphan_retries值。当重试次数达到tcp_orphan_retries时,连接就会直接关闭掉。对于正常情况来说,调低tcp_orphan_retries已经够用,但如果遇到,FIN报文根本无法发送出去。这是由TCP的2个特性导致的。首先,TCP须保证报文是有序发送的,FIN文也不例外,当发送缓冲区还有数据没发送时,FIN报文也不能提前发送。其次,TCP有流控功能,当接收方将接收窗口设为0时,发送方就不能再发送数据。所以,当者大文件时,就可以通过将接收窗口设为0,导致FIN报文无法发送,进而导致连接一直处于FIN_WAIT1状态。解决这种问题的方案是调整tcp_max_orphans参数1net.ipv4.tcp_max_orphans=顾名思义,tcp_max_orphans定义了孤儿连接的最大数量。当进程调用close函数关闭连接后,无论该连接是在FIN_WAIT1状态,还是确实关闭了,这个连接都与该进程无关了,它变成了孤儿连接。Linux系统为防止孤儿连接过多,导致系统资源长期被占用,就提供了tcp_max_orphans数。如果孤儿连接数量大于它,新增的孤儿连接将不再走四次挥手,而是直接发送RST复位报制关闭。当连接收到ACK进入FIN_WAIT2状态后,就表示主动方的发送通道已经关闭,接下来将等待对方发送FIN报文,关闭对方的发送通道。这时,如果连接是用shutdown函数关闭的,连接可以一直处于FIN_WAIT2状态。但对于close函数关闭的孤儿连接,这个状态不可以持续太久,而tcp_fin_timeout控制了这个状态下连接的持续时长。1net.ipv4.tcp_fin_timeout=它的默认值是60秒。这意味着对于孤儿连接,如果60秒后还没有收到FIN报文,连接就会直接关闭。这个60秒并不是拍脑袋决定的,它与接下来介绍的TIME_WAIT状态的持续时间是相同的,我们稍后再来回答60秒的由来。TIME_WAIT是主动方四次挥手的最后一个状态。当收到方发来的FIN报文时,主动方回复ACK,表示确认对方的发送通道已经关闭,连接随之进入TIME_WAIT状态,等待60TIME_WAIT状态的连接,在主动方看来确实已经关闭了。然而,方没有收到ACK报文前,连接还处于LAST_ACK状态。如果这个ACK报文没有到达方,方就会重发FIN报文。重发次数仍然由前面介绍过的tcp_orphan_retries参数控制如果主动方不保留TIME_WAIT状态,会发生什么呢?此时连接的端口恢复了自由身,可以复用于新连接了。然而,方的FIN报文可能再次到达,这既可能是网络中的路由器重复发送,也有可能是方没收到ACK时基于tcp_orphan_retries参数重发。这样,正常通讯的新连接就可能被重复发送的FIN报文误关闭。保留TIME_WAIT状态,就可以应付重发的FIN报文,当然,其他数据报文也有可能重发,所以TIME_WAIT状态还能避我们再回过头来看看,为什么TIME_WAIT状态要保持60秒呢?这与孤儿连接FIN_WAIT2状态默认保留60秒的原理是一样的,因为这两个状态都需要保持2MSL时长。MSL全称是 umSegmentLifetime,它定义了一个报文在网络中的最长生存时间(报文每经过一次路由器的转发,IP头部的TTL字段就会减1,减到0文就被为什么是2ML的时长呢?这其实是相当于至少允许报文丢失一次。比如,若ACK在一个ML内丢失,这样方重发的FIN会在第2个ML内到达,TME_WAIT状态的连接可以应对。为什么不是4或者8ML的时长呢?你可以想象一个丢包率达到百分之一的糟糕网络,连续两次丢包的概率只有万分之一,这个概率实在是太小了,忽略它比解决它更具性价比。因此,TIME_WAITFIN_WAIT2态的最大时长都是2MSL,由于在Linux统中MSL值固定为30,所以它们都是60虽然TIME_WAIT状态的存在是有必要的,但它毕竟在消耗系统资源,比如状态的端口就无法供新连接使用。怎样解决这个问题呢Linux供了tcp_max_tw_buckets当TIME_WAIT连接数量超过该参数时,新关闭的连接就不再经历TIME_WAIT而直接关闭。1net.ipv4.tcp_max_tw_buckets=当服务器的并发连接增多时,相应地,同时处于TIME_WAIT态的连接数量也会变多,此时就应当调大tcp_max_tw_buckets参数,减少不同连接间数据错乱的概率。当然,tc_max_twbuces也不是越大越好,毕竟内存和端都是有限的。有没有办法让新连接复用TIME_WAT状态的端口呢?如果服务器会主上游服务器发起连接的话,就可以把cp_twree参数设置为1,它允许作为客户端的新连接,在安全条件下使用TIME_WAT状态下的端口。1net.ipv4.tcp_tw_reuse=当然,要想使tcp_tw_reuse效,还得把timestamps数设置为1,它满足安全复用的先决条件(对方也要打开tcp_timestamps):1net.ipv4.tcp_timestamps=老版本的Linux提tcp_tw_recycle数,它并不要求TIME_WAIT态存在秒,很容易导致数据错乱,不建议设置为11net.ipv4.tcp_tw_recycle=所以在Linux4.12版本后,直接取消了这一参当方收到FIN报文时,就开启了方的四次挥手流程。内核自动回复ACK报文后,连接就进入CLOSE_WAIT状态,顾名思义,它表示等待进程调用close函数关闭连接。内核没有权力替代进程去关闭连接,因为若主动方是通过shutdown闭连接,那么它就是想在半关闭连接上接收数据。因此,Linux并没有限制CLOSE_WAIT状态的持续时当然,大多数应用程序并不使用shutdown函数关闭连接,所以,当你用netstat命令发现大量CLOSE_WAIT状态时,要么是程序出现了Bug,read函数返回0时忘记调用close函数关闭连接,要么就是程序负载太高,close函数所在的回调函数被延迟执行了。由于CLOSE_WAIT状态下,连接已经处于半关闭状态,所以此时进程若要关闭连接,只能调用close函数(再调用shutdown关闭单向通道就没有意义了),内核就会发出FIN报文关闭发送通道,同时连接进入LAST_ACK状态,等待主动方返回ACK来确认连接关闭如果迟迟等不到ACK,内核就会重发FIN报文,重发次数仍然由tcp_orphan_retries参数控制,这与主动方重发FIN报文的优化策略一致。至此,由一方主动发起四次挥手的流程就介绍完了。需要你注意的是,如果方迅速调用close函数,那么方的ACK和FIN有可能在一个报文中发送,这样看起来,四次挥手我们再来看一种特例,如果连接双方同时关闭连接,会怎么此时,上面介绍过的优化策略仍然适用。两方发送FIN报文时,都认为自己是主动方,所以都进入了FIN_WAIT1状态,FIN报文的重发次数仍由tcp_orphan_retries参数控制。接下来,双方在等待ACK报文的过程中,都等来了FIN文。这是一种新情况,所以连接会进入一种叫做CLOSING的新状态,它替代了FIN_WAIT2状态。此时,内核回复ACK确认对方发送通道的关闭,仅己方的FIN报文对应的ACK还没有收到。所以,CLOSING状态与LAST_ACK状态下的连接很相似,它会在适时重发FIN报文的情况下最终关闭。我们对这一讲的内容做个小四次挥手的主动方,为了应对丢包,允许在tcp_orphan_retries数内重发FIN文。当收到ACK报文,连接就进入了FIN_WAIT2状态,此时系统的行为依赖这是否为孤儿连如果这是lose函数关闭的孤儿连接,那么在tcpfintimeout秒内没有收到对方的FIN报文,连接就直接关闭,反之shutdown函数关闭的连接则不受此限制。毕竟孤儿连接可能在重发次数内存在数分钟之久,为了应对孤儿连接占用太多的资源,tcp_maxorha定义了最大孤儿连接的数量,超过时连接就会直接释放。当接收到FIN报文,并返回ACK后,主动方的连接进入TIME_WAIT状态。这一状态会持续1分钟,为了防止TIME_WAIT状态占用太多的资源,tcp_max_tw_buckets定义了最大数量,超过时连接也会直接释放。当TIME_WAIT状态过多时,还可以通过设置tcp_tw_reuse和tcp_timestamps为1,将TIME_WAIT状态的端口复用于作为客户端的关闭的连接方应对非常简单,它在回复ACK后就进入了CLOSE_WAIT状态,等待进程调用close函数关闭连接。因此,出现大量CLOSE_WAIT状态的连接时,应当从应用程序中找问题。当方发送FIN报文后,连接就进入LAST_AC

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论