Linux服务器端口级带宽管控:TC+HTB在Nginx/PHP服务中的实战应用

当你的服务器同时运行着关键业务网站和资源密集型API服务时,带宽争夺战往往悄无声息地爆发。某个深夜,文件上传功能突然占满带宽,导致前端页面加载缓慢;或是促销活动期间,支付接口被突发流量淹没,整个电商系统陷入瘫痪——这些场景对运维工程师来说都不陌生。传统QoS方案和云厂商提供的统一限速功能,在面对这种 端口级精细管控需求 时往往力不从心。

1. 为什么需要端口级流量控制?

云平台提供的带宽限制就像给整栋大楼安装总水阀,而我们需要的是给每个房间安装独立水表。当Nginx(80/443)和PHP-FPM(9000)共享同一台服务器时,简单的全局限速会导致两种典型问题:

  • 资源浪费 :为应对峰值流量设置过高带宽上限,平时大部分配额闲置
  • 服务雪崩 :某个端口突发流量挤占其他服务资源,引发连锁反应

HTB(Hierarchical Token Bucket)算法 的独特优势在于:

  • 支持 带宽保证 (Guaranteed Rate)
  • 允许 突发借用 (Burst)
  • 实现 层级分配 (Hierarchy)
# 查看系统支持的qdisc类型
grep htb /proc/net/psched

2. TC核心组件实战配置

2.1 基础环境准备

确保内核支持HTB(现代Linux发行版默认包含):

modprobe sch_htb && lsmod | grep htb

识别需要控制的网卡:

ip -o link show | awk '{print $2,$9}' | cut -d':' -f1

2.2 三级带宽分配实战

假设服务器总带宽100Mbps,需要为以下服务分配:

  • Nginx主站:保证50Mbps,可突发至70Mbps
  • PHP-FPM API:保证30Mbps,可突发至50Mbps
  • 其他流量:限制20Mbps
# 清除现有规则
tc qdisc del dev eth0 root

# 创建HTB根队列
tc qdisc add dev eth0 root handle 1: htb default 20

# 第一级分类(总带宽)
tc class add dev eth0 parent 1: classid 1:1 htb rate 100mbit ceil 100mbit

# 第二级分类(服务分配)
tc class add dev eth0 parent 1:1 classid 1:10 htb rate 50mbit ceil 70mbit
tc class add dev eth0 parent 1:1 classid 1:20 htb rate 30mbit ceil 50mbit 
tc class add dev eth0 parent 1:1 classid 1:30 htb rate 20mbit ceil 20mbit

# 端口过滤器配置
tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 \
  match ip dport 80 0xffff flowid 1:10
tc filter add dev eth0 protocol ip parent 1:0 prio 2 u32 \
  match ip dport 9000 0xffff flowid 1:20

关键参数说明: rate 表示保证带宽, ceil 表示最大可用带宽, prio 决定匹配顺序

3. 高级管控技巧

3.1 动态带宽调整

通过脚本实现上班时间(9:00-18:00)自动调整带宽分配:

#!/bin/bash
HOUR=$(date +%H)
if [ $HOUR -ge 9 ] && [ $HOUR -lt 18 ]; then
  tc class change dev eth0 parent 1:1 classid 1:10 htb rate 70mbit ceil 90mbit
else
  tc class change dev eth0 parent 1:1 classid 1:10 htb rate 50mbit ceil 70mbit
fi

3.2 结合iptables实现复杂过滤

当需要基于IP和端口组合限速时:

# 标记特定IP访问9000端口的流量
iptables -t mangle -A OUTPUT -p tcp --dport 9000 -d 192.168.1.100 -j MARK --set-mark 100

# 将标记流量导向特定class
tc filter add dev eth0 parent 1:0 protocol ip handle 100 fw flowid 1:30

3.3 监控与排错

实时监控各class带宽使用:

watch -n 1 'tc -s class show dev eth0'

关键指标解读:

指标 说明 健康阈值
sent 已发送数据 结合rate判断
rate 当前速率 不超过ceil
drops 丢包数 <100/min

4. 生产环境集成方案

4.1 systemd服务化配置

创建 /etc/systemd/system/tc-traffic-shaping.service

[Unit]
Description=TC Traffic Shaping
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/tc-setup.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

配套脚本 /usr/local/bin/tc-setup.sh 需添加:

#!/bin/bash
# 防止重复执行
if [ -f /var/lock/tc.lock ]; then
  exit 0
fi
touch /var/lock/tc.lock

# 实际TC配置命令
...

4.2 异常处理机制

/etc/rsyslog.d/10-tc-monitor.conf 中添加:

:msg, contains, "tc qdisc" /var/log/tc.log
& stop

配套日志分析脚本:

#!/usr/bin/env python3
import re
from collections import defaultdict

log_pattern = re.compile(r'class (\d+:\d+).*sent (\d+)')
stats = defaultdict(int)

with open('/var/log/tc.log') as f:
    for line in f:
        match = log_pattern.search(line)
        if match:
            class_id, bytes_sent = match.groups()
            stats[class_id] += int(bytes_sent)
            
    for class_id, total in stats.items():
        print(f"{class_id}: {total//1024} KB")

5. 性能优化与限制

5.1 内核参数调优

调整 /etc/sysctl.conf 提升TC性能:

net.core.netdev_max_backlog = 10000
net.core.somaxconn = 32768
net.core.dev_weight = 512

5.2 HTB参数优化建议

参数 推荐值 作用
quantum 1514 每次调度发送的字节数
r2q 10 估算的内部参数
burst 15kb 允许的瞬时突发

设置示例:

tc class add dev eth0 parent 1:1 classid 1:10 htb \
  rate 50mbit ceil 70mbit burst 15k quantum 1514

在实际生产环境中,我们曾遇到PHP文件上传功能突发流量导致主站响应延迟的问题。通过将9000端口的保证带宽设置为30Mbps,主站响应时间从2秒降低到200毫秒以内,而文件上传功能仍能保持可用——这正是端口级流量控制的魅力所在。

更多推荐