混沌工程之ChaosMesh使用之模拟网络Duplicate包

x33g5p2x  于2021-11-03 转载在 其他  
字(2.8k)|赞(0)|评价(0)|浏览(302)

前言

今天我们来玩一下 ChaosMesh 模拟网络 duplicate 包的情况。同时也要看一下对应用产生的直接影响。

目标

模拟网络重复包。

配置

yaml 文件配置

[root@s5 ChaosMesh]# cat network-duplicate.yaml
apiVersion: chaos-mesh.org/v1alpha1
kind: NetworkChaos
metadata:
  name: network-duplicate
  namespace: chaos
spec:
  action: duplicate
  mode: one
  selector:
    labelSelectors:
      "k8s.kuboard.cn/name": "svc-7dmall"
  duplicate:
    duplicate: "40"
    correlation: "25"
  duration: "10s"
  scheduler:
    cron: '@every 15s'

界面配置:

执行

在命令行执行:

[root@s5 ChaosMesh]# kubectl apply -f network-duplicate.yaml
networkchaos.chaos-mesh.org/network-duplicate created

在界面上配置完成提交后即开始执行。

验证

  1. 进入被模拟的 POD,先查看 qdisc 上增加的规则,再执行 tcpdump 抓包。
- 查看qdisc上的规则
[root@svc-7dmall-664d59f75b-whtvc /]# tc qdisc ls dev eth0
qdisc netem 1: root refcnt 2 limit 1000 duplicate 40%
[root@svc-7dmall-664d59f75b-whtvc /]#

- 执行tcpdump抓包
[root@svc-7dmall-664d59f75b-whtvc /]# tcpdump -i eth0 -w networkduplicate.cap
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

^C195 packets captured
195 packets received by filter
0 packets dropped by kernel
[root@svc-7dmall-664d59f75b-whtvc /]#

从上面的结果看抓到了195个包。

  1. 进入pod所在机器或用其他工具把抓到的文件复制到本地。
[root@s7 ~]# docker cp 3d4ab3241d8a:/networkduplicate.cap ./
  1. 用 wireshark 打开查看。


确实出现了大量的重复包。

正常抓包结果是这样的:

  1. 用 Jmeter 开始一个线程访问应用,持续 60s,看下有什么区别。

有重复包的结果:

无重复包的结果:

从上面的结果来看,产生重复包的时候,对性能的影响还是不小的。

  • 应用直接的感受就是:响应时间长、TPS下降。
  • 用户直接的感受就是:慢但有响应或慢直到报错。
  1. 进入被模拟的POD,再次查看 qdisc 上的规则
[root@svc-7dmall-664d59f75b-whtvc /]# tc qdisc ls dev eth0
qdisc noqueue 0: root refcnt 2
[root@svc-7dmall-664d59f75b-whtvc /]#

恢复

在界面上停止案例

用命令行停止案例

[root@s5 ChaosMesh]# kubectl delete -f network-duplicate.yaml
networkchaos.chaos-mesh.org "network-duplicate" deleted
[root@s5 ChaosMesh]#

重传原理逻辑说明和 RTO 算过程

重复包产生的原因有很多,像应用故障、网络设备故障、服务宕机等等。

我们这里主要来说明一下重传的逻辑。

决定报文重传机制的是重传计时器(retransmission timer),它的功能是维护重传超时值(retransmission timeout)。

发出报文后,重传计时器启动,收到ACK后计时器停止。如果未收到ACK,发送方认为报文丢失并重传,同时RTO加倍;如果2倍RTO之后还没收到ACK,则再次重传。

在 Linux 中重传次数默认最大为 15 次,由两个参数控制:

net.ipv4.tcp_retries1 = 3
net.ipv4.tcp_retries2 = 15
  • tcp_retries1 = 3 是指重传了3次后,如果还没收到ACK,则后续重传中会先更新路由。
  • tcp_retries2 = 15 是指最多重传15次,15次都传不成功,那就放弃了。

正常情况下,你看到这里就可以结束了。但也不排除有些人想看明白 RTO 的计算逻辑。那就接着看。

也许你会问RTO是多长时间?在Linux源码中,有这样的定义(源码路径include/net/tcp.h,在我这个3.10版本的内核代码中是134、135行):

#define TCP_RTO_MAX ((unsigned)(120*HZ))
#define TCP_RTO_MIN ((unsigned)(HZ/5))

看到这里,知道 RTO 有最大最小值,分别是 HZ/5 和 120/*HZ 。但是又有疑问,那HZ是什么值?

你可以在系统中执行如下命令获得。

[root@s5 ~]# cat /boot/config-`uname -r` | grep '^CONFIG_HZ='
CONFIG_HZ=1000

在我的系统中值是 1000,也就是说 RTO 的最小值是200、最大值是 120000(单位是毫秒)。

但是这个 RTO 又是怎么算来的呢?这个值由 __tcp_set_rto(3.10源码路径 include/net/tcp.h 中 606-609 行)函数算出(其中 srtt 的计算逻辑,我就不展开了,越说越多越容易乱,有兴趣的可以自己去查查资料)。

static inline u32 __tcp_set_rto(const struct tcp_sock *tp)
{
  return (tp->srtt >> 3) + tp->rttvar;
}

这个函数算出来的值不可以小于TCP_RTO_MIN的值。

而 RTO 的最大值又由谁来确定呢?那就是 ·tcp_bound_rto·(3.10 源码路径 include/net/tcp.h 中 600-604 行)了。

static inline void tcp_bound_rto(const struct sock *sk)
{
  if (inet_csk(sk)->icsk_rto > TCP_RTO_MAX)
    inet_csk(sk)->icsk_rto = TCP_RTO_MAX;
}

以上就是 RTO 的计算逻辑。

留下思考的空间

  1. 怎么分析网络包重传的原因?
  2. 有没有设置最小RTO的函数?

相关文章