TCP的优化?
TCP三次握手的性能提升
客户端优化
当客户端发送SYN报文后会进入SYN_SENT状态,正常情况下服务器会在毫秒内返回ACK+SYN,但当发生丢包触发客户端的重传机制时,客户端需要等待1…3…7…15…31…63s,也就是需要在重传5次之后才会断开连接(重传最大次数有tcp_syn_retries参数决定),因此可以根据网络的稳定性和服务器的繁忙程度修改SYN重传次数
服务端优化
-
半连接队列满
增大半连接队列大小:增大tcp_max_syn_backlog和somaxconn以及backlog参数的大小,后两者的最小值是全连接队列的大小
开启tcp_syncookies机制.
减少ACK+SYN报文重传次数:修改tcp_synack_retries
-
全连接队列满
丢弃/回复RST报文(设置tcp_abort_on_overflow:0/1)
增大全连接队列长度:增大somaxconn和backlog参数的大小.
如何绕过三次握手
引入快速连接(TCP fast open)机制.
传统的TCP连接需要消耗最少一个RTT后才能开始发送HTTP请求.但快速连接可以在建立一次连接之后,之后每次建立连接耗费的时间都是0RTT.
TFO过程:
第一次建立连接时:客户端发送SYN报文并在SYN报文中添加空的Cookie选项;服务器接收到SYN报文后会生成Cookie然后保存在SYN+ACK报文发送给客户端,客户端将Cookie缓存到本地;之后就客户端就可以发送数据了.
第二次建立连接时:客户端发送的SYN中包含数据和Cookie,服务器接收后验证Cookie的有效性,如果有效就返回响应和ACK报文.至此可以节省一个RTT.如果Cookie失效则会只发送ACK报文.
Cookie的值是保存在option选项中的.在Linux中,可以通过调整tcp_fastopn参数开始快速连接机制(1:客户端开启TFO,2:服务器开启TFO,3:任意一方开启TFO)
TCP四次挥手的性能提升
发送方优化
关闭连接的方式分为两种:分别是RST报文关闭和FIN报文关闭.其中前者属于暴力关闭,不经历四次握手的过程,安全的连接方式需要通过四次握手,由进程调用close函数或shutdown函数发起FIN报文.
close函数意味着完全关闭连接,即调用close函数的一方之后既不能发送数据,也不能接收数据.
shutdown函数可以通过参数来控制关闭的程度
RD:关闭连接的读.即不能再接收数据.会将接收缓冲区中的数据丢弃,即使对端发送了数据报文也会在回复ACK后将报文丢弃.
WR:关闭连接的写.即不能再发送数据.如果发送缓冲区中有数据会立即发送,并发送一个FIN报文.
RDWR:关闭连接的读和写,即不能接收数据和发送数据.
FIN_WAIT1的优化
发送方发送了FIN报文后会进入FIN_WAIT1状态,在接收到接收方的ACK报文后会迅速进入到FIN_WAIT2状态.但当发生丢包时会触发发送方重传FIN报文,因此可以通过减少重传次数来加速发送方断开连接,即减少tcp_orphan_retries参数的值(默认是8).
但有时候当遇到恶意攻击时会导致连重发的FIN报文也无法发送(恶意攻击导致接收方窗口大小为0致使发送方无法发送数据,而发送方的发送缓冲区中的数据没有发送完,FIN报文需要在数据发送完后再发送).这时候需要调整tcp_max_orphans参数来降低最大的孤儿连接数量.当孤儿连接数量大于tcp_max_orphans的值时,新的孤儿连接会直接回复RST报文.
FIN_WAIT2的优化
当发送方接收到接收方的ACK报文后会进入FIN_WAIT2状态.如果调用的是shutdown函数,因为可能还可以继续发送或接收数据,所以发送方可以一直处于FIN_WAIT2状态.但如果调用的是close函数,那么则会处于孤儿连接,因此在FIN_WAIT2状态不能持续太长时间,这个时间有tcp_fin_timeout参数决定,通常是60s(超过60s会直接关闭连接.),和TIME_WAIT一致.
TIME_WAIT状态的优化
- 通过tcp_max_tw_buckets参数来控制TIME_WAIT的最大连接,当超过这个值,新关闭的连接将不经过TIME_WAIT状态而直接关闭.
- 在建立连接时,复用在TIME_WAIT状态的连接超过1s的连接.通过打开tcp_tw_reuse参数(注意:该参数只能由客户端发起,因为是在调用connect方法时发挥作用的.),同时也要将时间戳打开(通信双方都需要打开)
- 通过tcp_tw_recycle参数回收TIME_WAIT状态的连接(不推荐).当开启recycle和timestamp时,就会开启per-host的PAWS(判断TCP报文中的时间戳是否失效).per-host是对对端IP做PAWS检查,这就面临一个问题:当对端是通过NAT网关后进行通信,不同的客户端经过相同的NAT网关后的IP地址是相同,per-host无法判断对方的时间戳是哪一个客户端的,容易发生误判.优化方式就是对四元组做PAWS检查.
- 通过设置socket参数来跳过TIME_WAIT状态:将l_onoff设置为非0,l_linger设置为0,在调用close函数会直接回复RST报文来中断连接.
接收方优化
接收方在发送了FIN报文后会进入LAST_ACK状态,如果收不到ACK会触发重传,与发送方一样,可以通过设置tcp_orphan_retries来加速连接的断开.
注意:接收方发送ACK报文和FIN报文之间如果没有数据发送,则ACK报文和FIN报文可能会同时发送.
当通信双方同时关闭连接时,即同时给对方发送FIN报文后,会同时进入FIN_WAIT1状态,所以上述的优化策略仍然成立.之后会给对方传输ACK报文,传输后会进入新的状态CLOSEING,在对方接收到ACK后会进入TIME_WAIT状态,等待2MSL时间后关闭连接.在这里插入图片描述
TCP数据传输的性能提升
- 扩大滑动窗口大小:tcp_window_scaling.可以让滑动窗口从默认的最大值64KB调整为1GB
- 内核缓冲区决定了滑动窗口的大小,将内核缓冲区的上限设置为带宽时延积,带宽时延积是网络中能够承载的数据的最大数量,通过带宽与RTT相乘得到.tcp_wmem是调整发送缓冲区的大小,tcp_rmem是调整接收缓冲区的大小.
- 发送缓冲区的大小是自动动态调节的,而接收缓冲区的动态调节功能可以通过tcp_moderate_rcvbuf打开.
|