本文目录导读:

- 核心概念:自动 Corking 与 MSS 阈值
- 如何通过 MSS 阈值控制它?
- 它与实际 MSS 大小(MSS Cache)的关系
- 总结:如何通过 MSS 进行控制?
- 代码层面的实现(内核源码参考)
- 实践建议
在 Linux 内核中,tcp_autocorking 与 MSS (Maximum Segment Size,最大报文段长度) 的交互,主要是通过一个名为 tcp_autocork_mss 的阈值来实现的。
tcp_autocork_mss 并不是直接设置 MSS 的大小,而是设置一个 MSS 数量 的阈值,用于决定是否触发自动 Cork(塞子)机制。
下面我们来详细拆解这个机制和 MSS 的关系:
核心概念:自动 Corking 与 MSS 阈值
-
自动 Corking 的作用:当应用程序多次调用
send()发送小块数据时,内核不会立即发送每个小块,而是将它们暂存在发送缓冲区中,等待累积到一定量后再一次性发出,这可以减少小包(尤其是纯 ACK 包)的数量,提高网络吞吐量。 -
tcp_autocork_mss的含义:- 它不是一个绝对值(1460 字节)。
- 它是一个 MSS 的倍数。
- 默认值是 0,当值为 0 时,自动 Corking 被禁用。
- 生效机制:当内核决定是否开始“自动塞子”时,它会检查一个条件,在
tcp_sendmsg()或tcp_push()等函数中,内核会检查:如果发送缓冲区中已经有数据,并且这些数据的长度加上新写入的数据长度,除以tcp_sk(sk)->mss_cache得到的整数部分大于或等于 1,那么就会触发自动 Corking。
这个逻辑可以简化理解为:如果当前待发送的数据量已经超过了一个 MSS,内核会认为值得开启 Cork 来合并后续的写入。
如何通过 MSS 阈值控制它?
在 Linux 内核中,这个阈值是通过 sysctl 参数 net.ipv4.tcp_autocork_mss 来设置的。
-
获取当前值:
sysctl net.ipv4.tcp_autocork_mss # 通常输出: net.ipv4.tcp_autocork_mss = 0 (默认禁用)
-
修改值:
# 设置为3,意味着当待发送数据达到3个MSS时,才开始自动Corking。 sudo sysctl -w net.ipv4.tcp_autocork_mss=3
它与实际 MSS 大小(MSS Cache)的关系
实际的 MSS 大小(mss_cache)由连接建立时的 SYN/SYN-ACK 协商决定(通常是 1460 字节,取决于 MTU)。
-
当
tcp_autocork_mss= 1 时:mss_cache= 1460 字节。- 只要内核发现缓冲区中已有
> 1460字节的数据,就会开启自动 Cork,等待后续写入后一次性发送,这通常能很好地平衡延迟和吞吐量。
-
当
tcp_autocork_mss= 3 时:mss_cache= 1460 字节。- 内核需要看到缓冲区中已累积
> 3 * 1460 = 4380字节的数据才触发 Cork,这会强制让应用程序合并更多的写入,但可能会增加单个 TCP 段的发送延迟。
如何通过 MSS 进行控制?
你不能直接设置一个“MSS 字节数”作为阈值,内核暴露的控制参数是 tcp_autocork_mss,它是一个 MSS 的计数。
- 禁用自动 Corking:
sysctl -w net.ipv4.tcp_autocork_mss=0 - 启用一个保守的策略(最少攒一个 MSS 再发):
sysctl -w net.ipv4.tcp_autocork_mss=1(推荐,平衡延迟和吞吐量) - 启用更激进的合并策略(攒多个 MSS 再发):
sysctl -w net.ipv4.tcp_autocork_mss=3或更高(可能增加延迟,但减少小包)
代码层面的实现(内核源码参考)
在 Linux 内核源码 net/ipv4/tcp.c 的 tcp_should_autocork() 函数中,逻辑大致如下(简化):
static bool tcp_should_autocork(struct sock *sk, struct sk_buff *skb,
int size_goal)
{
struct tcp_sock *tp = tcp_sk(sk);
int mss = tcp_sk(sk)->mss_cache;
// sysctl_tcp_autocork_mss 为 0,直接返回 false
if (!sysctl_tcp_autocork_mss)
return false;
// 关键条件:检查发送队列中已有数据的长度
// 使用 skb_queue_len(&sk->sk_write_queue) 获取队列中 skb 的数量
// 但更核心的是判断当前累积的字节数是否达到了 mss * sysctl_tcp_autocork_mss
// 以下是简化版逻辑
return (tp->write_seq - tp->snd_nxt) > (sysctl_tcp_autocork_mss * mss);
}
实践建议
- 对于大多数通用场景,保持默认值
0或设置为1是合理的。 - 如果你的应用是小块写入、高频发送(例如游戏服务器、流媒体),建议设置为
1,可以有效合并小包。 - 如果你的应用是低延迟优先,且每个
send()本身就很大,可以保持0(禁用),避免不必要的等待。 - 设置的值不要过大,否则会导致发送延迟显著增加,影响交互性,通常不超过
3。
一句话总结:tcp_autocork_mss 不是设置 MSS 的字节数,而是设置一个 MSS 的计数阈值,用来控制 TCP 自动塞子机制何时开启。
标签: MSS