最近准备取消一批垃圾小🐔,于是就有了服务迁移的问题。但要迁移到的服务器上已经有一些服务,这时我希望保证一些服务得到CPU和网络上传带宽的优先级较高,于是就有了本篇。
查资料查了半天,发现网络优先级并没有一个像CPU优先级那样的nice值或者cgroup进行管理,只查到RHEL系的Linux有一个net_prio
模块,还不知道是不是对进程/用户生效的东西,因为入手时间比较晚的服务器都装了Debian系统,所以这个也就没有继续深究。
最终的解决办法是tc+iptables,不过纯tc应该也可以达到相同的效果。大致原理是用tc/iptables给特定端口特定协议的数据包标记,标记的数据包使用tc保障带宽(高优先级规则),默认的走低优先级规则。这里的这种方法对流入服务器的带宽没有影响,代码(这里用的是tc+iptables,网卡假设为eth0
):
#!/bin/bash
# 总上传带宽
GLOBAL_LIMIT=8mbit
# 保障带宽
ENSURE_BAND_10=6mbit
# 保证规则
ENSURE_BAND_PROTO1=tcp
ENSURE_BAND_PROTO2=udp
ENSURE_BAND_PORT=8080
# 清空tc原有规则
tc qdisc del dev eth0 root
# 默认走1:99规则
tc qdisc add dev eth0 root handle 1: htb default 99
# 总规则
tc class add dev eth0 parent 1: classid 1:1 htb rate ${GLOBAL_LIMIT}
# 高优先级规则,保障设定的带宽
tc class add dev eth0 parent 1:1 classid 1:10 htb rate ${ENSURE_BAND_10} ceil ${GLOBAL_LIMIT} prio 0
# 默认规则,留200Kb给ssh等
tc class add dev eth0 parent 1:1 classid 1:99 htb rate 200kbit ceil ${GLOBAL_LIMIT} prio 1
# 使有标记的数据包走高优先级规则
tc filter add dev eth0 parent 1:0 prio 0 protocol ip handle 10 fw flowid 1:10
# 清空OUTPUT的mangle表
iptables -F OUTPUT -t mangle
# 给要保证带宽的协议端口标记
iptables -A OUTPUT -t mangle -p ${ENSURE_BAND_PROTO1} --sport ${ENSURE_BAND_PORT} -j MARK --set-mark 10
iptables -A OUTPUT -t mangle -p ${ENSURE_BAND_PROTO2} --sport ${ENSURE_BAND_PORT} -j MARK --set-mark 10
参考:
cgroup 子系统之 net_cls 和 net_prio | ggaaooppeenngg
Example of a full nat solution with QoS (lartc.org)
Advanced traffic control – ArchWiki (archlinux.org)
tc: Linux HTTP Outgoing Traffic Shaping (Port 80 Traffic Shaping) – nixCraft (cyberciti.biz)
至于CPU保障,一般用途使用nice值(高-20~19低)控制就已经完全足够,下面贴一下renice
的usage
renice [-n] <priority> [-p|--pid] <pid>...
renice [-n] <priority> -g|--pgrp <pgid>...
renice [-n] <priority> -u|--user <user>...
设定某用户的默认nice值需要修改limits.conf
文件,一般位置在/etc/security/limits.conf
,修改user1用户的默认nice值为-10:
user1 soft priority -10
参考:Changing the default nice value for a user or group – Benjamin Cane (bencane.com)
至于更高级的,把某个进程分配到特定核心上,或者使用实时调度器,感觉瞎玩玩的场景用不到,就没有深究。
参考:Linux: Assign Process to CPU Core – Stack Pointer
Views: 52