其他分享
首页 > 其他分享> > 云边通信中如何对边缘节点进行流量整形?

云边通信中如何对边缘节点进行流量整形?

作者:互联网

1、问题背景

之前项目需要一个边缘集群场景下的镜像缓存功能,但随之而来的问题是:

由于边缘节点网络带宽资源有限,加上云边网络的不稳定性,当边缘节点频繁拉取云端镜像文件时会占用大量的网络带宽,这样会阻碍其他网络应用程序的运行,比如此时我们的交互式SSH会话可能会变得异常迟钝以至于无法使用。因此我们需要一种方法来对高带宽应用进行流量整形。

目前可以根据 image id、container id来对特定容器进行带宽限制,下一步准备在k8s环境中进行运用。

代码地址:YRXING/bandwidth-limit

2、高效Linux限流神器——Trickle

如果在容器内使用trickle工具,加上--cap-add=NET_ADMIN选项

2.1、安装与使用

yum install trickle

#源码编译安装
wget https://codeload.github.com/mariusae/trickle/zip/master
mv master trickle-master.zip
unzip trickle-master.zip
yum -y install autoconf automake libtool libevent-devel
autoreconf -if
./configure
make
make install

#使用时,仅需要放在你想要运行的命令之前
trickle -d <download-rate> -u <update-rate> <command> #单位 KB/s

#trickle还可以以守护进程形式启动,它可以限制通过trickle启动的所有程序的总带宽使用
trickle -d 1000

2.2、trickle如何工作的

Trickle通过控制socket数据读写量来控制和限制应用的上传/下载速度。它使用另一个版本的BSD套接字API,但区别就是trickle还管理socket调用。

但是要注意的是trickle使用动态链接和加载,所以它只对于使用glibc库的程序有用。由于trickle可以设置数据在socket上的传输延迟,所以它可以用来限制一个应用的网络带宽。

Trickle通过在程序运行时,预先加载一个速率限制 socket 库 的方法,trickle 命令允许你改变任意一个特定程序的流量。trickle 命令有一个很好的特性是它仅在用户空间中运行,这意味着,你不必需要 root 权限就可以限制一个程序的带宽使用。要能使用 trickle 程序控制程序的带宽,这个程序就必须使用非静态链接库的套接字接口。当你想对一个不具有内置带宽控制功能的程序进行速率限制时,trickle 就派上用场了。

socket编程中,可以通过修改发送和接收缓冲区的大小,完全利用可用的带宽。

int ret, sock, sock_buf_size;
sock = socket( AF_INET, SOCK_STREAM, 0 );
sock_buf_size = BDP;
ret = setsockopt( sock, SOL_SOCKET, SO_SNDBUF,
                   (char *)&sock_buf_size, sizeof(sock_buf_size) );
ret = setsockopt( sock, SOL_SOCKET, SO_RCVBUF,
                   (char *)&sock_buf_size, sizeof(sock_buf_size) );

3、控制网卡带宽——wondershaper

3.1、安装与使用

yum install wondershaper

#使用
wondershaper <interface> <download-rate> <update-rate> #单位KB/s
#比如限制eth0网卡带宽
wondershaper etho 1000 500
#解除限制
wondershaper clear etho

wondershaper实际上是一个shell脚本,它使用tc来定义流量调整命令,使用QoS来处理特定的网络接口。外发流量通过放在不同优先级的队列中,达到限制传出流量速率的目的,而传入流量通过丢包的方式来达到速率限制的目的。

4、Linux自带高级流控——tc

Linux操作系统中的流量控制器TC(Traffic Control)用于Linux内核的流量控制,主要是通过在输出端口处建立一个队列来实现流量控制。tc属于 iproute2 可以直接修改内核的流控设置。

iproute2简介
iproute2是linux下管理控制TCP/IP网络和流量控制的新一代工具包,旨在替代老派的工具链net-tools,即大家比较熟悉的ifconfig,arp,route,netstat等命令。
要说这两套工具本质的区别,应该是net-tools是通过procfs(/proc)和ioctl系统调用去访问和改变内核网络配置,而iproute2则通过netlink套接字接口与内核通讯。

其次,net-tools的用法给人的感觉是比较乱,而iproute2的用户接口相对net-tools来说相对来说,更加直观。比如,各种网络资源(如link、IP地址、路由和隧道等)均使用合适的对象抽象去定义,使得用户可使用一致的语法去管理不同的对象

img

Linux流量控制主要分为建立队列、建立分类和建立过滤器三个方面。

4.1、原理

它以qdisc-class-filter的树形结构来实现对流量的分层控制

Traffic Control

Traffic Control

类(Class)组成一个树,每个类都只有一个父类,而一个类可以有多个子类。某些QDisc(例如:CBQ和HTB)允许在运行时动态添加类,而其它的QDisc(例如:PRIO)不允许动态建立类。允许动态添加类的QDisc可以有零个或者多个子类,由它们为数据包排队。此外,每个类都有一个叶子QDisc,默认情况下,这个叶子QDisc使用pfifo的方式排队,我们也可以使用其它类型的QDisc代替这个默认的QDisc。而且,这个叶子QDisc有可以分类,不过每个子类只能有一个叶子QDisc。 当一个数据包进入一个分类QDisc,它会被归入某个子类。 我们可以使用以下三种方式为数据包归类,不过不是所有的QDisc都能够使用这三种方式:

4.2、应用

  1. 针对端口进行限速

    #查看现有的队列
    tc -s qdisc ls dev eth0
    
    #查看现有的分类
    tc -s class ls dev eth0
    
    #创建队列
    tc qdisc add dev eth0 root handle 1:0 htb default 1 
    #添加一个tbf队列,绑定到eth0上,命名为1:0 ,默认归类为1
    #handle:为队列命名或指定某队列
    
    #创建分类
    tc class add dev eth0 parent 1:0 classid 1:1 htb rate 10Mbit burst 15k
    #为eth0下的root队列1:0添加一个分类并命名为1:1,类型为htb,带宽为10M
    #rate: 是一个类保证得到的带宽值.如果有不只一个类,请保证所有子类总和是小于或等于父类.
    #ceil: ceil是一个类最大能得到的带宽值.
    
    #创建一个子分类
    tc class add dev eth0 parent 1:1 classid 1:10 htb rate 10Mbit ceil 10Mbit burst 15k
    #为1:1类规则添加一个名为1:10的类,类型为htb,带宽为10M
    
    #为了避免一个会话永占带宽,添加随即公平队列sfq.
    tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
    #perturb:是多少秒后重新配置一次散列算法,默认为10秒
    #sfq,他可以防止一个段内的一个ip占用整个带宽
    
    #使用u32创建过滤器
    tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip sport 22 flowid 1:10
    
    #删除队列
    tc qdisc del dev eth0 root
    
    配置完成后加入本地启动文件:  
    /etc/rc.local
    
  2. 针对ip进行限速:

    情景: 因为带宽资源有限(20Mbit≈2Mbyte),使用git拉取代码的时候导致带宽资源告警,所以对git进行限速,要求:内网不限速;外网下载速度为1M左右。(注意:此处需要注意单位转换1byte=8bit)...

    #!/bin/bash
    #针对不同的ip进行限速
    
    #清空原有规则
    tc qdisc del dev eth0 root
    
    #创建根序列
    tc qdisc add dev eth0 root handle 1: htb default 1
    
    #创建一个主分类绑定所有带宽资源(20M)
    tc class add dev eth0 parent 1:0 classid 1:1 htb rate 20Mbit burst 15k
    
    #创建子分类
    tc class add dev eth0 parent 1:1 classid 1:10 htb rate 20Mbit ceil 10Mbit burst 15k
    tc class add dev eth0 parent 1:1 classid 1:20 htb rate 20Mbit ceil 20Mbit burst 15k
    
    #避免一个ip霸占带宽资源(1有讲到)
    tc qdisc add dev eth0 parent 1:10 handle 10: sfq perturb 10
    tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10
    
    #创建过滤器
    #对所有ip限速
    tc filter add dev eth0 protocol ip parent 1:0 prio 2 u32 match ip dst 0.0.0.0/0 flowid 1:10
    #对内网ip放行
    tc filter add dev eth0 protocol ip parent 1:0 prio 1 u32 match ip dst 12.0.0.0/8 flowid 1:20
    
  3. 控制出口流量

    基于 classless 队列,我们可以进行故障模拟,也可以用来限制带宽。TC 使用 linux network netem 模块进行网络故障模拟。

    #模拟网络延迟
    tc qdisc add dev eth0 root netem delay 100ms #添加一个固定延迟到本地网卡eth0
    tc qdisc change dev eth0 root netem delay 100ms 10ms #延迟有10ms的上下波动
    tc qdisc change dev eth0 root netem delay 100ms 10ms 25% #添加25%的相关概率
    tc qdisc change dev eth0 root netem delay 100ms 10ms distribution normal  #让波动成正太分布
    #模拟网络丢包
    tc qdisc change dev eth0 root netem loss 1% #丢包率1%
    tc qdisc change dev eth0 root netem loss 1% 25% #当前丢包概率与上一条数据包丢包概率有25%的相关性
    #模拟数据包重复
    tc qdisc change dev eth0 root netem duplicate 1%
    #模拟数据包损坏
    tc qdisc change dev eth0 root netem corrupt 2%
    #模拟数据包乱序
    tc qdisc change dev eth0 root netem gap 5 delay 10ms #没5th的包延迟10ms
    tc qdisc change dev eth0 root netem delay 10ms reorder 25% 50% # 25%的立刻发送(50%的相关性),其余的延迟 10ms
    
  4. 控制入口流量

    使用 TC 进行入口限流,需要把流量重定向到 ifb 虚拟网卡,然后在控制 ifb 的输出流量

    # 开启 ifb 虚拟网卡
    modprobe ifb numifbs=1
    ip link set ifb0 up
    
    # 将 eth0 流量重定向到 ifb0
    tc qdisc add dev eth0 ingress handle ffff:
    tc filter add dev eth0 parent ffff: protocol ip prio 0 u32 match u32 0 0 flowid ffff: action mirred egress redirect dev ifb0
    
    # 然后就是限制 ifb0 的输出就可以了
    # ......
    
  5. 监视

    #显示队列的情况
    tc [-s] qdisc|class|filter| ls dev eth0 # -s 显示详细信息
    

4.3、队列规则Qdisc详解

无分类的qdisc:只能用于root队列

使用建议

有分类的qdisc(可以包括多个队列)

如果想对不同的流量做不同的处理,那么classful qdisc非常有用。

4.4、用过滤器对流量进行分类

class用来表示控制策略,只用于有分类的qdisc上。每个class要么包含多个子类,要么只包含一个子qdisc。当然,每个class还包括一些列的filter,控制数据包流向不同的子类,或者是直接丢掉。

filter用来将数据包划分到具体的控制策略中,filter是在qdisc内部。包括以下几种:

截屏2021-06-19 下午5.34.35

当enqueue一个包时,在每一个分叉的地方都需要查询相关的过滤规则。

一种配置是:在1:1配置一个filter,将包送到12: 。在12:配置一个filter,将包送到12:2

另一种配置是将两个filter都配置在1:1,但将更精确的filter放到更下面的位置有助于提升性能。

需要注意的是,包是无法向上过滤的(filter a packet ‘upwards’)。 另外,使用 HTB 时,所有的 filters 必须 attach 到 root

示例配置:

# 假设一个名为10:的PRIO qdisc,我们想将端口22的流量都导向优先级最高的band
tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip dport 22 0xffff flowid 10:1
tc filter add dev eth0 protocol ip parent 10: prio 1 u32 match ip sprot 80 0xffff flowid 10:1
tc filter add dev eth0 protocol ip parent 10: prio 2 flowid 10:2 #为匹配上面的包都发送到优先级次高的band 10:2

# 精确匹配单个IP地址
tc filter add dev eth0 parent 10: protocol ip prio 1 u32 match ip dst 4.3.2.1/32 flowid 10:1
tc filter add dev eth0 parent 10: protocol ip prio 1 u32 match ip src 1.2.3.4/32 flowid 10:1
tc filter add dev eth0 parent 10: protocol ip prio 2 flowid 10:2
#这会将 dst_ip=4.3.2.1 或 src_ip=1.2.3.4 的流量送到优先级最高的队列,其他流量送到优先级次高的队列

#还可以将多个match级联起来,同时匹配源IP和port
tc filter add dev eth0 parent 10: protocol ip prio 1 u32 match ip port src 4.3.2.1/32 \
match ip port 80 0xffff flowid 10:1

4.5、ingress shaping

IMQ

中介队列设备用来解决两个局限:

对外部进来的包先打上标记(mark),打了标的包在经过 netfilter NF_IP_PRE_ROUTINGNF_IP_POST_ROUTING hook 点时会被捕获,送到 IMQ 设备上 attach 的 qdisc。就能实现入向整型(ingress shaping);将接口们作为 classes(treat interfaces as classes),就能设置全局限速

示例配置:

tc qdisc add dev imq0 root handle 1: htb default 20

tc class add dev imq0 parent 1: classid 1:1 htb rate 2mbit burst 15k

tc class add dev imq0 parent 1:1 classid 1:10 htb rate 1mbit
tc class add dev imq0 parent 1:1 classid 1:20 htb rate 1mbit

tc qdisc add dev imq0 parent 1:10 handle 10: pfifo
tc qdisc add dev imq0 parent 1:20 handle 20: sfq

tc filter add dev imq0 parent 10:0 protocol ip prio 1 u32 match \
ip dst 10.0.0.230/32 flowid 1:10

接下来选中流量,给他们打上标记,以便被正确送到imq0设备:

iptabels -t mangle -A PREROUTING -i eth0 -j IMQ --todev 0
ip link set imq0 up

ifb——见5.3

5、Linux网络测试工具

5.1、实时网络流量监控——iftop

Iftop工具主要用来显示本机网络流量情况及各相互通信的流量集合,如单独同哪台机器间的流量大小,非常适合于代理服务器和iptables服务器使用,这样可以方便的查看各客户端流量情况。iftop可以用来监控网卡的实时流量(可以指定网段)、反向解析IP、显示端口信息等,详细的将会在后面的使用参数中说明。

# 安装所需依赖包
yum -y install flex byacc libpcap ncurses ncurses-devel libpcap-devel

wget http://www.ex-parrot.com/pdw/iftop/download/iftop-0.17.tar.gz  #下载安装包
tar zxvf iftop-0.17.tar.gz  #解压
cd iftop-0.17
./configure --prefix=/usr/local/iftop  #配置安装目录
make && make install   #编译、安装
cp /usr/local/iftop /usr/local/bin

截屏2021-06-17 下午3.24.08

交互界面操作

过滤和排序&启动参数

在交互模式,按下l(表示limit)会在顶端显示一个文本输入框,可以输入过滤规则,只显示特定内容。

iftop大多数启动参数和交互界面的快捷键相关。

使用-f参数是一种过滤特性数据包的方法,可以组合网络,主机或端口。例如以下只显示在/dev/wlan0无限网卡接口的ssh数据包

iftop -i wlan0 -f "dst port 22"
过滤器 描述
dst host 1.2.3.4 所有目标地址是1.2.3.4的数据包
src port 22 所有从端口22发出的数据包
dst portrange 22-23 端口范围是22到23的数据包
gateway 1.2.3.5 使用网关地址1.2.3.5的数据包

5.2、带宽测试工具——iperf3

Iperf可以测试最大TCP和UDP带宽性能,具有多种参数和UDP特性,可以根据需要调整,可以报告带宽、延迟抖动和数据包丢失.对于每个测试,它都会报告带宽,丢包和其他参数,可在Windows、Mac OS X、Linux、FreeBSD等各种平台使用,是一个简单又实用的小工具。

Iperf3也是C/S(客户端/服务器端)架构模式,在使用iperf3测试时,要同时在server端与client端都各执行一个程序,让它们互相传送报文进行测试。

yum install -y iperf3

服务端命令行

-s    表示服务器端;
-p    定义端口号;
-i    设置每次报告之间的时间间隔,单位为秒,如果设置为非零值,就会按照此时间间隔输出测试报告,默认值为零

客户端命令行

-c    表示服务器的IP地址;
-p    表示服务器的端口号;
-t    参数可以指定传输测试的持续时间,Iperf在指定的时间内,重复的发送指定长度的数据包,默认是10秒钟.

-i    设置每次报告之间的时间间隔,单位为秒,如果设置为非零值,就会按照此时间间隔输出测试报告,默认值为零;

-w    设置套接字缓冲区为指定大小,对于TCP方式,此设置为TCP窗口大小,对于UDP方式,此设置为接受UDP数据包的缓冲区大小,限制可以接受数据包的最大值.

--logfile    参数可以将输出的测试结果储存至文件中.

-J  来输出JSON格式测试结果.
-R  反向传输,缺省iperf3使用上传模式:Client负责发送数据,Server负责接收;如果需要测试下载速度,则在Client侧使用-R参数即可.
-u	采用udp协议

6、实验过程

实验一共两个节点,IP为172.16.9.3/172.16.9.5。通过改变5号机的tc策略,将其带宽限制在某个值以内,然后用3号机测试上传速度是否符合预期。本次实验主要测试tc的入口流量限制能否有效。

先看一下两个节点之间原本的带宽。

#3号机
iperf3 -s -p 80
#5号机
ieprf3 -c 172.16.9.3 -p 80 -R #测试下载速度

image-20210618100011686

现在限制5号机入口流量

#按照前面方法将流量重定向到ifb0网卡
tc qdisc add dev ifb0 root tbf rate 100mbit latency 50ms burst 1600

截屏2021-06-18 上午10.08.18

可以看到带宽为80Mbit,虽然有误差,但已经达起到了限制入口流量的作用。经过调试发现这么大的误差跟burst参数值的设置有关,我索性增加10倍,改为16000。

让我们多测几次看一看误差有多少,发现只要burst值设置的够大,基本有4%-5%的误差,可以接受。

限制带宽 实际带宽 Burst 误差
10mbit 9.67mbit 16000 3.3%
100mbit 96mbit 16000 4%
200mbit 142mbit 1600 29%
350mbit 336mbit 160000 4%
350mbit 333mbit 16000 4.9%
500mbit 478mbit 16000 4.4%

7、拓展

7.1、百度网盘是怎么限速的?

百度网盘是在服务器端做了限速,控制发送数据的频率来实现,而pandownload破解限速的原理就是开启多线程。

7.2、QoS

服务质量(英语:Quality of Service,缩写QoS)是一个术语,在分组交换网络领域中指网络满足给定业务合约的几率;或在许多情况下,非正式地指分组在网络中两点间通过的几率。QoS是一种控制机制,它提供了针对不同用户或者不同数据流采用相应不同的优先级,或者是根据应用程序的要求,保证数据流的性能达到一定的水准。QoS的保证对于容量有限的网络来说是十分重要的,特别是对于流多媒体应用,例如VoIPIPTV等,因为这些应用常常需要固定的传输率,对延迟也比较敏感。

分组排序和带宽分配的QoS机制分别是排队和带宽管理。然而,在实施之前,必须使用分类工具区分流量。根据策略对流量进行分类使组织能够为其最重要的应用程序确保资源的一致性和足够的可用性。

流量可以按端口或 IP 进行粗略分类,也可以使用更复杂的方法(例如按应用程序或用户)进行分类。后面的参数允许更有意义的识别,并因此对数据进行分类

7.3、ifb虚拟网卡是什么?

Linux TC是一个控发不控收的框架,然而这是对于TC所置于的位置而言的,而不是TC本身的限制,事实上,你完全可以自己在ingress点上实现一个队列机制,说TC控发不控收只是因为Linux TC目前的实现没有实现ingress队列而已。

ifb驱动模拟一块虚拟网卡,它可以被看作是一个只有TC过滤功能的虚拟网卡,说它只有过滤功能,是因为它并不改变数据包的方向,即对于往外发的数据包被 重定向到ifb之后,经过ifb的TC过滤之后,依然是通过重定向之前的网卡发出去,对于一个网卡接收的数据包,被重定向到ifb之后,经过ifb的TC 过滤之后,依然被重定向之前的网卡继续进行接收处理,不管是从一块网卡发送数据包还是从一块网卡接收数据包,重定向到ifb之后,都要经过一个经由ifb 虚拟网卡的dev_queue_xmit操作。

image-20210629202959459

除 了ingress队列之外,在多个网卡之间共享一个根Qdisc是ifb实现的另一个初衷,可以从文件头的注释中看出来。如果你有10块网卡,想在这10 块网卡上实现相同的流控策略,你需要配置10遍吗?将相同的东西抽出来,实现一个ifb虚拟网卡,然后将这10块网卡的流量全部重定向到这个ifb虚拟网 卡上,此时只需要在这个虚拟网卡上配置一个Qdisc就可以了。

7.4、数据包传输过程中用到的各种队列

驱动程序队列(又名环形缓冲区)

在IP堆栈和NIC之间是驱动程序队列,该队列不包含数据包数据,他由指向称为套接字内核缓冲区SKB的其他数据结构的描述符组成,这些数据结构保存数据包数据,并在整个内核中使用。

驱动程序队列存在的原因是为了确保每当系统有数据要传输时,这些数据都可以立即传输给 NIC,也就是说它充当生产者-消费者中的缓存作用,使得数据的生产和消费异步起来,提高效率。

截屏2021-06-18 上午11.40.03

来自堆栈的大数据包

大多数NIC都有一个固定的最大传输单元MTU,对于以太网默认为1500字节。如果应用程序向TCP套接字写入2000字节,则IP堆栈需要创建两个IP数据包并通过驱动程序队列传输,更多的数据包意味着更多的网络协议头部开销。为了避免这种情况,Linux内核实施了很多优化:TCP分段卸载(TSO)、UDP分段卸载(UFO)和通用分段卸载(GSO)。

图 3 - 启用 TSO、UFO 或 GSO 时,将大数据包发送到设备。 这会大大增加驱动程序队列中的字节数。

当启用 TSO、UFO 或 GSO 时,可以将大数据包发送到 NIC。这会大大增加驱动程序队列中的字节数。得注意的是,Linux 还具有接收端优化,其操作类似于 TSO、UFO 和 GSO。这些优化的目的还在于减少每个数据包的开销。具体来说,通用接收卸载 ( GRO ) 允许 NIC 驱动程序将接收到的数据包组合成一个大数据包,然后将其传递到 IP 堆栈。在转发数据包时,GRO 允许重构原始数据包,这是保持 IP 数据包端到端性质所必需的。然而,有一个方面的影响,当大数据包在转发操作的传输侧被分解时,它会导致流的多个数据包同时排队。数据包的这种“微突发”会对流间延迟产生负面影响。

饥饿和延迟

尽管有其必要性和好处,但 IP 堆栈和硬件之间的队列引入了两个问题:饥饿和延迟。

如果NIC驱动程序唤醒以从队列中拉出数据包进行传输,并且队列为空,则硬件将错过传输机会,从而降低系统的吞吐量。这被称为饥饿。如果在一个繁忙的系统中,IP堆栈将获得更少的机会把数据包添加到缓冲区,那么硬件很可能在新的数据包到来之前消耗完缓冲区,因此需要一个大的缓冲区来减少饥饿的可能并确保高吞吐量,但它的缺点是引入大量延迟。

图 4 - 批量流数据包(蓝色)后面的交互数据包(黄色)

上图驱动程序队列中,几乎充满了高带宽,大容量的TCP段,排在最后的是来自 VoIP 或游戏流的数据包(黄色)。VoIP 或游戏等交互式应用程序通常以固定间隔发出小数据包,这些数据包对延迟敏感,而高带宽数据传输会产生更高的数据包速率和更大的数据包。这种较高的数据包速率可以填充交互数据包之间的缓冲区,从而导致交互数据包的传输延迟。

因此,为驱动程序队列选择合适的大小是一个“Goldilocks problem”。

字节队列限制BQL

字节队列限制 (BQL) 是最近的 Linux 内核 (> 3.3.0) 中的一项新功能,它试图自动解决驱动程序队列大小的问题。这是通过添加一个层来实现的,该层基于计算在当前系统条件下避免饥饿所需的最小缓冲区大小来启用和禁用对驱动程序队列的排队。回想之前,排队数据量越小,排队数据包所经历的最大延迟越低。

理解 BQL 不会改变驱动程序队列的实际大小是关键。而是 BQL 计算当前时间可以排队的数据量(以字节为单位)的限制。超过此限制的任何字节都必须由驱动程序队列上方的层保留或丢弃。

BQL 基于测试设备是否处于饥饿状态。如果它被饿死,那么 LIMIT 会增加,允许更多的数据排队,从而减少饿死的机会。如果设备在整个时间间隔内都处于忙碌状态,并且队列中仍有字节要传输,则队列大于当前条件下系统所需的队列,并且减少 LIMIT 以限制延迟,这个机制有点类似于TCP的拥塞控制机制。

BQL 通过将排队数据量限制为避免饥饿所需的最低限度来减少网络延迟。它还具有非常重要的副作用,将大多数数据包排队的点从驱动程序队列(一个简单的 FIFO)移动到队列规则 (QDisc) 层,该层能够实现更复杂的排队策略。

排队规则Qdisc

驱动程序队列是一个简单的先进先出 (FIFO) 队列。它平等地对待所有数据包,并且没有区分不同流的数据包的能力。这种设计使 NIC 驱动程序软件保持简单和快速。夹在 IP 堆栈和驱动程序队列之间的是排队规则 (QDisc) 层。该层实现了 Linux 内核的流量管理功能,包括流量分类、优先级和速率整形。

默认情况下,每个网络接口都分配了一个pfifo_fast QDisc,它基于 TOS 位实现了一个简单的三频段优先级方案。类和过滤器的概念不在介绍。

传输层和排队规则之间的缓冲

在查看前面的图时,您可能已经注意到在排队规则层之上没有数据包队列。这意味着网络数据包直接放入排队规则中,对于具有单个队列的 QDisc,会出现上图中针对驱动程序队列概述的相同问题。也就是说,单个高带宽或高数据包速率流会消耗队列中的所有空间,从而导致数据包丢失并给其他流增加显着的延迟。

从 Linux 3.6.0 (2012-09-30) 开始,Linux 内核有一个名为 TCP Small Queues 的新功能,旨在解决 TCP 的这个问题。

另一个部分解决方案是使用一个 QDisc,它有许多队列,理想情况下每个网络流一个。随机公平队列 ( SFQ ) 和具有受控延迟的公平队列 ( fq_codel ) QDisc 都很好地解决了这个问题,因为它们实际上每个网络流都有一个队列。

如何在Linux中操作队列大小

ethtool命令用于控制以太网设备驱动程序队列的大小。ethtool 还提供低级接口统计信息以及启用和禁用 IP 堆栈和驱动程序功能的能力。

截屏2021-06-18 下午3.45.28

而BQL算法是自调整的,因此不需要过多地弄乱它。如果非要修改,那么需要覆盖计算出的LIMIT值的上限,根据NIC的位置和名称,可以在/sys目录中找到BQL的状态和配置。在我的服务器上,eth0目录是/sys/devices/pci0000:00/0000:00:14.0/net/eth0/queues/tx-0/byte_queue_limits

这个目录下主要的两个文件:

什么是txqueuelen

image-20210618161418089

Linux 中传输队列的长度默认为 1,000 个数据包,这是一个很大的缓冲,尤其是在低带宽下。txqueuelen 仅用作某些排队规则的默认队列长度。

对于大多数排队规则,tc命令行上的limit参数会覆盖txqueuelen的默认值,也可以通过ip命令设置。

ip link set txqueuelen 500 dev eth0

7.5、微服务限流是限制带宽吗?

微服务限流是通过对并发/请求进行限速来保护系统,防止系统过载,限流的方式有:

所以,微服务的限流并不是限制带宽,而是限制一定时间区间内的并发数量,而常见的限流算法:漏桶算法、令牌桶算法等是针对这个的。Golang标准库中也自带了限流算法的实现golang.org/x/time/rate,该限流器是基于Token Bucket实现的。

参考链接:

How to limit network bandwidth on Linux

Linux Advanced Routing & Traffic Control HOWTO

Trickle: A Userland Bandwidth Shaper for Unix-like Systems

Queue in the Linux Network Stack

https://cloud.tencent.com/developer/article/1409664

图解linux网络包接收过程

多线程下载 一个大文件的速度更快的真正原因是什么

QoS实现之限速

linux网络工具iproute2的使用简介

Linux TC的ifb原理以及ingress流控

标签:qdisc,云边,整形,dev,tc,add,数据包,节点,eth0
来源: https://www.cnblogs.com/yrxing/p/14951947.html