前言:
    Linux系统的tcp相关的参数主要保存在: /proc/sys/net/ipv4/

    常见参数理解与配置:

    1. tcp_syn_retries 控制 SYN 包重传的次数,默认是6次(Ubuntu16.04)
    2. tcp_max_syn_backlog 与最大半连接有关
    3. somaxconn 与最大全连接有关(全连接还与 listen 函数调用的第二个参数有有关)
    4. syncookies 是否弃用 syn 的 cookie 功能(1:开启)
    5. tcp_abort_on_overflow 控制当 accept 队列已满之后,针对 ack 的回应(0:丢弃客户端发过来的 ack;1:收到客户端的 ack 之后,返回一个 RST 给客户端)
    6. tcp_fastopen 开启 tcp 的快速连接(第一次还是三次握手,但是由于有 cookie,所以之后可以跳过 3 次握手)tcp_fastopn 各个值的意义:(0 关闭;1 作为客户端使用 Fast Open 功能;2 作为服务端使用 Fast Open 功能;3 无论作为客户端还是服务器,都可以使用 Fast Open 功能;)TCP Fast Open 功能需要客户端和服务端同时支持,才有效果。

    TCP参数理解 - 图1

    TCP参数理解 - 图2

    主动方的优化

    主动发起 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_reusetcp_timestamps 为 1 ,将 TIME_WAIT 状态的端口复用于作为客户端的新连接,注意该参数只适用于客户端。

    被动方的优化

    被动关闭的连接方应对非常简单,它在回复 ACK 后就进入了 CLOSE_WAIT 状态,等待进程调用 close 函数关闭连接。因此,出现大量 CLOSE_WAIT 状态的连接时,应当从应用程序中找问题。
    当被动方发送 FIN 报文后,连接就进入 LAST_ACK 状态,在未等到 ACK 时,会在 tcp_orphan_retries 参数的控制下重发 FIN 报文。

    TCP参数理解 - 图3

    数据传输的优化策略

    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,则会关闭缓冲区的动态整功能,所以不建议在程序设置它俩,而是交给内核自动调整比较好。

    有效配置这些参数后,既能够最大程度地保持并发性,也能让资源充裕时连接传输速度达到最大值。