Linux网络性能分析:ss、netstat、iftop、sar实战

服务响应变慢,浏览器转圈,运维第一反应是「不卡吧」。查完 CPU、内存、磁盘都没事,最后往往落在网络上:连接数爆炸、带宽打满、TIME_WAIT 堆积、重传率高。网络问题隐蔽、跨主机,排查难度比单机资源高。这一篇用 ss、netstat、iftop、sar -n 四把工具,从连接状态、带宽占用、历史趋势三个角度把网络看清。

一、网络性能的四个维度

排查网络,先明确你要回答哪个问题:

维度 问题 工具
连接 有多少连接?什么状态? ss / netstat
带宽 谁在占流量?跑满了吗? iftop / nload
质量 有丢包/重传/错误吗? sar -n / netstat -s
历史 过去某个时间点怎么样? sar -n

「连接多」和「带宽满」是两回事,很多人混为一谈。连接数多可能是短连接风暴(TIME_WAIT),带宽满则是有大流量传输。用不同的工具看。

二、ss:现代版 netstat(首选)

ss = socket statistics,netstat 的替代品。它直接读内核的 netlink 接口,比 netstat 遍历 /proc 快得多,几万连接时差距非常明显。新系统优先用 ss。

语法格式

复制代码
ss [选项] [过滤]

常用参数

参数 说明
-t TCP
-u UDP
-n 不解析端口名/主机名,显示数字(快)
-l 只显示 LISTEN 状态的套接字
-p 显示进程(需 root 看全部)
-a 显示所有
-s 打印汇总统计
-o 显示定时器信息(含重传)
-i 显示 TCP 内部信息(含 cwnd、rtt)

示例与预期输出

看所有监听端口:

复制代码
sudo ss -tlnp

预期输出:

复制代码
State   Recv-Q  Send-Q  Local Address:Port   Peer Address:Port  Process
LISTEN  0       128     0.0.0.0:22           0.0.0.0:*          users:(("sshd",pid=980))
LISTEN  0       511     0.0.0.0:80           0.0.0.0:*          users:(("nginx",pid=1234))
LISTEN  0       128     127.0.0.1:3306       0.0.0.0:*          users:(("mysqld",pid=2345))

关键列:

  • Recv-Q / Send-Q:对 LISTEN 状态,这是全连接队列(accept queue)的当前长度 / 上限 。Recv-Q 持续接近 Send-Q,说明应用来不及 accept,连接会溢出。
  • Local Address:Port:0.0.0.0 表示监听所有网卡,127.0.0.1 表示只监听本地。

统计各状态连接数(排查 TIME_WAIT 必备):

复制代码
ss -tan | awk 'NR>1 {print $1}' | sort | uniq -c | sort -rn

预期输出:

复制代码
  15234 ESTAB
   3421 TIME-WAIT
    128 LISTEN
     12 CLOSE-WAIT

看某端口的连接来自哪些 IP:

复制代码
ss -tan state established '( sport = :80 )' | awk 'NR>1{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head

看 TCP 内部指标(诊断慢连接):

复制代码
ss -tin state established '( dport = :443 )'

输出里会带 rtt、cwnd、retrans 等,重传次数高说明网络质量差。

⚠️ Recv-Q 溢出是「连接被拒」的常见根因

如果服务负载高时客户端报 connection refused 或超时,但 ss 看监听在、进程也在,很可能是全连接队列满了 。Recv-Q 顶到 Send-Q 就是证据。解决方向:调大 net.core.somaxconn 和 nginx 的 backlog,或优化应用 accept 速度。

三、netstat:老将,仍要会读

netstat 属于 net-tools 包,很多精简系统默认不装。虽然被 ss 取代,但面试和排障仍常遇到,得会读。

语法格式

复制代码
netstat [选项]

常用参数

参数 说明
-tlnp TCP 监听 + 数字 + 进程
-an 所有连接(数字)
-s 协议统计(重传、错误)
-r 路由表
-i 网卡统计

示例与预期输出

看重传、错误等协议统计:

复制代码
netstat -s | grep -iE "retrans|error|drop|overflow"

    1203 segments retransmitted
    56 packets received with errors
    89 times the listen queue of a socket overflowed

listen queue overflowed 直接对应上面说的全连接队列溢出,是个非常有用的信号。

注意:netstat 在连接数上万时会很慢(遍历 /proc/net/tcp),此时务必改用 ss。

四、iftop:实时看谁在吃带宽

ss/netstat 看连接,iftop 看流量排名------类似 top 之于进程。

安装

复制代码
sudo apt install iftop -y       # Ubuntu
sudo dnf install iftop -y       # Rocky/CentOS

使用

复制代码
sudo iftop -i eth0 -nNP
参数 说明
-i 网卡 指定网卡
-n 不做 DNS 解析
-N 显示端口号
-P 显示端口列
-B 以字节显示

预期输出:

复制代码
                12.5Mb         25.0Mb         37.5Mb
└───────────────┴───────────────┴───────────────
10.0.0.5:443      <=>  203.0.113.7:54321     5.20Mb  3.10Mb  2.80Mb
10.0.0.5:3306     <=>  10.0.0.9:41234        1.10Mb  980kb   870kb

左列本机地址,中间箭头方向(=> 发送,<= 接收,<=> 双向),右侧三列是 2s/10s/40s 平均速率。一眼看出是谁在传大流量。

iftop 还有两个常用键:p 切换显示端口,h 帮助,q 退出。轻量替代品是 nload(看总量)和 iptraf-ng。

五、sar -n:历史网络数据

ss/iftop 都是看「现在」。想知道「凌晨 3 点网络为什么抖动」,得靠 sar 的历史记录(它默认每 10 分钟采样一次并保留一个月)。

复制代码
# 看今天的网络统计
sar -n DEV 1 5

# 看指定日期的网络
sar -n DEV -f /var/log/sysstat/sa15

预期输出:

复制代码
10:35:01     IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
10:35:02      eth0   2150.00   1980.00    5800.00   6200.00      0.00      0.00      0.00

常用 -n 子选项:

子选项 含义
DEV 网卡流量
EDEV 网卡错误/丢包
TCP TCP 连接统计
SOCK socket 使用情况(看 tw 等)

排查历史网络问题,sar -n EDEV 看丢包错误,sar -n TCP 看重传和连接建立,配合时间点定位。

注意:sar 依赖 sysstat 服务持续采集。默认可能没开,需编辑 /etc/default/sysstat 把 ENABLED="false" 改成 true 并启动 sysstat 服务。

六、读懂 TCP 状态:TIME_WAIT 与 CLOSE_WAIT

这两个状态是网络排障里的常客,也是被误解最多的。

TIME_WAIT(主动关闭方进入)

四次挥手时,主动关闭连接的一方 最后进入 TIME_WAIT,持续 2MSL(通常 60 秒)才真正释放。

为什么要等? 两个原因:

  1. 保证最后一个 ACK 能到达对端,万一丢了可以对端重发 FIN,我方还能响应。
  2. 让本次连接的老数据包在网络中彻底消失,避免影响同端口的新连接。

TIME_WAIT 大量出现通常是正常的,尤其短连接服务(HTTP 短连接、爬虫)。它是「优雅关闭」的必要代价。

什么时候要处理?

  • 端口被耗尽(客户端主动连大量目标,本地端口用光):开 net.ipv4.tcp_tw_reuse(只对客户端有效)。
  • 服务端大量 TIME_WAIT:更该优化成长连接(keep-alive),从根上减少连接数。

CLOSE_WAIT(被动关闭方没关)

如果是被动关闭方 收到 FIN 后一直停在 CLOSE_WAIT,那基本是应用 bug :应用没调用 close()。CLOSE_WAIT 堆积会耗尽文件描述符。

关键区别:

状态 谁进入 是否正常 处理
TIME_WAIT 主动关闭方 正常现象 优化为长连接
CLOSE_WAIT 被动关闭方 异常 查应用代码为何不 close

看到 CLOSE_WAIT 多,别去调内核参数,去改代码。

⚠️ 常见错误

  1. TIME_WAIT 多就慌 。它是正常状态,先看数量级和场景,别盲目调 tcp_tw_recycle(该参数在 4.12 内核已被移除,且 NAT 环境下有害)。
  2. CLOSE_WAIT 当 TIME_WAIT 处理。调内核参数没用,根因在应用没关连接。
  3. 改 tcp_tw_reuse 却没生效 。它只对主动发起连接的一方有效,服务端被动连接不适用。
  4. 用 netstat 在几万连接时排查 。卡到怀疑人生,果断换 ss。
  5. 忽略全连接队列溢出 。netstat -s 的 listen queue overflowed 和 ss 的 Recv-Q 满,是「连接被拒」的隐形杀手。
  6. 只在本机看 。网络问题跨主机,本机 ss 正常不代表网络正常,要两端都看,必要时抓包(第 74 篇)。

七、原理探究:TCP 连接队列与三次握手

理解 ss 输出里的 Recv-Q/Send-Q,得先懂内核怎么处理新连接。

三个队列

服务端 listen() 后,内核维护两个队列:

  1. 半连接队列(SYN queue) :收到 SYN、回了 SYN-ACK,等待对方 ACK 的连接。长度上限 net.ipv4.tcp_max_syn_backlog。
  2. 全连接队列(accept queue) :三次握手完成、等待应用 accept() 的连接。长度上限是 min(somaxconn, backlog),其中 backlog 由 listen() 传入,somaxconn= net.core.somaxconn。

握手与队列流转

复制代码
客户端                    服务端内核                应用
  |--- SYN ----------------->|                       |
  |                           | 入【半连接队列】      |
  |<-- SYN+ACK ---------------|                       |
  |--- ACK ------------------>|                       |
  |                           | 移入【全连接队列】    |
  |                           |---------------------->| accept()

ss -lnt 里 LISTEN 状态的 Recv-Q 就是全连接队列的当前长度 ,Send-Q 是它的上限。当 Recv-Q 顶到 Send-Q,新来的握手完成连接会被丢弃 (或按 tcp_abort_on_overflow 决策直接 RST),客户端表现为超时或拒绝。

调优参数

复制代码
# 全连接队列上限(应用 listen backlog 也受它限制)
sysctl net.core.somaxconn

# 半连接队列上限
sysctl net.ipv4.tcp_max_syn_backlog

# SYN 队列满时是否直接 RST(默认 0,丢弃让它重试)
sysctl net.ipv4.tcp_abort_on_overflow

配合应用侧调大 listen() 的 backlog(如 nginx 的 listen ... backlog=2048;),才能真正扩容。

为什么会有 SYN Flood 攻击

攻击者只发 SYN 不回最后的 ACK,半连接队列被占满,正常连接进不来。防御手段:SYN cookies(net.ipv4.tcp_syncookies=1)、调大 tcp_max_syn_backlog、缩短 tcp_synack_retries。

八、网络排查速查表

复制代码
# 1. 监听端口与队列
sudo ss -tlnp

# 2. 各状态连接数统计
ss -tan | awk 'NR>1{print $1}' | sort | uniq -c | sort -rn

# 3. 某端口连接来源 Top
sudo ss -tn state established '( sport = :80 )' | awk 'NR>1{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head

# 4. 实时流量排名
sudo iftop -i eth0 -nNP

# 5. 协议错误统计
netstat -s | grep -iE "retrans|overflow|error"

# 6. 历史网络数据
sar -n DEV 1 5
sar -n EDEV 1 5

一句话记住网络排查的主线:连接看 ss、流量看 iftop、质量看 sar/netstat -s、历史看 sar。而绝大多数「网络慢」背后,其实是 TIME_WAIT 堆积、队列溢出或应用没关连接------先分清是谁的问题,再谈优化。

相关推荐
镜子AI15 小时前
镜子AI 技术复盘:三条自动化链路上的“停止条件“设计
运维·人工智能·自动化
tianyuanwo16 小时前
NetBox 数据库详解:当“关系型数据库”被装进一个网络运维的领域模型里
运维·数据库·netbox
HideF16 小时前
Linux sudo
linux
FlightYe16 小时前
视界原理之3D视频(四):裸眼、眼镜和头显
android·linux·c++·3d·ffmpeg·音视频
蹊黎17 小时前
Linux 下用 C 语言实现进度条
linux·c语言·单片机
知已难寻18 小时前
03 · OpenStack的计算管理 Nova
运维·服务器·开发语言·云原生·云计算·openstack·开源软件
huainingning18 小时前
Windows syslog日志服务器搭建与模拟器对接
运维·服务器·智能路由器
牛马鸡niumasi18 小时前
【Linux】C语言文件操作
linux
say_fall18 小时前
【Linux系统编程】Ext 文件系统:磁盘与存储、文件与目录、现代计算机究竟如何寻找文件
linux·运维·服务器·数据库·c++
wacsii19 小时前
【Linux进程(一)】Linux 进程初探:操作系统如何管理进程?fork() 为什么返回两次?
linux·运维·服务器