TCP三次握手如何优化

三次握手在一个HTTP请求中的平均时间占比在10%以上,当网不好,高并发 ,遭遇SYN泛洪攻击的时候,性能就会受影响。

TCP协议是通过OS实现的,调整TCP必须通过OS提供的接口和工具。

客户端的性能优化比服务器简单一些,因为服务器需要在监听端口上被动等待连接,还要保存许多握手的中间状态。

3次握手建立连接的首要目的是同步序列号。因为只有同步了序列号才可以有可靠的传输,TCP协议中的流量控制和消息丢失后的重发等特性都是依赖序列号实现的。所以三次握手中的报文被称为SYN的原因——Synchronize Sequence Numbers

OS实现了三次握手,但是我们看到的是连接状态 ,可以来看下3种状态的意义——
客户端发送SYN开启了三次握手,这个时候在客户端使用netstat命令可以看到连接的状态是SYN_SENT

通常,服务器会在几ms内返回ACK,但是如果客户端一直都没有收到ACK的话,客户端会重发 SYN,重试的次数是tcp_syn_retries参数来控制。

image.png

一般终止3次握手,最长时间超过了2分钟。

可以降低重试次数,从而可以尽快地把错误暴露给应用程序。


服务器收到SYN报文后,会返回给客户端SYN+ACK报文,确认客户端的序列号,同时发送自己的序列号。

这个时候,服务器端出现了新的连接状态,SYN_RCV
netstat -s命令可以得到由于队列已满而引发的失败次数。队列溢出,会导致SYN被丢弃。如果SYN被丢弃的个数一直变多,就应该增大SYN半连接队列(设置Linux的tcp_max_syn_backlog参数)

当SYN半连接队列满的时候,也可以不丢弃队列,而是开启syncookies功能就可以在不使用SYN队列的情况下成功建立连接。使用syncookies建立的连接会导致许多TCP特性均无法使用,所以只有当队列要溢出的时候启动syncookies

SYN泛洪攻击:攻击者使用大量的SYN报文发送给服务器,从而导致SYN半连接队列溢出,从而导致客户端的连接无法建立。

客户端收到服务器回复的SYN+ACK报文后,就会回复ACK 给服务器,同时客户端的连接状态从SYN_SENT会变成ESTABLISHED,表明连接成功

但是服务器端连接成功的建立要晚一些,当收到客户端发送的ACK后服务器的连接状态才会变成ESTABLISHED

image.png

image.png

服务器收到ACK连接建立成功后,OS的内核会把连接(这个连接是什么?)从 SYN半连接队列中移出,再移入到accept队列,等到进程调用accept()函数的时候把连接取出来。

image.png

image.png

image.png

TFO:客户端可以在首个SYN报文中就携带请求,从而节省了1个RTT的时间。

image.png


说了半天,如何优化呢(面试时候怎么答)?

  1. 当客户端发送SYN的时候,控制重发次数。(如果客户端一直没收到服务器回复的ACK,客户端就会重发)。
  2. 调整服务器的SYN半连接队列的长度。(如果SYN半连接队列溢出,SYN报文就会丢失,导致连接建立失败
  3. 当网络稳定的时候,减少服务器重发SYN+ACK报文的次数。(如果服务器没有收到客户端发送的ACK(ACK报文?),就会一直重发SYN+ACK报文)
  4. 当SYN队列满了后,开启syncookie功能,应对泛洪攻击。(保证连接成功建立)
  5. 进程想取出连接是通过调用accept()函数。
  6. 如果accept()队列溢出,系统默认会丢弃ACK,也可以用RST通知客户端连接建立失败。
  7. 当通过netstat发现大量的ACK被丢弃后,可以通过listen()函数提高accept队列的上限。
  8. TFO可以让HTTP请求减少一个RTT的时间。

实际情况:

image.png
image.png
image.png
image.png
image.png
image.png

你可能感兴趣的:(TCP三次握手如何优化)