参数是干什么的
net.ipv4.tcp_notsent_lowat 设定发送队列中未发送字节数的阈值:只有当未发送数据低于该值时,内核才向应用报告「可写」(select/poll/epoll 返回可写)。默认 -1 表示不限制。它的用途是抑制缓冲膨胀——限制内核里排队等待发送的数据量,让应用跟随网络的实际发送速度推进,从而降低延迟,代价是在大流量场景下可能限制吞吐。
基本信息
| 系统参数 | net.ipv4.tcp_notsent_lowat(默认 -1,不限制) |
|---|---|
| 应用侧选项 | TCP_NOTSENT_LOWAT,可按单个连接设置 |
| 观测方式 | ss -ti 输出中的 notsent 字段 |
| 相关参数 | net.ipv4.tcp_wmem(发送缓冲的自动调优范围) |
| 适用平台 | Linux(需要内核支持该 sysctl) |
| 影响面 | 改变的是「何时通知应用可写」,不改变拥塞控制 |
典型使用场景
- 延迟敏感的代理、网关与推送服务:限制内核排队数据以压低响应时间
- 排查「应用写很快、客户端收很慢」的缓冲膨胀问题
- 与 SO_SNDBUF 配合控制进程的内存占用上限
- 按连接精细控制:只对延迟敏感的业务连接设置该选项
- 长尾延迟分析时观察 notsent 是否长期偏高,判断排队位置
查看与设置
查看与设置
sysctl net.ipv4.tcp_notsent_lowat # 查看全局值,-1 表示不限制
ss -tin dst :8080 # 关注 notsent: 与 skmem 中的发送排队量
printf 'net.ipv4.tcp_notsent_lowat = 131072\n' > /etc/sysctl.d/90-notsent.conf # 全局设为 128KB
sysctl --system # 重新加载并复核
# 应用侧按连接设置(C 语言示意):
# int val = 65536; setsockopt(fd, IPPROTO_TCP, TCP_NOTSENT_LOWAT, &val, sizeof(val));
sysctl net.ipv4.tcp_wmem # 同时确认发送缓冲范围,两者需要配合观测项读法
| 观测项 | 含义 | 判读要点 |
|---|---|---|
| notsent | 该连接未发送的字节数 | 长期偏高说明数据积在内核里 |
| skmem 的 tb/rb | 发送与接收缓冲上限 | 确认是否被系统上限截断 |
| skmem 的 t/r | 当前收发排队字节数 | 与 notsent 一起判断排队位置 |
| cwnd / rtt | 拥塞窗口与往返时间 | 用于判断发送受限是否来自网络 |
该参数只影响「应用何时被通知可写」,不能替代拥塞控制:如果对端读取慢或网络本身受限,未发送数据仍会积压,只是应用会更早被阻塞而不是把数据推进缓冲。
阈值设得过小会限制吞吐:发送方频繁被阻塞、带宽利用下降,在大文件传输或高吞吐代理上尤其明显。全局调整前先确认应用是否已按连接设置,并以压测数据为依据。