这在Linux中可以通过iptables
和来实现tc
。您可以将iptables配置为MARK
已传输一定数量字节的连接上的数据包。然后tc
,您可以将这些标记的数据包放在排队规则的类中,以对带宽进行速率限制。
有点棘手的部分是限制上载和下载的连接。tc
不支持入口流量整形。您可以通过在面向Web服务器的界面上调整出口(这将对下载到您的Web服务器的形状)进行整形,并在面向上游提供者的界面上调整出口(将对从Web服务器的上传进行整形)来解决此问题。由于您无法控制上游提供商发送数据的速度,因此您并没有真正在影响入口(下载)流量。但是,对面向Web服务器的界面进行整形将导致数据包丢失,并且上传程序会缩小其TCP窗口以适应带宽限制。
示例:(假设这是在基于Linux的路由器上,面向接口的Web服务器是eth0
,上游是eth1
)
# mark the packets for connections over 4MB being forwarded out eth1
# (uploads from webserver)
iptables -t mangle -A FORWARD -p tcp -o eth1 -m connbytes --connbytes 4194304: --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark 50
# mark the packets for connections over 4MB being forwarded out eth0
# (downloads to webserver)
iptables -t mangle -A FORWARD -p tcp -o eth0 -m connbytes --connbytes 4194304: --connbytes-dir both --connbytes-mode bytes -j MARK --set-mark 50
# Setup queuing discipline for server-download traffic
tc qdisc add dev eth0 root handle 1: htb
tc class add dev eth0 parent 1: classid 1:50 htb rate 50mbit
# Setup queuing discipline for server-upload traffic
tc qdisc add dev eth1 root handle 1: htb
tc class add dev eth1 parent 1: classid 1:50 htb rate 50mbit
# set the tc filters to catch the marked packets and direct them appropriately
tc filter add dev eth0 parent 1:0 protocol ip handle 50 fw flowid 1:50
tc filter add dev eth1 parent 1:0 protocol ip handle 50 fw flowid 1:50
如果您想在网络服务器本身而不是在Linux路由器上执行此操作,则仍然可以使用上述内容的上载部分。一个值得注意的变化是您将替换FOWARD
为OUTPUT
。要进行下载,您需要使用“中间功能块”设备或来设置排队规则ifb
。简而言之,它使用虚拟接口,因此您可以将入口流量视为出口,并使用从此处进行调整tc
。有关如何设置的更多信息,请ifb
参见:https://serverfault.com/questions/350023/tc-ingress-policing-and-ifb-mirroring
请注意,这种类型的内容往往需要大量调整才能缩放。迫在眉睫的是connbytes
依赖conntrack
模块,它往往会碰到带有大量连接的缩放壁。我建议进行重负载测试。
另一个警告是,这对于UDP根本不起作用,因为它是无状态的。还有其他技术可以解决此问题,但看起来您的要求仅针对TCP。
另外,要撤消上述所有操作,请执行以下操作:
# Flush the mangle FORWARD chain (don't run this if you have other stuff in there)
iptables -t mangle -F FORWARD
# Delete the queuing disciplines
tc qdisc del dev eth0 root
tc qdisc del dev eth1 root