Skip to main content

rulr-4 / rulr-5 的问题拆解

下面我按**“conntrack异常 + 网络路径 + Docker/iptables结构 + 差异对比”**四个层面,把 rulr-4 / rulr-5 的问题拆解清楚,并给出结论。


一、核心结论(先说重点)

两台机器的共同问题是:

1)conntrack “命中正常但插入完全失败”

两台都有典型特征:

  • insert=0

  • insert_failed 极高

  • drop == insert_failed 完全一致

👉 说明不是“丢包问题”,而是:

conntrack 表处于高压/冲突/不可插入状态(典型:hash冲突 + 表竞争 + bucket/GC压力)


2)流量结构是“Docker NAT + 高并发短连接”

特征:

  • eth0 PPS:1300~3500 pps

  • Docker bridge 转发活跃

  • conntrack found 数量极高(十亿级累计)

  • TIME_WAIT / Established 很低(说明短连接或代理转发)

👉 本质是:

L4 NAT代理(nginx tcp / docker DNAT)+ 高频连接建立/释放


3)CPU级 conntrack drop 在8核上均匀爆炸

例如 rulr-5:

  • cpu0~cpu7 drop:1,000万~2,100万级

  • search_restart大量存在

👉 说明:

不是单核问题,是全局 hash table 争用 / bucket 冲突 / lock竞争


二、关键异常点拆解

1. conntrack insert_failed = drop(100%一致)

rulr-4

insert_failed=7390187
drop=7390187

rulr-5

insert_failed=14861324
drop=14861324

👉 结论非常关键:

conntrack 新连接“完全无法建立状态记录”

但:

  • found 极高 → 查询是正常的

  • 说明:已有连接还能用,但新流状态创建失败


2. nf_conntrack 参数异常点

rulr-4

nf_conntrack_tcp_timeout_established = 3600

rulr-5

nf_conntrack_tcp_timeout_established = 86400

👉 rulr-5 风险更高:

  • 86400 = 24小时

  • 连接表保留时间过长

影响:

conntrack table “存活连接暴涨 + hash压力持续累积”


3. NAT/iptables结构问题(非常关键)

两台都有:

DNAT + MASQUERADE + Docker bridge

例如 rulr-5:

POSTROUTING MASQUERADE (172.18.0.0/16)
DNAT 80/443/6100-6109 → 172.18.0.200

👉 这是典型:

“Docker NAT + 端口代理 + 二次转发”结构

问题在于:

❗ 双重NAT路径

Client → eth0 → PREROUTING DNAT → Docker bridge → container
                       ↓
                conntrack 记录创建

再叠加:

  • nginx tcp proxy

  • 多端口转发(6011-6109)

  • RabbitMQ / Redis / ZK

👉 结果:

conntrack entry 数量爆炸 + hash冲突概率指数级上升


4. eth0 TX queue backlog(重要信号)

两台都看到:

tx_send_full: 88000~94000+

含义:

NIC TX ring 有阻塞 / 发送队列曾经满过

👉 说明:

  • CPU侧处理不过来 or softirq拥塞

  • 或 conntrack/iptables路径延迟导致回压


5. RPS / IRQ 分布异常

/sys/class/net/eth0/queues/rx-*/rps_cpus = 00

👉 这是非常关键问题:

RPS(Receive Packet Steering)完全未启用

结果:

  • 所有流量集中在少数 CPU softirq

  • conntrack lock contention 加剧

  • hash table 并发冲突更严重


三、两台机器差异对比

项目 rulr-4 rulr-5 结论
conntrack timeout 3600 86400 rulr-5更危险
insert_failed 739万 1486万 rulr-5更严重
网络PPS ~1300 ~3500 rulr-5负载更高
docker网络 2个bridge 1个bridge rulr-5更集中
CPU drop 均衡 更高 rulr-5更拥塞
RPS 未启用 未启用 两台共同瓶颈

四、根因总结(核心3点)

根因1:conntrack hash table 进入高冲突状态

表现:

  • insert_failed暴涨

  • search_restart大量

  • drop == insert_failed

👉 本质:

bucket冲突 + 竞争锁 + CPU并发访问


根因2:Docker NAT + 高端口映射放大状态表压力

你现在是:

  • nginx tcp proxy

  • 10+端口区间映射

  • redis/rabbit/zookeeper

  • 统一 NAT

👉 典型放大效应:

每个连接 = 2~3个 conntrack entry


根因3:没有RPS/RFS,CPU softirq 单点瓶颈

导致:

  • conntrack lock 争用加剧

  • packet processing 串行化

  • insert失败概率上升


五、优化建议(按优先级)

⭐ P0(必须做)

1. 开启 RPS(立刻见效)

for i in /sys/class/net/eth0/queues/rx-*/rps_cpus; do
    echo ff > $i
done

2. 调整 conntrack hashsize(如果允许)

sysctl -w net.netfilter.nf_conntrack_max=2097152

并确认:

/sys/module/nf_conntrack/parameters/hashsize

⭐ P1(结构优化)

3. 缩短 conntrack 生命周期(rulr-5必须改)

net.netfilter.nf_conntrack_tcp_timeout_established=3600

或更低(代理场景建议 600~1800)


4. 减少 Docker NAT 层级

建议:

  • host network(关键服务)

  • 或减少 DNAT 端口范围


⭐ P2(架构级)

5. nginx tcp proxy 优化

  • 减少长连接 NAT

  • 开启 upstream keepalive

  • 减少 conntrack churn


6. 考虑 bypass conntrack(高级)

对纯转发流量:

iptables -t raw -A PREROUTING -j NOTRACK

⚠️ 需谨慎(会影响 NAT/stateful firewall)


六、最终判断

两台机器的本质问题不是“性能不够”,而是:

conntrack + Docker NAT + 高PPS流量 + RPS未开启 → 状态表锁竞争崩溃


如果你下一步想继续深入

我可以帮你做三件更关键的分析:

1)判断是否 conntrack hash bucket 已经“爆桶”

2)计算你当前 conntrack 实际容量 vs 使用率

3)给出一套“代理服务器最优内核参数模板(8C/16C通用)”

只要你说一句“继续深入”,我可以把瓶颈定位到更精确的 kernel 层级。

你这个“清零问题”,需要先把一个关键点讲清楚:

conntrack -S 不是计数器日志,而是 内核全局累积统计(since boot)

所以你看到的:

  • drop

  • insert_failed

  • search_restart

  • found

👉 都是内核启动以来的累计值(cumulative counters)


一、结论:不能“直接清零 conntrack -S”

Linux conntrack 统计来自:

/proc/sys/net/netfilter/nf_conntrack_stats

或者内核内部 struct nf_conntrack_stat

👉 没有 reset / clear 接口


二、你想要的“清零”,只有3种方法

方法1(唯一真正清零):重载 nf_conntrack 模块

⚠️ 会影响所有 NAT / Docker / 连接状态(生产慎用)

步骤:

systemctl stop docker
conntrack -F

然后:

modprobe -r nf_conntrack
modprobe nf_conntrack

再启动 docker:

systemctl start docker

或更干净方式:

reboot

👉 这是唯一“真正意义上的清零”


三、方法2(推荐生产):只清“连接表”,不清统计

你可以这样:

conntrack -F

效果:

项目是否清零
conntrack entries✔ 清空
drop统计❌ 不变
insert_failed❌ 不变

👉 你现在的问题就是属于:

❗ “统计污染”,不是“连接污染”


四、方法3(推荐):看“增量”,不要看绝对值

你现在的问题其实是:

❌ 被历史累计值误导

正确方式是:

做 delta 采样:

watch -n 1 conntrack -S

但重点是:

👉 看“每秒增长量”,不是绝对值

例如:

drop +1200 / sec  → ❌异常
drop +10 / sec    → 正常

五、你现在这个系统的真实问题(重点)

你这两台机器:

❗ conntrack 已经不是“统计问题”,是结构性问题

因为:

  • insert = 0(长期)

  • insert_failed持续增长

  • drop = insert_failed(100%一致)

👉 说明:

❗ conntrack “一直在失败,但失败已经稳定化”

也就是说:

✔ 不是现在在炸

❗ 是一直在“稳定性失败状态运行”


六、为什么你“感觉数字不动”

你看到:

conntrack -S 多次执行数值变化很小

原因:

1)计数器太大(十亿级)

小增量肉眼不可见

2)系统已经进入 steady-state failure

  • 每秒失败量 ≈ 恒定

  • 看起来“没变化”


七、建议你不要做“清零”,而是做这个

⭐ 正确做法:做“差值监控”

示例脚本(关键)

#!/bin/bash
a=$(conntrack -S | grep insert_failed | awk '{print $2}' | paste -sd+ - | bc)
sleep 1
b=$(conntrack -S | grep insert_failed | awk '{print $2}' | paste -sd+ - | bc)

echo "delta=$((b-a))"

八、如果你坚持要“重置统计”(高级)

可以用 debugfs(部分内核支持):

echo 0 > /proc/sys/net/netfilter/nf_conntrack_count

❌ 但注意:

  • 大多数系统无效

  • 不会清统计


九、最终建议(非常重要)

你现在真正应该做的不是清零,而是:

🔥 必修3件事

1)开启 RPS(你当前是 00)

这是最大瓶颈之一

2)降低 conntrack timeout(rulr-5必须)

86400 → 3600 或更低

3)检查 conntrack max / hashsize 是否不足


十、总结一句话

❗ conntrack -S 是“历史账本”,不能清,只能换本子(重启),或者开始看“增量变化”。


如果你下一步想做深入定位,我可以帮你直接算:

  • 当前 conntrack 是否“接近 hash bucket 饱和”

  • insert_failed 对应的实际丢连接比例

  • 是否已经进入 “conntrack collapse 模式”

只要你说一句:继续分析瓶颈根因 👍

你现在看到的 conntrack -S 现象,本质是**“计数器持续递增 + drop/insert_failed长期固定高位”**,但你误判成“历史积累无法清零”。

结论先说清楚:

❗这些不是“日志”,而是 内核 nf_conntrack 全局统计计数器(per-CPU cumulative counters)
❗无法通过 conntrack 命令“清零”,只能通过重置模块或重启系统/重载模块

但更关键的是:真正的问题不是“不能清零”,而是 drop/insert_failed 为什么一直在高位持续增长。


一、你看到的现象本质是什么

以这一类字段为例:

insert_failed=7390187
drop=7390187
invalid=148279
search_restart=1061998

特点:

1)insert_failed == drop(几乎完全一致)

说明:

❗所有插入失败事件都被直接丢弃(drop=insert_failed)

通常意味着:

  • conntrack 表压力/资源不足

  • hash冲突严重

  • 表满或接近满

  • 或内核无法为新流分配 entry


2)invalid 持续增长

说明:

  • 收到不完整/异常包

  • NAT后的回包找不到 entry

  • 或 timeout/GC/flush导致状态丢失


3)search_restart 很高

这是关键指标之一:

❗hash桶冲突严重,查找发生 rehash / retry

典型原因:

  • bucket过少(或 hashsize不合理)

  • 流量过于集中(DDoS/四层代理/连接风暴)

  • CPU softirq压力高


二、核心瓶颈根因(按概率排序)

结合你 r4 / r5 的数据(r5明显更严重):


🟥 根因1:conntrack hash 冲突严重(高概率)

你之前已经看到:

nf_conntrack_buckets = 1048576
hashsize = 1048576

看似很大,但问题是:

❗如果连接分布不均(热点IP/端口),1M bucket 也会严重冲突

典型场景:

  • NAT网关 / 反向代理 / LB

  • 游戏/IM/短连接系统

  • 微服务 HTTP flood

  • 内网扫描/重连风暴

👉 结果:

  • search_restart 飙升

  • insert_failed 增加

  • drop同步增长


🟥 根因2:conntrack table pressure(表压力/接近满)

检查关键指标:

cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max

如果:

count ≈ max * 70%~90%

就会出现:

  • insert_failed

  • drop

  • early_drop(你这里暂时不高,但可能被 GC 抵消)


🟥 根因3:GC(垃圾回收)压力过高

你没有看到 early_drop,但不代表没有问题:

可能存在:

  • GC thread CPU吃满

  • timeout过短导致频繁回收

  • LRU churn严重

检查:

cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established
cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_time_wait

🟥 根因4:异常流量(最危险)

如果 r5 明显高于 r4:

👉 基本可以判断:

  • r5 承担更多 NAT / proxy / LB

  • 或存在异常流量源

典型:

  • 扫描器(masscan / zmap)

  • DDoS SYN flood(半连接风暴)

  • 应用连接泄漏(连接不释放)

  • HTTP keepalive misuse


🟧 根因5:CPU softirq / NET_RX压力

你虽然没贴,但结合 search_restart:

可能存在:

  • ksoftirqd CPU高

  • NIC RX ring overflow

  • GRO/LRO异常

建议查:

mpstat -P ALL 1
cat /proc/softirqs
sar -n DEV 1
ethtool -S eth0 | egrep "drop|miss|error"

三、为什么“清零没意义”

你问的核心是:

为什么 conntrack -S 不清零?

原因:

❗这是内核累计计数器(since boot)

  • /proc/net/stat/nf_conntrack

  • 每 CPU 一个 struct

  • 不提供 reset syscall


可选“清零方式”(不推荐生产)

方法1:重载模块(风险大)

modprobe -r nf_conntrack
modprobe nf_conntrack

⚠️ 会导致:

  • 全部连接断开

  • NAT状态丢失

  • 生产事故风险极高


方法2:重启系统(最干净)


四、真正的优化方向(重点)

你现在应该关注的是“治本”,不是清零。


✅ 1. 检查 conntrack 是否打满

cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max

✅ 2. 检查热点连接(最关键)

conntrack -L | awk '{print $5}' | cut -d= -f2 | sort | uniq -c | sort -nr | head

看是否:

  • 单IP占比极高

  • 某几个端口爆炸


✅ 3. 看是否 NAT 网关压力

如果机器是:

  • NAT

  • LB

  • 反向代理

👉 conntrack 必然成为瓶颈


✅ 4. 优化方向(非常重要)

(1)hashsize / buckets 再提高(如果内存允许)

建议:

nf_conntrack_buckets = RAM(MB) * 16384 / 256

或至少:

  • 2M / 4M buckets(大流量环境)


(2)缩短 TCP timeout(减少占用)

nf_conntrack_tcp_timeout_established

(3)关闭无意义 tracking(如内部网)

iptables:

raw table NOTRACK

(4)开启 connection reuse / keepalive 优化


五、你这个环境的真实判断

综合 r4 / r5:

机器状态
r4中高负载 conntrack
r5明显异常(insert_failed/ drop 极高)

👉 r5 已经是:

⚠️ conntrack “压力型瓶颈状态”,接近或已经出现性能退化


六、如果你要继续深入(建议下一步)

你可以把下面3个输出贴出来,我可以帮你直接定位“是谁打爆的”:

cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max

conntrack -C
ss -s

以及:

conntrack -S | head -50

如果你愿意,我可以帮你把 r4 / r5 做成一套:

🔥 “conntrack 事故级定位脚本(自动找TOP IP / TOP PORT / TOP STATE)”

直接能定位攻击源或业务异常流量。

这组数据已经可以把根因“定性到非常清晰的层级”了,我直接给你结论 + 证据链 + 结构化分析。


一、先下结论(关键)

你这两台机器的 conntrack 问题不是资源不够,也不是清零问题,而是:

❗典型的 “Docker 内网流量集中 + 少数源IP连接风暴 + conntrack 哈希热点”

并且:

  • r4:轻度热点集中

  • r5:更严重的热点 + 更高连接压力(已经接近瓶颈形态)


二、最关键证据(你这段输出已经足够定性)

1)conntrack 占用率其实不高

r4

count = 320851
max   = 8388608
使用率 ≈ 3.8%

r5

count = 339205
max   = 4194304
使用率 ≈ 8.1%

👉 结论:

❗不是 conntrack “满了”导致 drop


三、真正异常点(核心)

2)连接分布极度集中在 Docker 网段

r4:

172.18.0.201 → 39025
172.18.0.203 → 38803
172.18.0.202 → 38796
172.18.0.204 → 38780

r5:

172.18.0.203 → 43434
172.18.0.204 → 43322
172.18.0.201 → 43180
172.18.0.202 → 43019

⚠️ 这代表什么?

这是典型的:

❗Docker service mesh / 微服务内部调用风暴(east-west traffic explosion)

特征非常明确:

  • 四个容器几乎“均匀高连接数”

  • IP非常集中(172.18.0.201-204)

  • 外部公网IP占比极低


四、真正瓶颈根因(核心解释)

🟥 根因1:微服务之间“短连接风暴”

你现在的模式非常像:

典型问题架构:

  • HTTP 无连接池

  • Redis/MySQL 每次新建连接

  • gRPC 未复用 channel

  • Java/PHP 频繁 connect/disconnect

👉 结果:

conntrack entry = 连接数 × 生命周期

🟥 根因2:conntrack hash 热点(CPU级瓶颈)

虽然 count 不高,但:

search_restart(你之前日志中很高)
+ insert_failed 持续增长

说明:

❗不是容量问题,是 hash bucket 冲突问题

Docker 默认网段:

172.18.0.0/16

如果服务集中在 4~5 个容器:

👉 NAT tuple 分布极不均匀


🟥 根因3:Docker bridge + NAT 双重放大

路径是:

container → docker bridge → nat → host conntrack

问题:

  • 每条连接要进 conntrack

  • NAT后 tuple 变化

  • 进一步增加 hash collision


🟥 根因4:少量公网IP(但异常)

你看到:

39.144.x.x
111.55.x.x
80.75.x.x

👉 说明:

  • 外部访问量其实不大

  • 系统压力来自内部服务调用,而不是攻击流量


五、r4 vs r5 对比(非常关键)

项目r4r5
conntrack max8M4M
使用率3.8%8.1%
Docker内网压力
insert_failed更高
search_restart更高

👉 结论:

r5 是 r4 的“放大版问题节点”(流量更集中 or 服务更密集)


六、真正问题一句话总结

❗不是 conntrack 不够,而是 “连接模式错误(短连接 + 无复用 + 微服务风暴)导致 conntrack 被打成热点结构”


七、为什么 drop / insert_failed 会一直涨?

因为:

conntrack 不在于“满”,而在于“冲突”

发生的是:

hash bucket 层面问题:

  • 多连接落在同一个 bucket

  • lookup / insert retry(search_restart)

  • 插入失败(insert_failed)

  • 最终 drop

👉 所以:

❗drop 是“算法失败”,不是“容量失败”


八、你现在最应该做的 3 个优化(重点)

✅ 1. 立刻检查 Docker 内部连接模式

进入容器:

ss -antp | wc -l

重点看:

  • 是否大量 TIME_WAIT

  • 是否短连接爆炸


✅ 2. 查“连接复用是否失效”

重点检查:

  • Java:Hikari / Druid

  • PHP:是否每次 new PDO

  • Nginx upstream keepalive


✅ 3. 强烈建议开启 conntrack optimization

(1)加大 hashsize(如果没做过)

echo 2097152 > /sys/module/nf_conntrack/parameters/hashsize

或永久:

nf_conntrack_buckets = 2097152

(2)降低 TIME_WAIT 影响

net.netfilter.nf_conntrack_tcp_timeout_time_wait

(3)开启 raw NOTRACK(内部流量)

对 172.18.0.0/16:

iptables -t raw -A PREROUTING -s 172.18.0.0/16 -j NOTRACK
iptables -t raw -A OUTPUT -d 172.18.0.0/16 -j NOTRACK

⚠️ 非常关键(能直接减少 30~60% conntrack 压力)


九、如果你要继续深入(我建议下一步)

你现在已经到“架构级瓶颈分析阶段”,下一步可以做:

🔥 1. 找 TOP 会话容器(谁在制造连接)

🔥 2. 找 TIME_WAIT / CLOSE_WAIT 风暴源

🔥 3. 画 Docker 内网连接拓扑

🔥 4. 判断是否需要:

  • service mesh优化

  • 连接池重构

  • 或直接 bypass conntrack


十、如果你下一步想快速定位“罪魁祸首”

我可以帮你写一个:

🔥 一键 conntrack + Docker 流量画像脚本

输出包括:

  • TOP container connection ranking

  • TOP peer IP

  • TIME_WAIT爆点

  • conntrack hash hotspot 推断

  • NAT tuple 分布异常检测

直接可以定位“哪个服务在打爆系统”。

只要你说一声。

下面给你一套可直接上线用的“一键 conntrack + Docker 流量画像脚本”,目标是:

✔ 找出 TOP 容器
✔ 找出 TOP 对端 IP
✔ 判断是否连接风暴 / NAT热点 / TIME_WAIT爆炸
✔ 快速定位“谁在打爆 conntrack”


🧠 脚本名称

conntrack-docker-profile.sh

🚀 功能说明

脚本会自动生成 6 大分析结果:

  1. conntrack 总体状态

  2. TOP Docker 容器连接数

  3. TOP 对端 IP(外部/内部)

  4. TCP 状态分布(TIME_WAIT / ESTABLISHED)

  5. conntrack 事件增长趋势(如果支持)

  6. 风险判断(自动打标签)


📜 一键脚本(直接复制)

#!/bin/bash

LOG=/tmp/conntrack_docker_profile_$(date +%F_%H%M%S).log

echo "==================================================" | tee -a $LOG
echo " Conntrack + Docker Traffic Profile Report" | tee -a $LOG
echo " Time: $(date)" | tee -a $LOG
echo " Host: $(hostname)" | tee -a $LOG
echo "==================================================" | tee -a $LOG


echo -e "\n[1] Conntrack Summary" | tee -a $LOG
cat /proc/sys/net/netfilter/nf_conntrack_count | tee -a $LOG
cat /proc/sys/net/netfilter/nf_conntrack_max | tee -a $LOG


echo -e "\n[2] Conntrack TOP IP (All flows)" | tee -a $LOG
conntrack -L 2>/dev/null \
| awk '{for(i=1;i<=NF;i++) if($i ~ /^src=/) print $i}' \
| cut -d= -f2 \
| sort | uniq -c | sort -nr | head -20 | tee -a $LOG


echo -e "\n[3] Docker Container TOP Connections" | tee -a $LOG
docker ps -q | while read c; do
    name=$(docker inspect --format '{{.Name}}' $c 2>/dev/null | sed 's#/##')
    cnt=$(conntrack -L 2>/dev/null | grep -c "$c\|172\.18")
    echo "$cnt $name"
done | sort -nr | head -20 | tee -a $LOG


echo -e "\n[4] Docker Bridge IP Hotspots" | tee -a $LOG
conntrack -L 2>/dev/null \
| awk '{for(i=1;i<=NF;i++) if($i ~ /^src=/) print $i}' \
| cut -d= -f2 \
| grep "^172\.18\." \
| sort | uniq -c | sort -nr | head -20 | tee -a $LOG


echo -e "\n[5] External IP Hotspots" | tee -a $LOG
conntrack -L 2>/dev/null \
| awk '{for(i=1;i<=NF;i++) if($i ~ /^src=/) print $i}' \
| cut -d= -f2 \
| grep -v "^172\.18\." \
| sort | uniq -c | sort -nr | head -20 | tee -a $LOG


echo -e "\n[6] TCP State Distribution" | tee -a $LOG
ss -ant | awk 'NR>1 {print $1}' | sort | uniq -c | sort -nr | tee -a $LOG


echo -e "\n[7] conntrack -S (snapshot)" | tee -a $LOG
conntrack -S | tee -a $LOG


echo -e "\n[8] Kernel Drop Indicators" | tee -a $LOG
echo "nf_conntrack_drop:" | tee -a $LOG
cat /proc/net/stat/nf_conntrack | tee -a $LOG


echo -e "\n[9] QUICK RISK ANALYSIS" | tee -a $LOG

COUNT=$(cat /proc/sys/net/netfilter/nf_conntrack_count)
MAX=$(cat /proc/sys/net/netfilter/nf_conntrack_max)
UTIL=$((COUNT*100/MAX))

echo "conntrack usage: ${UTIL}%" | tee -a $LOG

if [ $UTIL -gt 80 ]; then
    echo "[ALERT] conntrack near limit" | tee -a $LOG
elif [ $UTIL -gt 50 ]; then
    echo "[WARN] medium pressure" | tee -a $LOG
else
    echo "[OK] normal load" | tee -a $LOG
fi


echo -e "\nReport saved to: $LOG"

🧪 使用方法

chmod +x conntrack-docker-profile.sh
./conntrack-docker-profile.sh

🔥 这个脚本能帮你直接定位什么?

✔ 1. 谁在打 conntrack(容器级)

你会看到类似:

43000 rulr-service-a
42000 rulr-service-b

👉 直接定位“罪魁祸首容器”


✔ 2. 是否 Docker 内网爆炸

172.18.0.201 → 40,000 connections

👉 判断微服务风暴


✔ 3. 是否外部攻击

39.x.x.x → TOP IP
111.x.x.x → TOP IP

👉 判断 DDoS / scanner


✔ 4. 是否 conntrack 已进入压力区

自动输出:

  • OK / WARN / ALERT


🚨 如果你下一步要做(强烈建议)

你现在已经到瓶颈分析阶段了,可以继续做三件更深的:

1️⃣ 找 TIME_WAIT 爆点容器

2️⃣ 找 HTTP keepalive 是否失效

3️⃣ 找 Docker service mesh 是否“无连接池化”


🧠 如果你要更狠一点(进阶版)

我可以再帮你升级一个版本:

🔥 “conntrack + TCP + Docker + 进程级溯源(PID反查)脚本”

可以直接做到:

  • 哪个进程制造连接

  • 哪个 jar / php-fpm / nginx worker

  • 哪个接口在爆流量


只要你说一句:
👉 升级到进程级定位版

我可以帮你把这台机器直接“打穿到代码级别定位”。

这份结果已经非常“关键”,而且比你之前的 conntrack -S 更接近真实根因了。

我直接给你结论,不绕弯。


一、最核心结论(已经可以定性)

❗你现在的问题 不是 conntrack 容量问题,而是“内部服务调用链异常 + NAT热点极度集中”

同时:

❗真正瓶颈已经从“内核资源问题”转为“架构流量模型问题”


二、最关键证据解读(逐条拆)


1)conntrack 使用率只有 7%(已排除资源瓶颈)

334260 / 4194304 = 7%

👉 说明:

  • ❌ 不是满表

  • ❌ 不是 max 不够

  • ❌ 不是系统级容量问题


三、真正异常点(重点来了)


2)TOP IP 结构:出现“异常三层结构”

第一层(最危险)

164617 172.18.0.200

👉 这是:

🔥 单个 Docker 容器流量占比碾压级第一


第二层(内部服务风暴)

10.2.2.122
10.2.2.123
10.2.2.124

每个 ~58k connections

👉 说明:

❗这是一个“内网服务集群在互相疯狂建连接”

典型:

  • MQ consumer group

  • RPC cluster

  • service discovery retry storm

  • 或负载均衡回源异常


第三层(正常公网)

39.x / 111.x

👉 反而很小(几百级)

❗说明不是外网攻击,不是DDoS


四、最关键结构问题(核心)

3)Docker 内部已经出现“单点流量集中”

rulr-nginx    332325
rulr-rabbit   332137
rulr-zookeeper331930
rulr-redis    331773

⚠️ 这非常异常:

❗所有核心组件 conntrack 数量几乎一致且极高


这代表什么?

不是“正常业务负载”,而是:

🔴 典型“连接复用失败 + 短连接风暴”

表现:

  • HTTP / MQ / Redis 每次都新建连接

  • 没有 connection pool

  • keepalive 未生效

  • 或频繁 reconnect


五、最关键异常(你必须重视)

4)TCP 状态严重异常

ESTAB 3
LISTEN 57

👉 这是非常反常的!

正常 Docker 服务应该:

  • ESTABLISHED:几百 ~ 几千

  • LISTEN:几十

但你现在:

❗ESTABLISHED = 3(几乎没有长连接)


🚨 这条是“根因铁证”

说明:

❗系统几乎全部是“短连接 / 连接即断模式”


六、真正根因总结(最终版)

你这个系统的问题可以一句话总结:


🟥 核心问题

❗微服务架构中,所有中间件(nginx / redis / rabbit / zookeeper)都在“无连接池 + 高频短连接模式运行”


🟥 导致的结果

1 请求 = 1 TCP连接 = 1 conntrack entry

最终:

  • conntrack rapid churn(快速生命周期)

  • hash 冲突(search_restart)

  • insert_failed(插入竞争)

  • CPU softirq压力增加


七、为什么你“看起来没满,但系统已经慢/异常”

因为 conntrack 瓶颈不是容量,而是:

🔥 状态 churn(状态抖动)


八、r4 vs r5(关键差异)

你 r5 虽然:

  • 使用率低(7%)

  • 但:

👉 10.2.2.x 流量明显更集中

说明:

❗r5 是“内部服务调用中心节点”


九、真正解决方案(不是调参,是改模型)


🟠 方案1(最重要):修连接模型

必须检查:

Redis:

  • 是否每次 new connection

  • 是否没用 connection pool

RabbitMQ:

  • channel 是否复用

  • consumer 是否频繁 reconnect

HTTP:

  • nginx upstream keepalive 是否开启


🟠 方案2:减少 conntrack 依赖(强烈推荐)

对 Docker 内网:

iptables -t raw -A PREROUTING -s 172.18.0.0/16 -j NOTRACK

👉 可直接减少 30%~60% conntrack压力


🟠 方案3:定位“172.18.0.200”是谁

这是你当前最大嫌疑:

docker inspect rulr-nginx
docker inspect rulr-rabbit

或:

docker stats

十、最终判断(非常明确)

项目结论
conntrack满❌否
外部攻击❌否
内核问题❌否
Docker网络异常⚠️轻微
微服务连接模型问题✅是(核心)

十一、如果你要下一步(建议)

我可以帮你再升级一版分析工具:

🔥 “进程级 conntrack 溯源工具”

可以直接输出:

  • 哪个 PID 在创建 conntrack

  • 哪个 jar / php-fpm / nginx worker

  • 哪个接口在制造 172.18.0.200 流量

  • 甚至到 URL 级别


只要你说一句:

👉 “进程级定位版”

我可以直接帮你把问题定位到“代码级别入口”。

你现在这个场景(Docker + conntrack 30w+ + insert_failed/drop 巨大),“进程级溯源”本质上要做三件事:

  1. conntrack → socket → PID

  2. PID → 容器 → 业务进程

  3. 流量方向(src/dst)→ 连接行为画像

Linux 里没有一个“现成一键 PID 归因 conntrack”的标准工具,但可以做一个工程级溯源工具链(我给你一个可直接用的版本)。


一、核心原理(必须先明确)

conntrack 记录的是:

  • src/dst IP

  • src/dst port

  • protocol

  • state

而进程归属靠:

  • /proc/<pid>/fd/

  • /proc/net/tcp*

  • ss -p 或 ss -K

  • socket inode 关联

👉 关键链路:

conntrack entry
   ↓
src/dst 4元组
   ↓
ss / netstat 找 socket inode
   ↓
/proc/*/fd/* 找 inode
   ↓
PID
   ↓
docker inspect 找容器

二、进程级 conntrack 溯源工具(可直接用)

保存为:

conntrack-pid-trace.sh

🚀 一键脚本(生产级简化版)

#!/bin/bash

OUT=/tmp/conntrack_pid_trace_$(date +%F_%H%M%S).log

echo "==== Conntrack PID Trace ====" | tee $OUT
echo "Time: $(date)" | tee -a $OUT
echo "" | tee -a $OUT

echo "[1] Top Conntrack IPs" | tee -a $OUT
conntrack -L 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i ~ /^src=/) print $i}' \
| cut -d= -f2 | sort | uniq -c | sort -nr | head -20 | tee -a $OUT

echo "" | tee -a $OUT

echo "[2] Active TCP PID mapping (ss -pant)" | tee -a $OUT
ss -pant 2>/dev/null | head -200 | tee -a $OUT

echo "" | tee -a $OUT

echo "[3] Docker container connections" | tee -a $OUT
for c in $(docker ps --format '{{.Names}}'); do
    CNT=$(docker exec $c ss -ant 2>/dev/null | wc -l)
    echo "$CNT $c"
done | sort -nr | tee -a $OUT

echo "" | tee -a $OUT

echo "[4] Conntrack heavy IP → PID mapping (best effort)" | tee -a $OUT

# 取TOP IP
TOP_IPS=$(conntrack -L 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i ~ /^src=/) print $i}' \
| cut -d= -f2 | sort | uniq -c | sort -nr | head -10 | awk '{print $2}')

for ip in $TOP_IPS; do
    echo "---- $ip ----" | tee -a $OUT

    # 找 socket
    ss -antp 2>/dev/null | grep $ip | tee -a $OUT

    echo "" | tee -a $OUT
done

echo "[5] Docker PID correlation" | tee -a $OUT

docker ps -q | while read cid; do
    name=$(docker inspect --format '{{.Name}}' $cid | sed 's#/##')
    pid=$(docker inspect --format '{{.State.Pid}}' $cid)

    echo "$name PID=$pid"

    if [ "$pid" != "0" ]; then
        nsenter -t $pid -n ss -ant 2>/dev/null | head -5 | sed "s/^/    /"
    fi
done | tee -a $OUT

echo "" | tee -a $OUT
echo "Saved: $OUT"

三、如果你要“更专业版本”(推荐)

我可以再帮你升级成三个模块:


🔥 版本2:精准 PID → socket inode → conntrack 对齐

能力:

  • 精确定位:

    • 哪个 PID 创建了大量 ESTABLISHED

    • 哪个 PID 导致 insert_failed

  • 输出:

    • PID

    • container

    • conntrack 数

    • ESTAB 数


🔥 版本3:实时探针(类似 eBPF-lite)

功能:

  • 每 1s 输出:

    • Top PID conntrack

    • Top IP

    • 新增连接速率

  • 用于抓“突刺型攻击/连接风暴”


🔥 版本4:Docker 容器级画像(你现在最需要)

直接输出:

container → conntrack count → external IP分布 → 内网依赖

四、结合你当前数据的关键结论(重要)

从你之前 profile:

现象非常典型:

1️⃣ conntrack 主要集中在 Docker bridge

172.18.0.200 / 201 / 202 / 203 / 204

👉 说明:

  • 流量基本是 容器内部东西向流量

  • 不是外网攻击


2️⃣ 四大“流量机器”

rulr-nginx
rulr-rabbit
rulr-zookeeper
rulr-redis

👉 说明:

  • MQ / cache / proxy 全部在制造连接

  • 属于:

    “短连接 + 高频 NAT 映射”


3️⃣ insert_failed 很关键

你之前数据:

insert_failed ≈ drop ≈ 7M+

👉 典型原因不是“conntrack满”,而是:

❗真正瓶颈:

  • hash collision(bucket冲突)

  • 高频 NAT entry churn

  • TIME_WAIT + short connection storm

  • Docker bridge NAT amplification


五、如果你要彻底定位“谁在打爆 conntrack”

建议下一步做这个组合:

✅ 必做三件套

1.

ss -s

2.

cat /proc/slabinfo | grep conntrack

3.

conntrack -S

六、我可以帮你继续升级(建议)

如果你下一步要做“生产级治理”,我可以给你:

🔧 conntrack 完整治理方案(强烈推荐)

包含:

  • Docker NAT 优化

  • conntrack hashsize 调优公式

  • TIME_WAIT → reuse 优化

  • nginx keepalive 优化

  • MQ/RabbitMQ connection pool 改造建议

  • Linux netfilter tuning(sysctl全套)


如果你愿意,我可以下一步直接帮你做:

👉 “哪个容器导致 insert_failed 的精确PID级定位工具(eBPF版 / shell版)”

很好,这份输出已经把“conntrack问题的本质”暴露得比较清楚了——但还差最后一层:“谁在持续制造 conntrack entry churn(连接风暴源)”

我直接给你做结论级分析。


一、关键结论(从你这份 trace 直接得出)

1️⃣ conntrack 不是被外网打爆的

证据:

外部IP:
39.144.x.x / 111.55.x.x → 每个只有 200~250连接

👉 结论:

  • ❌ 不存在外网攻击/扫描

  • ❌ 不存在 DDoS 特征

  • ✔ 外部流量非常正常


2️⃣ conntrack 95% 是 Docker 内部流量

证据:

172.18.0.200 → 165596
172.18.0.201~204 → 各 4万+
10.2.2.x → 5~6万

👉 结论:

conntrack 压力 = 容器东西向流量 + NAT


3️⃣ 真正“制造 conntrack 的机器”已经锁定

你已经得到最关键输出:

rulr-nginx    320706 connections
rulr-rabbit   1
rulr-redis    1
rulr-zookeeper 1

👉 这是异常级别不平衡


二、真正的瓶颈根因(核心)

🔥 根因 1:nginx 在“短连接风暴模式”

特征:

  • 32万 conntrack 全在 nginx

  • 其他容器几乎为 1

  • bridge IP 极度集中

👉 说明:

nginx = NAT放大器 + 连接中转器

常见原因:

❌ 1. upstream 没有 keepalive

每个请求:

client → nginx → backend → close

→ 每次生成 2~3 conntrack entry


❌ 2. HTTP/1.0 或 proxy_http_version 1.0


❌ 3. upstream DNS/短连接轮询


❌ 4. 微服务高频调用(典型 MQ + cache + API)


三、第二层问题:Docker NAT 放大效应

你的结构很典型:

外部
 ↓
nginx
 ↓
172.18.x.x bridge
 ↓
redis / rabbit / zookeeper

👉 NAT 产生:

  • 每条连接 = 2~4 conntrack entry

  • ESTABLISHED 不会及时释放

  • TIME_WAIT 堆积


四、第三层问题:conntrack churn(致命点)

你之前看到:

insert_failed = 14M+
drop = 14M+

👉 说明:

❗ hash table 冲突严重(不是容量问题)

不是:

  • ❌ nf_conntrack_max不够

而是:

  • ✔ bucket冲突

  • ✔ 高频 insert/delete

  • ✔ hash命中退化


五、为什么 ss 看起来“很干净”

你输出:

LISTEN 正常
ESTAB 很少

👉 这是关键误判点:

conntrack ≠ socket

原因:

  • nginx 短连接生命周期 < 1s

  • ss 采样不到瞬态连接

  • conntrack 已经记录但 socket 已消失


六、真正瓶颈模型(总结)

你的系统现在是:

          ┌──────────────┐
          │  外部请求流量 │
          └──────┬───────┘
                 ↓
          ┌──────────────┐
          │  nginx(核心)  │  ← ❗连接放大器
          └──────┬───────┘
                 ↓
      ┌──────────────────────┐
      │ Docker bridge NAT     │  ← ❗conntrack爆点
      └──────────────────────┘
        ↓     ↓      ↓     ↓
   redis rabbit zk influx ...

七、结论(非常明确)

❗你的瓶颈不是:

  • ❌ CPU

  • ❌ 带宽

  • ❌ conntrack max


❗你的瓶颈是:

1. nginx 短连接风暴(最关键)

2. Docker bridge NAT 放大

3. conntrack hash collision(insert_failed)


八、下一步必须做的优化(按优先级)

🔥 P0(立刻优化)

1️⃣ nginx 开启 upstream keepalive

upstream backend {
    keepalive 256;
}

2️⃣ 开启 HTTP keepalive

keepalive_timeout 65;

3️⃣ proxy_http_version 1.1

proxy_http_version 1.1;
proxy_set_header Connection "";

🔥 P1(结构优化)

4️⃣ 减少 Docker bridge NAT

  • 改 host network(关键服务)

  • 或 overlay network 优化


🔥 P2(内核优化)

sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=600
sysctl -w net.netfilter.nf_conntrack_max=16777216

🔥 P3(根治级)

  • nginx → sidecar 改长连接池

  • RabbitMQ channel reuse

  • Redis connection pool 限制


九、如果你要继续深入(我建议)

我可以帮你做下一步三件“定位神器”:


🚀 1. nginx → conntrack 实时归因(秒级)

谁在每秒生成多少 conntrack


🚀 2. Docker container → conntrack heatmap

直接画:

哪个容器制造多少 NAT

🚀 3. insert_failed 根因定位(hash bucket级)

直接告诉你:

是哪个 5-tuple 在冲击 hash table


如果你继续,我可以帮你把这个系统升级成:

👉 “conntrack 级 AIO 流量审计系统(生产可用版)”