与容器相关的那些事——Flink性能优化案例

Updated on with 0 views and 0 comments

在迁移FTX实时消费程序到Flink时,遇到消费性能问题,QPS一直上不去,如下图所示:

d5294075b8634dd296ecd40a818f83e3.png

说明:

  • Flink部署在k8s上
  • 预期的QPS至少要达到350k/s

接下来借着这个案例,我们从性能分析的四个方面(CPU、内存、Disk IO和网络)来说说跟容器有关的那些事。

1 容器是什么

容器 = Namespace + Cgroups

Namespace帮助容器来实现各种计算资源的隔离,Cgroups主要限制的是容器能够使用的某种资源量。

Namespace的类型如下图所示:

609e840dc8804cb2aa95a70af6ca49bd.png

几种常见的Cgroup子系统:

  • CPU⼦系统,⽤来限制⼀个控制组(⼀组进程,你可以理解为⼀个容器⾥所有的进程)可使⽤的最⼤ CPU
  • memory⼦系统,⽤来限制⼀个控制组最⼤的内存使⽤量
  • pids⼦系统,⽤来限制⼀个控制组⾥最多可以运⾏多少个进程
  • cpuset⼦系统, 这个⼦系统来限制⼀个控制组⾥的进程可以在哪⼏个物理 CPU 上运⾏

2 CPU

在宿主机上执行 top 命令:

5c154bd55101406ca79841ffcffd64a4.png

请注意上面圈出来的地方跟软中断相关!!!

在容器里执行 top 命令:

2e895e26d10547cab2b0450aab126628.png

说明:top 命令是通过读取 /proc/stat 文件来得到CPU使用了多少ticks,这里的ticks是指操作系统里的一个时间单位,具体分类见下图:

5c60d7d6b2404b8d83bdf31a11d26d89.png

单个容器CPU使用率计算公式如下:

单个容器CPU使用率 = (进程的ticks / 单个CPU总ticks) * 100.0
       = ((utime_2 – utime_1) + (stime_2 – stime_1)) * 100.0 / (HZ * et * 1 )

说明:

  • HZ:表示1秒钟里ticks次数,这里值是100
  • et:utime_1和utime_2这两个值的时间间隔
  • 1:表示一个CPU

我们可以从 cpuacct.stat 文件中获取控制组里所有进程用户态和内核态的ticks,如下图所示:

486201f2f18b4705beffbd0100fa5923.png

代入公式中,整个容器的CPU使用率=((77606 - 77564) + (15676 - 15666)) * 100.0 / (100+1+1) = 50

上面发现软中断有异常,接下来具体看看软中断的情况,执行 watch -d cat /proc/softirqs,如下图所示:

065d5e449b6e4618a886c1710609f434.png

说明:

  • CPU11主要的软中断类型是 NET_RX,结合我们的业务场景应该对应的是Kafka消费
  • 每个CPU都有一个对应的 ksoftirqd 进程,请看上面top命令中圈出来 [ksoftirqd/11]

3 内存

free命令和top命令都不能直接在容器中执行,即便是能够执行,也不能反映容器的情况。

f6ee365439d44ff49678913be96c292d.png

如上图所示,可以查看容器中memory Cgroup下面的 memory.stat 文件,这里面有控制组内存信息。

一般我们会选择禁止透明大页,避免发生Compaction,如下图所示:

2f9fd108b10c490b9e95c66f17dbfd42.png

禁止透明大页的命令如下:

# 临时生效
echo never > /sys/kernel/mm/transparent_hugepage/defrag
echo never > /sys/kernel/mm/transparent_hugepage/enabled

# 保证重启生效
echo 'echo never > /sys/kernel/mm/transparent_hugepage/defrag' >> /etc/rc.local
echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.local

4 IO

使用 iostat 命令查看宿主机IO情况:

e188f49fec9444fe855e1f09a8392e67.png

Linux两种文件IO模式:Direct IO 和 Buffered IO

5b219684addb43c3ac86a890eb5b9cf0.png

注意:

  • Buffered IO会使用page cache
  • 受内存限制时,要申请新的page cache,就需要释放老的page cache,会造成IO波动
  • Cgroup有v1和v2两个版本,v1版本中的blkio Cgroup只能限制Direct IO !!!

5 网络

使用 sar 命令查看宿主机网络情况:

3181a216407e415194c9682150253277.png

一般地,网络接口有两类:一类是veth,另一类是macvlan/ipvlan。其中,veth用的比较多。

7523a263901a4674ab18137ab794a0ea.png

说明:

  • Docker默认使用的是 bridge + nat 转发方式
  • 虽然veth没有硬中断处理,但是软中断的处理和真实网络接口是一样的,因此会增加网络延迟

在生产环境使用 tcpdump 抓包的话,可能瞬间就会有几个GB的数据,这种情况下比较推荐的是使用 netstat 命令来查看协议栈中的丢包和重传情况。

在宿主机上使用 lsns 命令查看系统里已有的 Network Namespace:

fa16b2f0982e4e8b95ab3c223a3c7fd6.png

使用 nsenter 命令进入指定的Namespace:

730bea5c3480400ca059e4e9d035abd5.png

6 perf 和 火焰图

使用perf采样:

a49075c6528c4c6987c38e3654a07926.png

下载FlameGraph:

git clone https://github.com/brendangregg/FlameGraph

将perf采样数据生成火焰图:

2f84843151624b099f197c7d6ddfde55.png

打开svg文件,找出影响性能的“平顶”:

7af1a19abe1842d1b6aa3014e128bca2.png

说明:

  • 火焰图中的调用关系是从下往上
  • 比较明显的“平顶”是调用librocksdb-linux64.so,这个跟Flink的state存储有关
  • 优化未完待续。。。

标题:与容器相关的那些事——Flink性能优化案例
作者:yanghao
地址:http://solo.fancydigital.com.cn/articles/2022/02/28/1646062982278.html