通过流量整形减慢服务器速度

通过流量整形减慢服务器速度

我想研究从慢速服务器流式传输的应用程序的行为。我试图利用tc-netem引入网络延迟。

在设置更复杂的场景之前,我决定在虚拟机上执行此操作,该虚拟机应该模拟慢速服务器。我通过访问虚拟机ssh,所以我决定创建一个虚拟以太网,这会延迟,而我计划使用真实的以太网设备进行管理。

首先,我创建了假接口ip link add link eth0 type macvtap并为其分配了 IP 地址。

然后我添加了 40 毫秒的延迟tc qdisc add dev macvtap0 root netem delay 40000。这实际上让我的吞吐量下降了(从 ~250 MiB/秒到 ~6 MiB/秒)。

此时,我尝试稍微调整一下我的设置,然后我开始意识到延迟不仅影响设备macvtap0,而且还影响eth0我所连接的设备(简而言之,我的ssh会话开始滞后)。

我认为我netem delay影响了实际的网卡。这是因为我在虚拟机中工作吗?或者我应该使用不同的棕褐色macvtap?或者可能是因为我将更改应用到了root qdisc

编辑- 这是我第一次进入看似巨大的流量差异化世界。也许有更好的方法?例如,我可以设置一个队列来减慢选定的进程吗?我决定重新命名这个问题以反映我的实际目的。

答案1

首先说明一下:增加延迟与限制带宽不同。考虑地球同步卫星互联网链接:单向流有约 1/4 秒的强制性延迟(由于光速),因此如果整个路径通过卫星传输,往返可能为约 1/2 秒,并且它是成为能够达到 506 Mbps使用现代技术:大量数据可以在这个 1/2 秒的窗口中传输,无需等待每个数据包的确认后再发送下一个数据包。当然,延迟对速度没有任何帮助,而且可能会因为等待确认、需要重传等而阻碍速度。

由于提出问题的问题和问题的目标是真的不同的是,除了这些信息之外,我只会回答以下问题。

一些 qdisc 具有内置的速率限制功能:HTB,TBF,...这里有两个关于限制带宽(而不是增加延迟)的建议:

  • 使用 TC 限制 Linux 上的网络带宽

    # tc qdisc add dev eth0 root tbf rate 1024kbit latency 50ms burst 1540
    

    请注意,与往常一样,限制是针对出口的。为了限制进入,IFB必须插入设备,如我的回答中的示例使用netem模拟桥接接口上的丢包

  • 好(不是那么旧)wondershaper脚本(v1.4。它在某些发行版(如 Debian)中已经过时),它可以创造奇迹:虽然设计用于优先考虑流并降低延迟,但它也可以降低速率,并且已经使用 IFB 以简单的方式进行限制出口和入口。

    # wondershaper -a eth0 -d 1000 -u 100会将eth0的带宽限制为 1000 kbps 下载和 100 kbps 上传。

现在关于这个问题...


该问题与以下内容无关macvtap(该tap部分甚至没有在OP的设置中使用),也不macvlan也没有任何虚拟化也没有tc-netem。它与使用同一 IP LAN 将多个接口置于同一以太网 LAN 中时路由的工作方式有关。

由于如果没有 OP 在虚拟机中的特定配置,就无法确定发生了什么,因此我将在几个网络命名空间中重现一个人为示例:“system”同行ping“系统”双卡,两者都通过“开关”链接

添加第二张卡之前的初始配置:

ip netns del bridge || :
ip netns del twocards || :
ip netns del peer || :
ip netns add bridge
ip netns add twocards
ip netns add peer
ip -n bridge link add bridge0 type bridge
ip -n twocards link add eth0 type veth peer netns bridge name port1
ip -n peer link add eth0 type veth peer netns bridge name port2
ip -n bridge link set port1 master bridge0
ip -n bridge link set port2 master bridge0
ip -n bridge link set port1 up
ip -n bridge link set port2 up
ip -n bridge link set bridge0 up
ip -n twocards link set eth0 up
ip -n peer link set eth0 up
ip -n twocards address add dev eth0 192.0.2.1/24
ip -n peer address add dev eth0 192.0.2.2/24

现在:

# ip -n twocards route
192.0.2.0/24 dev eth0 proto kernel scope link src 192.0.2.1 

在使用无处不在的 NetworkManager 的典型安装中,会有一metric 100组以太网设备,让我们做同样的事情:

ip -n twocards route add 192.0.2.0/24 dev eth0 src 192.0.2.1 metric 100
ip -n twocards route del 192.0.2.0/24 dev eth0 src 192.0.2.1

我们来测量一下:

# ip netns exec peer ping -c2 192.0.2.1 
PING 192.0.2.1 (192.0.2.1) 56(84) bytes of data.
64 bytes from 192.0.2.1: icmp_seq=1 ttl=64 time=0.116 ms
64 bytes from 192.0.2.1: icmp_seq=2 ttl=64 time=0.060 ms

--- 192.0.2.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1018ms
rtt min/avg/max/mdev = 0.060/0.088/0.116/0.028 ms

结果正常。添加第二张卡,为其添加 IP 并添加 netem 队列:

ip -n twocards link add eth1 type veth peer netns bridge name port3
ip -n bridge link set port3 master bridge0
ip -n bridge link set port3 up
ip -n twocards link set eth1 up
ip -n twocards address add dev eth1 192.0.2.3/24
ip netns exec twocards tc qdisc add dev eth1 root netem delay 40000

新路线:

# ip -n twocards route
192.0.2.0/24 dev eth1 proto kernel scope link src 192.0.2.3 
192.0.2.0/24 dev eth0 scope link src 192.0.2.1 metric 100 

新行为(假设继承rp_filter已设置):

# ip netns exec peer ping -c2 192.0.2.1 
PING 192.0.2.1 (192.0.2.1) 56(84) bytes of data.

--- 192.0.2.1 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1021ms

发生了什么?现在路由和 ARP 行为开始发挥作用:

# ip -n twocards route get 192.0.2.2 from 192.0.2.1
192.0.2.2 from 192.0.2.1 dev eth1 uid 0 
    cache 
# ip -n twocards -br link
lo               DOWN           00:00:00:00:00:00 <LOOPBACK> 
eth0@if3         UP             96:45:4d:f0:52:35 <BROADCAST,MULTICAST,UP,LOWER_UP> 
eth1@if5         UP             c2:70:b7:40:6c:40 <BROADCAST,MULTICAST,UP,LOWER_UP> 

# ip -n peer neighbour
192.0.2.1 dev eth0 lladdr 96:45:4d:f0:52:35 REACHABLE

上的路由表双卡现在会使用eth1甚至对于分配给 的地址eth0。 Linux 只是遵循其路由表的默认行为。因为rp_filter启动后,设备eth0(其 MAC 仍在同行的缓存)。如果rp_filter没有设置,这将适用于非对称路由:在 上 ping 请求eth0,在 上 ping 回复eth1,(延迟netem)直到同行的 ARP 缓存最终过期,然后eth1仅使用(仅出口像往常一样延迟)。

让我们清除 ARP 缓存同行然后再试一次:

# ip -n peer neighbour flush dev eth0
# ip netns exec peer ping -c2 192.0.2.1 
PING 192.0.2.1 (192.0.2.1) 56(84) bytes of data.
64 bytes from 192.0.2.1: icmp_seq=1 ttl=64 time=80.2 ms
64 bytes from 192.0.2.1: icmp_seq=2 ttl=64 time=40.1 ms

--- 192.0.2.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 40.141/60.178/80.215/20.037 ms

# ip -n peer neighbour
192.0.2.1 dev eth0 lladdr c2:70:b7:40:6c:40 REACHABLE

第一个 ping(仅)被 netem 延迟两次:一次用于底层 ARP 回复 ARP 请求,一次用于实际 ping 回复。

让我们删除额外设备的路由双卡并再次清除 ARP 缓存同行:

ip -n twocards route del 192.0.2.0/24 dev eth1
ip -n peer neighbour flush dev eth0

再次正常结果:

# ip netns exec peer ping -c2 192.0.2.1
PING 192.0.2.1 (192.0.2.1) 56(84) bytes of data.
64 bytes from 192.0.2.1: icmp_seq=1 ttl=64 time=0.108 ms
64 bytes from 192.0.2.1: icmp_seq=2 ttl=64 time=0.050 ms

--- 192.0.2.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.050/0.079/0.108/0.029 ms

同样 ping 分配给的 IPeth1现在也会通过双卡毫不eth0拖延:

# ip netns exec peer ping -c2 192.0.2.3
PING 192.0.2.3 (192.0.2.3) 56(84) bytes of data.
64 bytes from 192.0.2.3: icmp_seq=1 ttl=64 time=0.143 ms
64 bytes from 192.0.2.3: icmp_seq=2 ttl=64 time=0.042 ms

--- 192.0.2.3 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1024ms
rtt min/avg/max/mdev = 0.042/0.092/0.143/0.051 ms

那么对此应该怎么办呢?只是不要在同一系统上使用同一以太网 LAN 上的两个网络设备,尤其是在使用同一 IP LAN 时,这会导致麻烦。macvlan或设备macvtap通常不应该由主机直接使用:它应该被移交给具有自己独立路由堆栈的虚拟机或容器(另一个网络命名空间),因此这不会成为问题一个典型的用法。

如果出于某种原因必须使用同一 LAN 上的两张卡(除了绑定、分组等之外),则必须进行额外的相当复杂的配置来避免这种情况。请参阅我在 SF 上的回答多 NIC Linux 系统上的 Ghost ping了解详情。

答案2

我不确定你遇到的问题,所以我跳过它。

如果您想调整每个进程的流量整形,您将需要使用有类排队规则。 HTB 或 HSFC 可能是您最好的选择。使用它,您可以创建一棵排队规则树(netem 可以附加到其中一个叶子)并使用 分配它们之间的流量tc filter

过滤非常灵活,因为fw过滤方法可以查找 iptables 标记,这意味着您可以使用 iptables 选择流量。您也可以直接选择流量。

话虽如此,请注意 qdisc 仅对传出流量有效。您可以拥有一个入口 qdisc,但这非常有限,并且可能不会按照您的预期运行。

出于测试目的,一个不错的选择是创建一个具有两个接口的真实虚拟机,并以某种方式强制通过该虚拟机路由流量。可能需要一些技巧(即几个级别的 NAT)。然后,在虚拟机中,您可以在两个接口上附加您喜欢的任何 qdisc,从而控制流量的两个方向。

相关内容