单线程为什么cpu慢_Kubernetes迁移踩坑:CPU节流

b3a4f784c21a0f77ab024af0dce8badc.png

前段时间在负责将公司一个非常重要的服务(代号:S)从专供服务器(Snowflake Server)迁移到Kubernetes的集群上。不料在压力测试的时候,我们发现S的请求响应速度明显比专供服务器的服务慢,有时候可能会夸张到慢1秒或者2秒。

由于我们请求的每一跳(hop)都有监控,所以很快排除了应用本身以外的所有问题。但问题又来了,代码完全相同,集成测试也没有发现任何错误,就连CPU使用率,JVM数据,磁盘性能都没有任何区别,那到底是什么拖慢了请求呢?然而在一次非常偶然的情况下,我们尝试将应用的CPU配额在K8s里从4核调到8核,结果奇迹发生了,请求相应速度瞬间降低并能与专供服务器持平!(专供服务器有32核,除了S以外还运行着几个其他应用。我们最初分配4核给S的原因是观察到CPU使用图表显示历史最高为3.5左右)于是我们开始深入反思到底CPU出了什么问题。

CPU节流与响应时间

结论:CPU分配不足会产生CPU节流,导致请求响应变慢

我们在Kubernetes中使用的是cgroups来管理资源分配与隔离,调度程序则选取了完全公平调度(CFS)中的强制上限(Ceiling Enforcement)。我们以单线程的情况举例:假使cpu.cfs_period_us设定为100毫秒(这是全局统一的设置),cpu.cfs_quota_us设定为20毫秒(这是每个应用在K8s自己设定的,当前的配置等同于给Pod分配200millicore)。这意味着CFS会每隔100毫秒会重新分配应用的CPU使用权,而在每个100毫秒内,应用可以占用CPU20毫秒。在专供服务器的情况下,由于我们没有使用cgroups,应用可以用尽空闲的CPU。但是假如一个请求在专供服务器需要花100毫秒,在刚刚设定的K8s环境下则会发生如下现象:

运行20毫秒 -> 挂起并等待80毫秒(节流) -> 运行20毫秒 -> 挂起并等待80毫秒-> 运行20毫秒 -> 挂起并等待80毫秒-> 运行20毫秒 -> 挂起并等待80毫秒-> 运行20毫秒 -> 请求完成并返回

原本只需100毫秒的请求,现在却花费了420毫秒,整整慢了4倍多!

于是我们加入了新的监控指标:cpu.stat.nr_throttled / cpu.stat.nr_periods (CPU节流率,越高越不好)。对比请求响应时间的数据,完全吻合。

在补充一句在多核多线程情况下,假设cpu.cfs_quota_us是200毫秒,如果有10个线程需要运行,每个线程只能分到20毫秒运行CPU时间。

CPU节流与CPU使用率

但问题又来了,明明CPU节流率已经快到百分之百了,为什么CPU使用率的不是100%呢,甚至在我们的另一些测试中低于20%的情况都有出现。

对于这个问题我们还没有定论,目前的猜测是在多核多线程的情况下,很多线程占着CPU配额却因为IO等原因挂起了,导致配额耗尽但却不计入CPU使用时间(IO不算CPU使用时间),所以看起来CPU使用率很低。

最后想总结一下这次问题排查的心得:

  • CPU使用率低并不代表应用性能没有受CPU节流的影响
  • 目前认为使用CPU节流率来判断CPU使用状况更合适
  • Kubernetes不是黑魔法,迁移一定会有坑,有效的数据监控能够极大得帮助发现问题原因
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值