TCP三次握手的性能提升
如果出现了问题,先用netstat命令查看是哪个握手阶段出现了问题,再来对症下药。
客户端方可以进行的优化
三次握手建立连接的首要目的是【同步序列号】。
正常情况下,客户端发送SYN报文后进入SYN_SENT状态,服务器会在几毫秒之内返回SYN+ACK报文,如果长时间没有收到就会重发SYN包,默认五次,同时每次发送之后等待的时间会乘以2倍。
那么我们可以调整tcp_syn_retries从而控制重传次数,调整三次握手的时间上限。
服务端优化
如何查看由于SYN半连接队列已满,而被丢弃连接的情况
可以通过netstat -s命令得到由于半连接队列已满,引发的失败次数,如果隔几秒钟执行几次发现输出值有上升的趋势,就说明当前存在半连接队列溢出的现象。
如何调整SYN半连接队列大小
我们之前说过,不能只单纯增大tcp_max_syn_backlog的值,还需要一同增大somaxconn和backlog也就是增大accept队列,否则是无效的。
增大tcp_max_syn_backlog和somaxconn的方法是修改linux内核的参数,增大backlog的方法每个web服务器不同。
如果SYN半连接队列已满,只能丢弃连接吗?
开启syncookies功能就可以不使用SYN半连接队列的情况下成功建立。我们之前提到过,看《全连接队列和半连接队列》
SYN_RCV状态的优化
当网络繁忙、不稳定时,报文丢失就会变得严重,此时应该调大tcp_synack_retries参数。反之,就应该调小这个参数。它默认也是5次。
accept队列已满,只能丢弃连接吗?
丢弃连接是默认的行为,我们可以选择向客户端发送RST复位报文,将tcp_abort_on_overflow参数设置为1。
- 0:accept满了,丢掉client发来的ack
- 1: accept满了,发送一个RST给client,废掉这个握手过程和这个连接
可以通过吧tcp_abort_on_overflow设置为1,如果在客户端可以看到很多connection reset by peer这种错误,就可以证明是因为TCP全连接队列溢出导致的问题。
如何调整accept队列的长度?
accept队列的长度取决于somaxconn和backlog之间的最小值,也就是min(somaxconn,backlog)。
somaxconn是Linux内核设置的参数,默认为128
backlog是listern(int sockfd, int backlog)函数中backlog大小默认511
如何绕过三次握手
三次握手造成了一个后果,就是HTTP请求必须在一个RTT(客户端到服务器的一个往返时间)后才能发送。

在Linux3.7内核版本之后,提供了TCP FAST OPEN功能,可以减少TCP连接建立的时延。
在客户端首次建立连接时的过程:
1.客户端发送SYN报文,该报文包含FAST OPEN选项,且该选项的cokkie为空,这表明客户端请求Fast Open Cookie
2.支持TCP fast open的服务器生成Cookie,并将其置于SYN-ACK数据包中的Fast Open选项以发回客户端
3.客户端收到SYN-ACK后,本地缓存Fast Open选项中的Cookie
所以,第一次发起HTTP GET请求的时候,还需要正常的三次握手流程。
在之后,客户端再次向服务器建立连接时的过程:
1.客户端发送SYN报文,该报文包含【数据】以及此前记录的Cookie
2.支持TCP Fast Open的服务器会对收到Cookie进行校验:如果Cookie有效,服务器将在SYN-ACK报文中对SYN和【数据】进行确认,服务器随后将【数据】递送至相应的应用程序;如果Cookie无效,服务器将丢弃SYN报文中包含的【数据】,且其随后发出的SYN-ACK报文将只确认SYN的对应序列号。
3.如果服务器接收了SYN报文中的数据,服务器可以在握手完成之前发送【数据】,这样减少了一个RTT的时间
4.客户端将发送ACK确认服务器发回的SYN以及【数据】,但是如果客户端在初始的SYN报文中发送的【数据】没有被确认,则客户端将重新【发送数据】。
开启TFO可以减少一次RTT的时间消耗。客户端在请求并存储了FAST OPEN COOKIE之后,可以不断重复TCP Fast Open直至服务器认为Cookie无效(通常为过期)

Linux下怎么打开TCP FAST OPEN功能
设置tcp_fastopn内核参数,来打开Fast Open功能:
epoch 3 > /proc/sys/net/ipv4/tcp_fastopen
- 0关闭
- 1作为客户端使用Fast Open功能
- 2作为服务端使用Fast Open功能
- 3无论作为客户端还是服务器,都可以使用Fast Open功能
TCP Fast Open功能需要客户端和服务端同时支持,才有效果。

总结:
客户端的优化:当客户端发起SYN包时,可以通过tcp_syn_retries控制其重传的次数
服务端的优化:服务端SYN半连接队列溢出后,首先可以通过netstat -s观察半连接队列的溢出情况,若溢出情况严重可以通过tcp_max_syn_backlog,somaxconn,backlog参数来调整SYN半连接队列的大小。服务端回复SYN+ACK的重传次数可以由tcp_synack_retries参数控制。若收到SYN攻击,tcp_syncookies参数应设置为1。可以通过ss -lnt查看服务端进程的accept队列长度,若溢出可以设置tcp_abort_on_overflow为1,返回RST报文。accept队列溢出严重的话,可以用listen函数的backlog参数和somaxconn系统参数提升队列大小。
绕过三次握手,TCP FAST OPEN可以绕过三次握手,使HTTP请求减少一个RTT的时间,Linux下可以通过tcp_fastopen开启该功能,同时必须保证服务端和客户端同时支持。
文章探讨了如何优化TCP三次握手过程,包括调整客户端的tcp_syn_retries参数和服务器的SYN半连接队列大小。提到了SYN_RCV状态的优化和启用SYNcookies以应对SYN攻击。此外,介绍了TCP_FASTOPEN功能,它能减少HTTP请求的RTT时间,以及如何在Linux系统中启用此功能。
978

被折叠的 条评论
为什么被折叠?



