传输层 三次握手中性能优化

服务器三次握手流程示例


当理解了三次握手当中的状态变迁之后,就可以进一步的去探讨客户端与服务器在实现当中的一些特点。这样我们就能够直到如何进行性能优化,以及握手当中的一些安全攻击问题。

首先以服务器为例,来看看三次握手的流程。

首先客户端发来syn分组到达了服务器,服务器内核,也就是对tcp的实现,会将syn分组插入到syn对列当中,同时会发出syn+ack,这个时候连接的状态为syn-received的状态,什么时候会从syn-received状态变为establish的状态呢?它会在客户端再次发来ack分组之后就会进入establish状态了。

但实际上在操作系统内核当中会将syn从syn队列当中移出,再塞入accept队列,这样我们的应用程序nginx tomcat在调用accept的方法的时候就从accept队列当中将之前的连接拿出来给相关的方法去使用了。

所以在这个过程当中可以看到这个syn的队列长度和accept队列长度和我们的负载都是相关的。

如果面对的是每秒几十万请求高负载的机器,那么对syn队列和accept队列也是需要延长的。

超时时间与缓冲队列


怎么样对syn accept队列进行延长呢?

客户端优化

应用层 connect 超时时间调整(客户端也可以调整,客户端调用connect方法的时候,通常会有一个connect_timeout,去设置超时时间)
服务端优化
操作系统内核限制调整
           • 服务器端 SYN_RCV 状态
                         • net.ipv4.tcp_max_syn_backlog:SYN_RCVD 状态连接的最大个数(调整sync队列的大小)
                           • net.ipv4.tcp_synack_retries:被动建立连接时,发SYN/ACK的重试次数(当我们发送SYN/ACK之后,长时间没有得到ack响应,我们可能要重发SYN/ACK的重试次数)
客户端 SYN_SENT 状态
• net.ipv4.tcp_syn_retries = 6 主动建立连接时,发 SYN 的重试次数(客户端发完syn,其实就进入了syn_sent状态,在syn_sent状态的时候,对于linux上面的负载均衡,或者向其他服务器建立大量连接的时候,也可以通过syn_retries来设置重发syn的重试次数)
net.ipv4.ip_local_port_range = 32768 60999 建立连接时的本地端口可用范围(划定更大的源端口的范围)
• ACCEPT队列设置(一样可以通过backlog设置)

Fast Open 降低时延


三次握手当中有没有进一步的优化空间呢?

比如发起http get的请求,需要进行三次握手,发出syn 收到一个syn+ack,下一个ack当中带一个http get请求,这里其实是用了两个rtt的时间。

tcp提供了一个叫fast open的功能,它在做什么样的事情呢?第一次去建立连接的时候,server会给他生成一个cookie,在发送syn+sck的时候,将cookie给了我们的client,client会缓存这个cookie,所以第一次发起连接的时候还是要提供两个rtt才能将get请求发出去,以及收到对方的响应。

但是在第二次发送请求的时候,我们就跳过了三次握手,因为cookie当中维护了上一次建立连接当中相关的信息,比如窗口,时间戳等等tcp的选项参数。

直接将cooki在syn当中发给server,而且可以将get请求也发给server,这样就使用了tcp fsat open。实际上就消除了三次握手rtt的时延。

Linux上打开TCP Fast Open


net.ipv4.tcp_fastopen:系统开启 TFO 功能

0:关闭
1:作为客户端时可以使用 TFO
2:作为服务器时可以使用 TFO
3:无论作为客户端还是服务器,都可以使用 TFO

猜你喜欢

转载自blog.csdn.net/qq_34556414/article/details/125816913
今日推荐