前言:
Linux系统的tcp相关的参数主要保存在: /proc/sys/net/ipv4/
常见参数理解与配置:
- tcp_syn_retries 控制 SYN 包重传的次数,默认是6次(Ubuntu16.04)
- tcp_max_syn_backlog 与最大半连接有关
- somaxconn 与最大全连接有关(全连接还与 listen 函数调用的第二个参数有有关)
- syncookies 是否弃用 syn 的 cookie 功能(1:开启)
- tcp_abort_on_overflow 控制当 accept 队列已满之后,针对 ack 的回应(0:丢弃客户端发过来的 ack;1:收到客户端的 ack 之后,返回一个 RST 给客户端)
- tcp_fastopen 开启 tcp 的快速连接(第一次还是三次握手,但是由于有 cookie,所以之后可以跳过 3 次握手)tcp_fastopn 各个值的意义:(0 关闭;1 作为客户端使用 Fast Open 功能;2 作为服务端使用 Fast Open 功能;3 无论作为客户端还是服务器,都可以使用 Fast Open 功能;)TCP Fast Open 功能需要客户端和服务端同时支持,才有效果。
主动方的优化
主动发起 FIN 报文断开连接的一方,如果迟迟没收到对方的 ACK 回复,则会重传 FIN 报文,重传的次数由 tcp_orphan_retries
参数决定。
当主动方收到 ACK 报文后,连接就进入 FIN_WAIT2 状态,根据关闭的方式不同,优化的方式也不同:
- 如果这是 close 函数关闭的连接,那么它就是孤儿连接。如果
tcp_fin_timeout
秒内没有收到对方的 FIN 报文,连接就直接关闭。同时,为了应对孤儿连接占用太多的资源,tcp_max_orphans
定义了最大孤儿连接的数量,超过时连接就会直接释放。 - 反之是 shutdown 函数关闭的连接,则不受此参数限制;
当主动方接收到 FIN 报文,并返回 ACK 后,主动方的连接进入 TIME_WAIT 状态。这一状态会持续 1 分钟,为了防止 TIME_WAIT 状态占用太多的资源,tcp_max_tw_buckets
定义了最大数量,超过时连接也会直接释放。
当 TIME_WAIT 状态过多时,还可以通过设置 tcp_tw_reuse
和 tcp_timestamps
为 1 ,将 TIME_WAIT 状态的端口复用于作为客户端的新连接,注意该参数只适用于客户端。
被动方的优化
被动关闭的连接方应对非常简单,它在回复 ACK 后就进入了 CLOSE_WAIT 状态,等待进程调用 close 函数关闭连接。因此,出现大量 CLOSE_WAIT 状态的连接时,应当从应用程序中找问题。
当被动方发送 FIN 报文后,连接就进入 LAST_ACK 状态,在未等到 ACK 时,会在 tcp_orphan_retries
参数的控制下重发 FIN 报文。
数据传输的优化策略
TCP 可靠性是通过 ACK 确认报文实现的,又依赖滑动窗口提升了发送速度也兼顾了接收方的处理能力。
可是,默认的滑动窗口最大值只有 64 KB,不满足当今的高速网络的要求,要想提升发送速度必须提升滑动窗口的上限,在 Linux 下是通过设置 tcp_window_scaling
为 1 做到的,此时最大值可高达 1GB。
滑动窗口定义了网络中飞行报文的最大字节数,当它超过带宽时延积时,网络过载,就会发生丢包。而当它小于带宽时延积时,就无法充分利用网络带宽。因此,滑动窗口的设置,必须参考带宽时延积。
内核缓冲区决定了滑动窗口的上限,缓冲区可分为:发送缓冲区 tcp_wmem 和接收缓冲区 tcp_rmem。
Linux 会对缓冲区动态调节,我们应该把缓冲区的上限设置为带宽时延积。发送缓冲区的调节功能是自动打开的,而接收缓冲区需要把 tcp_moderate_rcvbuf 设置为 1 来开启。其中,调节的依据是 TCP 内存范围 tcp_mem。
但需要注意的是,如果程序中的 socket 设置 SO_SNDBUF 和 SO_RCVBUF,则会关闭缓冲区的动态整功能,所以不建议在程序设置它俩,而是交给内核自动调整比较好。
有效配置这些参数后,既能够最大程度地保持并发性,也能让资源充裕时连接传输速度达到最大值。