服务器三次握手流程示例
当理解了三次握手当中的状态变迁之后,就可以进一步的去探讨客户端与服务器在实现当中的一些特点。这样我们就能够直到如何进行性能优化,以及握手当中的一些安全攻击问题。
首先以服务器为例,来看看三次握手的流程。
首先客户端发来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队列进行延长呢?
客户端优化
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 功能