前言

互联网产品的测试常常要覆盖在不同网络下的表现,例如丢包,带宽受限,时延及抖动等网络较差的情况,为了测试场景的网络情况可定义及复现,就需要有个工具对弱网进行模拟。业界一些通用的弱网模拟工具,如NEWT,fiddler,charles,atc,tc和packetstorm等软硬件弱网模拟工具。相较于硬件模拟器昂贵的价格和其他软件模拟器部署难度大,TC成本低,部署难度较低且容易和自动化结合实现自动化测试,此外TC适用任何平台的设备(包括PC、移动端等)。本文着重介绍TC的原理及应用。

一、TC及Netem简介

讲到tc工具不能不提iproute2工具集,iproute2工具集包括了一系列网络相关的工具,像大名鼎鼎的ip命令行工具,本文主要通过iptables创建一条linux系统的两块网卡的桥接。

netem 是 Linux 在2.6 及以上内核版本提供的一个网络模拟功能模块。该功能模块可以用来在性能良好的局域网中,模拟出复杂的互联网传输性能,如时延,丢包,抖动等场景。

2.6 (或以上) 版本内核的很多发行版 Linux 都开启了该内核功能,比如Fedora、Ubuntu、Redhat、OpenSuse、CentOS、Debian等,本文以Ubuntu18为例。

tc 是 Linux 系统中的一个工具,全名为traffic control(流量控制)。tc 可以用来控制 netem 的工作模式,每一个物理网卡都会和一个qdisc关联,然后通过netem添加不同设置参数以实现对网络的控制。

二、Linux中的队列规则

Linux操作系统中的流量控制器TC(Traffic Control)用于Linux内核的流量控制,它利用队列规定建立处理数据包的队列,并定义队列中的数据包被发送的方式, 从而实现对流量的控制。TC使用的队列规则分为两类,一类是无类别队列规则, 另一类是分类队列规则。 无类别队列规则相对简单,而分类队列规则则引出了分类和过滤器等概念,使其流量控制功能增强,本文中TC主要使用分类队列规则。

1、无类别队列规则是对进入网络设备(网卡) 的数据流不加区分统一对待的队列规则。

这类队列规则形成的队列可以对整个网络设备(网卡)的流量进行整形,但不能细分各种情况。

常用的无类别队列规则主要有pfifo _fast (先进先出) 、TBF ( 令牌桶过滤器) 、SFQ(随机公平队列) 、RED (随机早期检测)等等。这类队列规则使用的整形手段主要是排序、限速和丢包。

1.1  pfifo和pfifo_fast

FIFO是linux网络接口的默认qdisc规则,没有整形和重排序的功能,仅对收到的包按照先入先出的顺序排出。pfifo_fast与pfifo类似,只是针对收到的流排出三个优先级。

1.2  SFQ

此种队列企图用一套公平的队列算法(哈希函数)来实现收包随机分配到不同FIFO序列,但是有些讨厌的软件上就无法保证折中公平性(分布在多个FIFO序列上)。

1.3  TBF

如名字所示,令牌桶过滤器基于令牌和桶,只有当令牌足够时,数据包才会从网口发出,否则,数据包将会被延迟发送,以此来实现流量限速。

2、分类队列规则是对进入网络设备的数据包根据不同的需求以分类的方式区分对待的队列规则。数据包进入一个分类的队列后, 它就需要被送到某一个类中, 也就是说需要对数据包做分类处理。对数据包进行分类的工具是过滤器,队列规则会根据过滤器的分类结果把数据包送入相应的类进行排队。每个子类都可以使用它们的过滤器进一步分类,直到不需要进一步分类为止。如下图所示,为本文中TC用到的HTB,图中详细展示了qdisc和类以及子类的关系:

三、TC的实现

TC主要包括三个基本要素:队列规则(qdisc,queueing discipline)、类(class)和过滤器(filter)

l  qdisc:队列规则,TC的核心,用于确定数据包的发送方式。如下命令实现了指定的eth0网卡上所有的包固定加了200ms延时

# tc qdisc add dev eth0 root netem delay 200ms

l  class和filter:类和过滤器。类即是数据流量的类别,各种应用和终端的流量通过filter进行分类,进入到队列规则里排队进行发送。如下命令行所示即通过class和filter实现了对指定ip的限速,其他弱网类似:

# tc class add dev eth0 parent 1:1 classid 1:2 htb rate 500kbit

# tc filter add dev eth0 protocol ip parent 1:0 prio 3 u32 match 192.168.2.10 flowid 1:3

其他常用到的弱网场景:

l  延迟波动,如下命令表示延迟为时延150ms-250ms波动(由于网卡上发出的包延迟不同,所以会有一定程度的乱序发生):

# tc qdisc add dev eth0 root netem delay 200ms 50ms

l  乱序,如下代表随机丢包30%

# tc qdisc add dev eth0 root netem delay 50ms reorder 25%

l  随机丢包,如下代表随机丢包30%

# tc qdisc add dev eth0 root netem loss 30%

四、TC的自动化

通过把上述TC命令封装成python或其他语言的命令,匹配ip地址来对指定的设备设置想要的弱网环境,可以实现通过一条命令即可设置想要的弱网条件。结合一些自动化测试的框架和原有的测试场景的覆盖,实现测试场景的扩展,扩大测试的范围,实现TC对不同弱网场景的自动化测试的支持,提升测试的深度和广度。如下命令即为本文封装,实现对192.168.2.10设备的上行添加弱网受限1000k,delay 200ms,jitter 50ms,丢包10%。

五、扩展

如下一段文字摘自《Traffic Control HOWTO》:

Common traffic control solutions

1. Limit total bandwidth to a known rate; TBF, HTB with child class(es).

2. Limit the bandwidth of a particular user, service or client; HTB classes and classifying with a filter. traffic.

3. Maximize TCP throughput on an asymmetric link; prioritize transmission of ACK packets, wondershaper.

4. Reserve bandwidth for a particular application or user; HTB with children classes and classifying.

5. Prefer latency sensitive traffic; PRIO inside an HTB class.

6. Managed oversubscribed bandwidth; HTB with borrowing.

7. Allow equitable distribution of unreserved bandwidth; HTB with borrowing.

8. Ensure that a particular type of traffic is dropped; policer attached to a filter with a drop action.

由上文可见,特定网络场景的弱网设置仅仅对应了第一条,对于一些个性化的网络服务设置、带宽借用以及优先级等更灵活多样的应用,有待大家挖掘。


想要阅读更多技术干货、行业洞察,欢迎关注网易云信博客

了解网易云信,来自网易核心架构的通信与视频云服务。

网易云信(NeteaseYunXin)是集网易18年IM以及音视频技术打造的PaaS服务产品,来自网易核心技术架构的通信与视频云服务,稳定易用且功能全面,致力于提供全球领先的技术能力和场景化解决方案。开发者通过集成客户端SDK和云端OPEN API,即可快速实现包含IM、音视频通话、直播、点播、互动白板、短信等功能。

TC基础与自动化的更多相关文章

  1. TC基础使用指南(基于xbeta的TC配置文件)

    所有常用目录都可以通过ctrl+d加一个或几个字母的超快捷方式直接跳转到位. 按下BackSpace键,就可以进入到上一级目录 Ctrl+q 在右侧打开左侧选定文件,再按一次Ctrl+q退出 按 Ct ...

  2. vue基础 (三) 自动化工具(Vue CIL)

    一.自动化工具(Vue CIL) 安装过程 1. 先安装nvm 参考:https://www.jianshu.com/p/d0e0935b150a https://www.cnblogs.com/tj ...

  3. 云时代基础设置自动化管理利器: Chef

    云时代的到来势不可挡.尤其作为程序员,我们每天或多或少的直接或间接的使用者各种云服务.云平台有很多种,如云软件(SaaS, Software as a service).云平台(PaaS, Platf ...

  4. 作为比湖南还火的python网红,零基础要如何系统的开始学习呢?

    Python(发音:英[?pa?θ?n],美[?pa?θɑ:n]),是一种面向对象.直译式电脑编程语言,也是一种功能强大的通用型语言,已经具有近二十年的发展历史,成熟且稳定.它包含了一组完善而且容易理 ...

  5. 自动化预备知识上&&下--Android自动化测试学习历程

    章节:自动化基础篇——自动化预备知识上&&下 主要讲解内容及笔记: 一.需要具备的能力: 测试一年,编程一年,熟悉并掌握业界自动化测试工具(monkey--压力测试.monkeyrun ...

  6. 【目录】Python自动化运维

    目录:Python自动化运维笔记 Python自动化运维 - day2 - 数据类型 Python自动化运维 - day3 - 函数part1 Python自动化运维 - day4 - 函数Part2 ...

  7. springcloud微服务实战--笔记--1、基础知识

    微服务的问题: 分布式事务和数据一致性. 由于分布式事务本身第实现难度就非常大,所以在微服务架构中,我们更强调在各服务之间进行无事务第调用,而对于数据一致性,只要求数据在最后第处理状态是一致第即可:若 ...

  8. 使用 Gitlab CI/CD 实现自动化发布站点到 IIS

    说明 这里先介绍下两个东西 CI/CD.GitLab Runner,当然在此之前你需要对 git 有所了解,关于 git 这里不做说明,可以自行百度. 首先介绍 CI/CD :随着我们开发方式的转变, ...

  9. 零基础教程!一文教你使用Rancher 2.3和Terraform运行Windows容器

    本文来自Rancher Labs 介 绍 在Kubernetes 1.14版本中已经GA了对Windows的支持.这一结果凝结了一群优秀的工程师的努力,他们来自微软.Pivotal.VMware.红帽 ...

随机推荐

  1. 新年上新!极光认证 Web SDK 首版上线

    新年伊始,极光开发者服务也抢先为各位开发者朋友带来了"新年大礼包",几款明星产品都悉数有不少更新: 极光认证 Web SDK 版本上线 相信不少小伙伴早已熟知极光认证这款产品,3秒 ...

  2. SQL Server数据库、表、数据类型基本概念

    一.SQL Server的数据存储结构 SQL Server是一个数据库管理系统,需要以有效方式存储高容量数据.要更好地理解SQL Server处理数据的方式,就需要了解数据的存储结构. 1.文件类型 ...

  3. linux--工具进阶

    linux学习 看完了基础篇,下面来看进阶篇 我好想哭看这的时候,好多只是听说过,但完全没有试过,感觉自己懂得有点少,就是缺乏一些知识储备,也就是必须知道了某些或学过了某些知识才适合来看这一部分,看得 ...

  4. MVC5+EF6入门完整教程7:排序过滤分页

    https://www.cnblogs.com/miro/p/4134241.html 前置准备 – 应用之前样式,增加测试数据 界面样式修改前: 下面对Views --> Account -- ...

  5. Qt的qDebug()改写为cout

    经常用c++,qDebug()用的不习惯,将其改为cout,并且为了方便调试,还添加了文件名及行号. 代码如下: // __FILE__文件名,__LINE__行号,如果想看时间还可以添加__TIME ...

  6. H5_0025:css3自适应布局单位vw,vh

    视口单位(Viewport units) 什么是视口? 在桌面端,视口指的是在桌面端,指的是浏览器的可视区域:而在移动端,它涉及3个视口:Layout Viewport(布局视口),Visual Vi ...

  7. 取Cookie值

    string url_Login_Group = "http://ui.ptlogin2.qq.com/cgi-bin/login?appid=549000912&daid=5&am ...

  8. Java设计模式(三)简单工厂模式

    定义与类型 定义:由一个工厂对象决定创建出哪一种产品类的实例 类型:创建型,但不属于GOF23种设计模式 适用场景 工厂类负责创建的对象比较少 客户端(应用层)只知道传入工厂类的参数,对于如何创建对象 ...

  9. 嵊州D5T2 折纸 folding

    折纸 folding [问题描述] 在非常紧张的 NOIP 考试中,有人喜欢啃指甲,有人喜欢转铅笔,有人喜欢撕 纸条,……而小 x 喜欢迷折纸. 现有一个 W * H 的矩形纸张,监考老师想知道,小 ...

  10. 剑指offer-基础练习-增删节点-链表

    /* 链表基本操作: 插入节点和删除节点 */ /* 思路: 使用指向链表的头指针,这样在新插入节点后,头指针不会改变 */ struct ListNode{ int value; ListNode* ...