带宽跑满时 SSH 卡顿是因为管理流量被业务数据挤占,最直接的止血方案是通过流量控制工具限制占用带宽的进程,并为 SSH 端口设置高优先级。
先说结论:优先识别占用带宽的进程并限制其速率,同时利用 tc 为 SSH 流量建立高优先级队列。
- 先定位:使用 nethogs 或 iftop 找出占用带宽的进程 PID
- 先做:通过 tc 限制接口总速或 trickle 限制单进程,并设置 SSH 优先
- 再验证:在带宽满载情况下测试 SSH 输入响应和 ping 延迟
- 注意:操作前务必确认 VNC 控制台可用,并核对 SSH 端口与实际带宽
命令速用版
# 查看占用带宽的进程
sudo nethogs
# 限制某进程网速 (需安装 trickle)
# -d 下载限制,-u 上传限制,单位 KB/s
trickle -d 100 -u 50 ./your_program
# 为 SSH 设置高优先级 (示例 eth0,需替换带宽和端口)
# 请将 <TOTAL_BANDWIDTH> 替换为你的总带宽数值 (如 100)
# 请将 <SSH_PORT> 替换为你的实际 SSH 端口 (默认 22)
sudo tc qdisc add dev eth0 root handle 1: htb default 30
sudo tc class add dev eth0 parent 1: classid 1:1 htb rate <TOTAL_BANDWIDTH>mbit
sudo tc class add dev eth0 parent 1:1 classid 1:10 htb rate 10mbit prio 1
sudo tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport <SSH_PORT> 0xffff flowid 1:10
sudo tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip sport <SSH_PORT> 0xffff flowid 1:10
为什么会这样
当 VPS 出口带宽被后台进程占满时,网络接口的发送队列会堆积大量数据包。SSH 属于交互式流量,对延迟敏感,如果和业务数据混在同一队列中,必须等待前面的大数据包发送完毕才能处理,导致键盘输入回显慢甚至连接超时。
Linux 内核默认采用 FIFO 队列,不会自动区分管理流量和业务流量。需要通过流量控制(Traffic Control)机制人为干预队列调度。
分步处理
1. 确认 SSH 端口与带宽规格
在配置前,必须确认当前 SSH 监听端口和 VPS 实际带宽上限,避免配置错误导致无法连接或限速无效。
# 查看 SSH 端口配置
sudo grep "^Port" /etc/ssh/sshd_config
# 若未输出,默认为 22
# 查看网卡名称
ip addr
# 确认是 eth0, ens3 还是其他
2. 找出占用带宽的进程
使用 nethogs 可以看到每个进程的网络占用情况。如果没有安装,可通过包管理器安装。
sudo yum install nethogs # CentOS
sudo apt install nethogs # Ubuntu
运行后找到占用最高的进程 PID 或命令名。
3. 限制特定进程带宽(用户态方案)
如果是自己启动的程序,可以使用 trickle 包装启动。注意这仅适用于用户态程序,且需要重启该程序。
trickle -d 500 -u 100 ./your_application
参数 -d 限制下载,-u 限制上传,单位 KB/s。
4. 限制接口并优先保障 SSH(内核态方案)
如果无法控制进程启动方式,建议在网卡接口层面做限制。先设置总带宽略低于物理上限,留出余量,再将 SSH 流量设为最高优先级。
重要警告:执行 tc 命令前请确保你有控制台访问权限(VNC),防止配置错误导致无法 SSH 连接。建议先在测试环境验证。
# 清除旧规则 (防止冲突)
sudo tc qdisc del dev eth0 root 2>/dev/null
# 添加 HTB 队列
sudo tc qdisc add dev eth0 root handle 1: htb default 30
# 设置根类,假设物理带宽 100Mbps,限制为 90Mbps 留余量
# 请将 90mbit 替换为你实际带宽的 90% (如 10M 带宽则填 9mbit)
sudo tc class add dev eth0 parent 1: classid 1:1 htb rate 90mbit
# 设置 SSH 高优先级类,保障最低带宽
# 若总带宽较小 (如 5Mbps),建议保障 1mbit 即可
sudo tc class add dev eth0 parent 1:1 classid 1:10 htb rate 10mbit prio 1
# 设置其他流量默认类
sudo tc class add dev eth0 parent 1:1 classid 1:30 htb rate 80mbit prio 2
# 将 SSH 端口流量指向高优先级类
# 注意:若修改过 SSH 端口,请将 22 替换为实际端口号
sudo tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dport 22 0xffff flowid 1:10
sudo tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip sport 22 0xffff flowid 1:10
如何使配置开机生效
tc 规则存储在内存中,重启网络或服务器后会消失。建议编写脚本并加入开机启动。
1. 创建脚本
新建文件 /usr/local/bin/tc_ssh_priority.sh,填入以下内容(请根据实际情况修改带宽和端口):
#!/bin/bash
INTERFACE="eth0"
TOTAL_BW="90"
SSH_PORT="22"
# 清除旧规则
tc qdisc del dev $INTERFACE root 2>/dev/null
# 添加规则
tc qdisc add dev $INTERFACE root handle 1: htb default 30
tc class add dev $INTERFACE parent 1: classid 1:1 htb rate ${TOTAL_BW}mbit
tc class add dev $INTERFACE parent 1:1 classid 1:10 htb rate 10mbit prio 1
tc class add dev $INTERFACE parent 1:1 classid 1:30 htb rate $((TOTAL_BW - 10))mbit prio 2
tc filter add dev $INTERFACE protocol ip parent 1:0 prio 1 u32 match ip dport $SSH_PORT 0xffff flowid 1:10
tc filter add dev $INTERFACE protocol ip parent 1:0 prio 1 u32 match ip sport $SSH_PORT 0xffff flowid 1:10
赋予执行权限:
sudo chmod +x /usr/local/bin/tc_ssh_priority.sh
2. 设置开机自启
方法一:写入 rc.local(适用于大多数 VPS)
echo "/usr/local/bin/tc_ssh_priority.sh" | sudo tee -a /etc/rc.local
sudo chmod +x /etc/rc.local
方法二:创建 systemd 服务(更推荐)
新建 /etc/systemd/system/tc-priority.service:
[Unit]
Description=TC SSH Priority Rules
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/tc_ssh_priority.sh
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
启用服务:
sudo systemctl enable tc-priority.service
sudo systemctl start tc-priority.service
怎么验证是否生效
1. 查看队列状态
tc -s qdisc show dev eth0
观察是否有数据包 drop 或 backlog 变化。
2. 压力测试
在另一个终端启动带宽占用程序(如 dd if=/dev/zero of=/dev/null 配合限速或 wget 大文件),同时在本终端持续输入命令。如果 SSH 响应无明显延迟,说明优先级生效。
3. 延迟测试
新开一个终端 ping 服务器,观察满载时的延迟波动是否减小。
常见坑
- 规则重启失效:tc 规则存储在内存中,重启网络或服务器后会消失,必须写入启动脚本或 systemd 服务。
- 网卡名称错误:不同 VPS 厂商网卡名可能是 eth0、ens3 或 enp0s3,请用
ip addr确认。 - 锁死风险:配置错误可能导致 SSH 完全不可用,务必先测试 VNC 控制台是否可用。
- 方向混淆:SSH 卡顿通常是上传占满导致 ACK 包发送延迟,需同时关注上传和下载限制,tc 规则中 sport 和 dport 都要配置。
- 带宽数值硬编码:示例中的 90mbit 仅为示例,若你的 VPS 带宽只有 10Mbps,设置 90mbit 将无效,请按实际带宽比例设置。
- SSH 端口不一致:若修改过 SSH 默认端口,tc 规则中的端口号必须同步修改,否则 SSH 流量会被归类到默认低优先级队列。