配色: 字号:
智汇华云:浅谈TCP优化
2022-10-20 | 阅:  转:  |  分享 
  
智汇华云 | 浅谈TCP优化背景我们在日常开发中经常会使用到TCP相关技术,但我们往往不会去关心TCP连接本身,下面会给大家介绍一下TCP的
一些优化点。TCP 协议是由操作系统实现,所以操作系统提供了不少调节 TCP 的参数。如何正确有效的使用这些参数,我们可以从TCP
三次握手来提升TCP的性能。TCP三次握手的性能提升我们知道TCP 是面向连接的、可靠的、双向传输的传输层通信协议,在传输数据之前
需要经过三次握手才能建立连接。三次握手的过程在一个 HTTP 请求的平均时间占比 10% 以上,在网络状态不佳、高并发或者遭遇 S
YN 攻击等场景中,如果不能有效正确的调节三次握手中的参数,就会对性能产生很多的影响。如何正确有效的使用这些参数,来提高 TCP
三次握手的性能,这就需要理解”三次握手的状态变迁”,这样当出现问题时,先用?netstat命令查看是哪个握手阶段出现了问题客户端和
服务端都可以针对三次握手优化性能,但优化方式不同,接下来分别针对客户端和服务端介绍一下如何进行优化客户端优化三次握手建立连接的首要
目的是「同步序列号」。只有同步了序列号才有可靠传输,TCP 许多特性都依赖于序列号实现,比如流量控制、丢包重传等,这也是三次握手中
的报文称为 SYN 的原因。客户端作为主动发起连接方,首先它将发送 SYN 包,于是客户端的连接就会处于?SYN_SENT?状态。
客户端在等待服务端回复的 ACK 报文,正常情况下,服务器会在几毫秒内返回 SYN+ACK ,但如果客户端长时间没有收到 SYN+
ACK 报文,则会重发 SYN 包,重发的次数由 TCP_syn_retries 参数控制,默认是 5 次。通常,第一次超时重传是
在 1 秒后,第二次超时重传是在 2 秒,第三次超时重传是在 4 秒后,第四次超时重传是在 8 秒后,第五次是在超时重传 16 秒
后。没错,每次超时的时间是上一次的 2 倍。当第五次超时重传后,会继续等待 32 秒,如果服务端仍然没有回应 ACK,客户端就会终
止三次握手。所以,总耗时是 1+2+4+8+16+32=63 秒,大约 1 分钟左右。可以根据网络的稳定性和目标服务器的繁忙程度修
改 SYN 的重传次数,调整客户端的三次握手时间上限。比如内网中通讯时,就可以适当调低重试次数,尽快把错误暴露给应用程序。服务端优
化服务端收到 SYN 包后,服务端会立马回复 SYN+ACK 包,表明确认收到了客户端的序列号,同时也把自己的序列号发给对方。此时
,服务端出现了新连接,状态是?SYN_RCV。在这个状态下,Linux 内核就会建立一个「半连接队列」来维护「未完成」的握手信息,
当半连接队列溢出后,服务端就无法再建立新的连接。我们可以通过该?netstat -s?命令给出的统计结果中, 可以得到由于半连接队
列已满,引发的失败次数,若失败次数一直增加,那我们需要增加半连接对了。要想增大半连接队列,不能只单纯增大tcp_max_syn_b
acklog 的值,还需一同增大 somaxconn 和 backlog,也就是增大 accept 队列。否则,只单纯增大 tcp
_max_syn_backlog 是无效的。增大 tcp_max_syn_backlog 和 somaxconn 的方法是修改 L
inux 内核参数:增大 backlog 的方式,每个 Web 服务都不同,比如 Nginx 增大 backlog 的方法如下:改
变了如上这些参数后,要重启 Nginx 服务,因为 SYN 半连接队列和 accept 队列都是在?listen()?初始化的。S
YN_RCV状态的优化客户端接收到服务器发来的 SYN+ACK 报文后,就会回复 ACK 给服务器,同时客户端连接状态从 SYN_
SENT 转换为 ESTABLISHED,表示连接建立成功。服务器端连接成功建立的时间还要再往后,等到服务端收到客户端的 ACK
后,服务端的连接状态才变为 ESTABLISHED。如果服务器没有收到 ACK,就会重发 SYN+ACK 报文,同时一直处于 SY
N_RCV 状态。当网络繁忙、不稳定时,报文丢失就会变严重,此时应该调大重发次数。反之则可以调小重发次数。修改重发次数的方法是,调
整 tcp_synack_retries 参数:tcp_synack_retries 的默认重试次数是 5 次,与客户端重传 SY
N 类似,它的重传会经历 1、2、4、8、16 秒,最后一次重传后会继续等待 32 秒,如果服务端仍然没有收到 ACK,才会关闭连
接,故共需要等待 63 秒。服务器收到 ACK 后连接建立成功,此时,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其
添加到 accept 队列,等待进程调用 accept 函数时把连接取出来。Accept队列调整丢弃连接只是 Linux 的默认行
为,我们还可以选择向客户端发送 RST 复位报文,告诉客户端连接已经建立失败。打开这一功能需要将 tcp_abort_on_ove
rflow 参数设置为 1。tcp_abort_on_overflow 共有两个值分别是 0 和 1,其分别表示:0 :如果 ac
cept 队列满了,那么 server 扔掉 client 发过来的 ack ;1 :如果 accept 队列满了,server
发送一个?RST?包给 client,表示废掉这个握手过程和这个连接;如果要想知道客户端连接不上服务端,是不是服务端 TCP 全连
接队列满的原因,那么可以把tcp_abort_on_overflow 设置为 1,这时如果在客户端异常中可以看到很多?connec
tion reset by peer?的错误,那么就可以证明是由于服务端 TCP 全连接队列溢出的问题。通常情况下,应当把 tcp
_abort_on_overflow 设置为 0,因为这样更有利于应对突发流量。所以,tcp_abort_on_overflow
设为 0 可以提高连接建立的成功率,只有你非常肯定 TCP 全连接队列会长期溢出时,才能设置为 1 以尽快通知客户端。总结TCP优化三次握手可以从四个角度入手出发进行调整,调整SYN报文的重传次数、调整SYN半连接队列长度、调整SYN+ACK报文的重传次数、调整accpet队列长度。
献花(0)
+1
(本文系他不懂你的...首藏)