业务进程正常、已有长连接还能传输,新请求却间歇超时,这类现象不一定来自应用监听队列。物理主机承担状态防火墙或网络地址转换(NAT)时,Linux 的连接跟踪表也可能成为瓶颈。排查重点是把失败时刻、表占用与内核计数对齐,而不是看到连接多就直接扩大上限。
本文以 Debian 13 为例,所有检查在宿主的网络命名空间执行。CloudUDP 机器付款后在控制台查看凭据,Linux 通过 SSH 接入;多个地址时使用第一个地址连接。以下操作不修改网络规则,也不清空现有连接状态。
一、确认故障经过连接跟踪路径
连接跟踪(conntrack)记录通信流的协议、地址、状态与超时,供状态匹配和 NAT 使用。一条业务连接不等于一个应用线程,表项还可能在应用关闭连接后保留一段时间。短连接密集创建、异常扫描或转发负载,都可能推高占用。
先安装检查工具并读取配置:
sudo apt-get update
sudo apt-get install conntrack
sysctl net.netfilter.nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max
sudo conntrack -S
sudo nft list ruleset
规则中出现 ct state 或 NAT,是需要关注跟踪容量的线索,但没有这些规则也不能证明完全不跟踪。若读取参数提示不存在,应先确认模块和实际流量路径,不为“补齐输出”盲目加载模块。
容器内的结果不能直接代替宿主结果。宿主转发和容器内部可能经过不同命名空间,必须记录命令执行位置;否则容易用容器的低占用解释宿主的丢包。
不执行
conntrack -F作为常规恢复手段。清表会移除既有状态,可能破坏依赖状态匹配或 NAT 的会话,还会让原本需要保留的现场证据消失。
二、采集同一时间段的占用与错误增量
nf_conntrack_count 是当前表项数,nf_conntrack_max 是容量上限。接近上限说明余量减少,却不能单独证明请求因此失败。conntrack -S 按处理器输出统计,应逐项求和并比较两次采样的差值,不把某一行当作整机总量。
umask 077
out=$(mktemp -d /var/tmp/ct-check.XXXXXX)
for sample in 1 2; do
{
date -Is
sysctl net.netfilter.nf_conntrack_count
sysctl net.netfilter.nf_conntrack_max
sudo conntrack -S
} > "$out/sample-$sample.txt"
if [ "$sample" -eq 1 ]; then
sleep 10
fi
done
sudo journalctl -k --since "-10 min" --no-pager \
> "$out/kernel.txt"
printf '%s\n' "$out"
这里的采样间隔只是操作示例,应覆盖业务失败发生的时段。重点关注 insert_failed、drop、early_drop 是否持续增加,以及内核是否出现连接表满的提示。字段随内核版本可能不同,不能因缺少某个字段就认定系统正常。
同时保存应用的新连接失败数、请求量与错误原文。若机器刚重启,累计计数的基准已经变化;不要把重启前后的数值直接相减。低峰时错误计数不再增加,也不代表高峰容量已经通过验收。
三、判断表项为何积累
先区分“正常并发增长”和“异常创建速度”。对照入口请求、应用主动建立的外连、转发业务及连接复用情况。大量短连接即使存活时间不长,也会因创建速率高而积累;长连接则更依赖真实并发规模。
避免把全表导出当作第一步
繁忙主机上,完整列举表项本身会增加排查开销,输出还包含通信地址。先读汇总计数,确有需要再限制协议和输出规模:
sudo timeout 5s conntrack -L -p tcp -o extended 2>/dev/null \
| head -n 100
这段输出只是有偏样本,不是状态分布统计。超时或管道提前关闭也可能使命令非零退出,不能据此判断表损坏。地址记录只保存在受限目录,提交工单前先移除无关业务信息。
还应同步检查监听进程、应用错误和上游响应。若占用有余量、相关计数没有增长,应转向应用阻塞、路由或其他丢包位置,不继续围绕 conntrack 调参。
不要先缩短全部协议的超时。超时决定空闲连接状态保留多久,过度压缩可能影响长连接;连接池未复用、失败重试失控等问题,应在调用方修复。
四、按内存预算实施可回退变更
扩大上限只是允许更多表项存在,并不修复异常流量来源。表项消耗内核内存,具体开销受协议扩展、内核配置等影响,不能用固定“每条若干字节”计算精确预算。
变更前记录 free -h、/proc/meminfo,并用 sudo slabtop -o 观察内核对象缓存。Slab 是内核用于管理对象的缓存机制;其中的连接跟踪对象统计也不是全部相关内存成本。
若证据支持容量不足,且内存有余量,可用小步调整验证。以下将原上限增加四分之一,仅为试验幅度,不是推荐固定配置:
old=$(sysctl -n net.netfilter.nf_conntrack_max) || exit 1
case "$old" in
''|*[!0-9]*) exit 1 ;;
esac
new=$((old + old / 4))
printf 'old=%s new=%s\n' "$old" "$new"
sudo sysctl -w net.netfilter.nf_conntrack_max="$new"
保留该会话和原值,在相近请求量下重新采样。失败没有改善时,不连续加大参数;恢复原值并检查其他证据:
sudo sysctl -w net.netfilter.nf_conntrack_max="$old"
回退前核对当前占用,若已超过原上限,应先降低新增连接压力,否则回退可能再次触发容量问题。不要同时调整哈希桶、协议超时和防火墙规则,避免失去单变量验证条件。
五、用业务结果决定是否持久化
验收必须同时满足三类证据:相近业务量下新连接成功率恢复,相关错误计数不再持续增长,内存与内核对象缓存没有出现新的压力。只有占用率下降,不能算修复完成。
确认有效后,将已验证的数字写入 /etc/sysctl.d/90-conntrack-capacity.conf。写入前检查其他配置文件是否重复定义同一参数,避免加载顺序覆盖。只加载本次文件,不顺带应用整机其他未验证配置:
sudo sysctl -p /etc/sysctl.d/90-conntrack-capacity.conf
sysctl net.netfilter.nf_conntrack_max
文件应包含一行 net.netfilter.nf_conntrack_max = 已验证的整数,其中说明文字必须替换为实际数字。下一次由运维安排的重启后,再核对生效值与加载错误,不为验证参数立即重启生产机器。
最后留存原值、新值、采样区间、请求量、计数差值和回退条件。连接跟踪容量治理的终点不是更大的数字,而是能解释连接失败、能证明变更有效,并能在负载变化后重新检查同一组证据。
常见问题
conntrack 占用接近上限,是否就能认定发生了耗尽?
不能。应结合相同时间段内的 insert_failed、drop、early_drop 计数增量、内核日志和业务新连接错误判断。占用率高只是容量风险信号,单项计数也不能独立确定根因。
能否通过清空 conntrack 表快速恢复业务?
不应把清表作为常规恢复手段。清空会移除现有连接的跟踪状态,可能破坏依赖状态匹配或 NAT 的会话。应先留存计数与日志,再处理异常连接来源或实施有内存预算的容量调整。
EPYC 7543P 独享物理主机,$454/月起