VPS 带宽跑满导致 SSH 卡顿如何限制后台进程网速优先保障管理

文章导读
带宽跑满时 SSH 卡顿是因为管理流量被业务数据挤占,最直接的止血方案是通过流量控制工具限制占用带宽的进程,并为 SSH 端口设置高优先级。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 如何使配置开机生效
  5. 怎么验证是否生效
  6. 常见坑
A A

带宽跑满时 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 包装启动。注意这仅适用于用户态程序,且需要重启该程序。

VPS 带宽跑满导致 SSH 卡顿如何限制后台进程网速优先保障管理
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. 设置开机自启

VPS 带宽跑满导致 SSH 卡顿如何限制后台进程网速优先保障管理

方法一:写入 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 流量会被归类到默认低优先级队列。