Linux 公网服务偶发不可用的定位方式

3次阅读

偶发不可用主因是中间设备RST、OOM Killer杀进程、systemd重启退避、TIME_WaiT端口耗尽;应优先用dmesg、ss、tcpdump定位系统与网络层问题。

Linux 公网服务偶发不可用的定位方式

看连接是否被中间设备重置

公网服务偶发不可用,第一反应常是服务进程挂了,但更常见的是连接在传输路径中被意外中断。典型表现是客户端 tcpdump 抓到 SYN 发出后没收到 SYN-ACK,或收到 RST 包;服务端 netstat -s | grep -i "reset" 显示大量 segments reset。这往往不是服务本身的问题,而是防火墙、云厂商安全组、NAT 网关或运营商设备因会话超时、连接数限制或策略变更主动发 RST。

实操建议:

  • 在服务端和客户端分别用 tcpdump -i any port PORT -w conn.pcap 抓包,比对三次握手是否完整
  • 检查云平台控制台的安全组/网络 ACL 日志(如 AWS VPC Flow Logs、阿里云流日志),确认是否有 REJECTDROP 记录
  • 临时关闭本地防火墙systemctl stop firewalldufw disable)排除干扰,再复现问题
  • 若使用 NAT 网关,确认其连接数配额(如 AWS NAT gateway 默认 5.5 万并发连接)是否被打满

查服务进程是否被 OOM Killer 杀掉

偶发不可用持续几秒到几十秒,且无明显错误日志,dmesg -T | grep -i "killed process" 却输出类似 Killed process 12345 (nginx) total-vm:2048000kB, anon-rss:1800000kB, file-rss:0kB 的记录——这就是 OOM Killer 在后台动的手。linux 内核发现内存严重不足时,会按 oom_score_adj 选一个“最该杀”的进程干掉,不通知应用层,也不写服务日志。

实操建议:

  • 立即执行 dmesg -T --level=err,过滤带时间戳的内核错误,重点找 Killed process
  • 检查服务进程的内存限制:cat /proc/PID/oom_score_adj(值越大越容易被杀),默认为 0,容器中可能被设为 1000
  • 给关键服务设置抗杀优先级:echo -999 > /proc/PID/oom_score_adj(需 root;容器启动时加 --oom-score-adj=-999
  • 监控 free -hcat /sys/fs/cgroup/memory/memory.usage_in_bytes(cgroup v1)趋势,提前预警内存压力

验 systemd 服务是否被 RestartSec 拖慢恢复

systemctl status SERVICE 看到状态是 activating (auto-restart) 或反复在 failed → activating → failed 循环,但服务二进制本身没问题——问题常出在 systemd 的重启退避机制。默认配置下,如果服务连续失败,RestartSec 会指数级增长(如 100ms → 200ms → 400ms…),导致看似“偶发不可用”,实则是服务刚崩就立刻重启,却被 systemd 卡着不让起。

实操建议:

  • 运行 systemctl show SERVICE | grep -E "(Restart|StartLimit)",重点关注 StartLimitIntervalSecStartLimitBurst 和当前计数 StartLimitAction
  • 临时禁用启动限制:systemctl set-Property SERVICE StartLimitIntervalSec=0(慎用于生产)
  • 在 service 文件里显式定义稳定重启间隔:RestartSec=5(避免默认指数退避),并设 StartLimitBurst=5 防止误触发熔断
  • 配合 ExecStartPre=/bin/sh -c 'sleep 1' 给依赖服务留出缓冲时间,避免雪崩式启动失败

盯住 TIME_WAIT 连接耗尽端口资源

高并发短连接服务(如 API 网关、http 客户端密集调用)偶发拒绝新连接,ss -s 显示 TIME-WAIT 数量高达六万以上,而 net.ipv4.ip_local_port_range 默认只有 32768 60999(约 28K 可用端口)——端口被占满,新连接连 SYN 都发不出,现象就是“服务突然不可用几秒后又好了”。

实操建议:

  • 快速统计:ss -tan state time-wait | wc -l,对比 cat /proc/sys/net/ipv4/ip_local_port_range 差值
  • 临时缓解:调大端口范围 sysctl -w net.ipv4.ip_local_port_range="1024 65535",并启用端口复用 sysctl -w net.ipv4.tcp_tw_reuse=1
  • 长期方案:服务端开启 SO_LINGER 强制 FIN+ACK 快速关闭(需代码修改);或改用长连接池(如 HTTP/1.1 keep-alive、HTTP/2 multiplexing)
  • 注意:tcp_tw_recycle 已在 Linux 4.12+ 移除,且在 NAT 环境下会导致连接失败,切勿启用

真正棘手的偶发问题,往往藏在系统层与网络层交界处:OOM Killer 不写应用日志,TIME_WAIT 不报错,RST 包不经过服务进程。定位时别急着翻服务代码,先看 dmesgsstcpdump 这三样,它们不会说谎,只是需要你问对问题。

text=ZqhQzanResources