Load很高,CPU使用率很低的诡异情况

Load很高,CPU使用率很低的诡异情况

第一次碰到这种Case:物理机的Load很高,CPU使用率很低

先看CPU、Load情况

如图一:0?wx_fmt=png0?wx_fmt=png

这个现象不太合乎常规,也许是在等磁盘IO、也许在等网络返回会导致CPU利用率很低而Load很高

贴个vmstat 说明文档(图片来源于网络N年了,找不到出处)0?wx_fmt=png

检查磁盘状态,很正常(vmstat 第二列也一直为0)

0?wx_fmt=png

再看Load是在5号下午15:50突然飙起来的:

0?wx_fmt=png

同一时间段的网络流量、TCP连接相关数据很平稳:

0?wx_fmt=png

所以分析到此,可以得出:Load高跟磁盘、网络、压力都没啥关系

物理机上是跑的Docker,分析了一下CPUSet情况:

0?wx_fmt=png

发现基本上所有容器都绑定在CPU1上(感谢 @辺客 发现这个问题)

进而检查top每个核的状态,果然CPU1 的idle一直为0

0?wx_fmt=png

看到这里大致明白了,虽然CPU整体很闲但是因为很多进程都绑定在CPU1上,导致CPU1上排队很长,看前面tsar的--load负载截图的 等待运行进程排队长度(runq)确实也很长。

物理机有32个核,如果100个任务同时进来,Load大概是3,这是正常的。如果这100个任务都跑在CPU1上,Load还是3(因为Load是所有核的平均值)。但是如果有源源不断的100个任务进来,前面100个还没完后面又来了100个,这个时候CPU1前面队列很长,其它31个核没事做,这个时候整体Load就是6了,时间一长很快Load就能到几百。

这是典型的瓶颈导致积压进而高Load。

为什么会出现这种情况

检查Docker系统日志,发现同一时间点所有物理机同时批量执行docker update 把几百个容器都绑定到CPU1上,导致这个核忙死了,其它核闲得要死(所以看到整体CPU不忙,最忙的那个核被平均掩盖掉了),但是Load高(CPU1上排队太长,即使平均到32个核,这个队列还是长,这就是瓶颈啊)。

如下Docker日志,Load飙升的那个时间点有人批量调docker update 把所有容器都绑定到CPU1上:0?wx_fmt=png

检查Docker集群Swarm的日志,发现Swarm没有发起这样的update操作,似乎是每个Docker Daemon自己的行为,谁触发了这个CPU的绑定过程的原因还没找到,求指点。

手动执行docker update, 把容器打散到不同的cpu核上,恢复正常:

0?wx_fmt=png

关于这个Case的总结

  • 技术拓展商业边界,同样技能、熟练能力能拓展解决问题的能力。 开始我注意到了Swarm集群显示的CPU绑定过多,同时也发现有些容器绑定在CPU1上。所以我尝试通过API: GET /containers/json 拿到了所有容器的参数,然后搜索里面的CPUSet,结果这个API返回来的参数不包含CPUSet,那我只能挨个 GET /containers/id/json, 要写个循环,偷懒没写,所以没发现这个问题。

  • 这种多个进程绑定到同一个核然后导致Load过高的情况确实很少见,也算是个教训

  • 自己观察top 单核的时候不够仔细,只是看到CPU1 的US 60%,没留意idle,同时以为这个60%就是偶尔一个进程在跑,耐心不够(主要也是没意识到这种极端情况,疏忽了)

关于Load高的总结

  • Load高一般对应着CPU高,就是CPU负载过大,检查CPU具体执行任务是否合理

  • 如果Load高,CPU使用率不高的检查一下IO、网络等是否比较慢

  • 如果是虚拟机,检查是否物理机超卖或者物理机其它ECS抢占CPU、IO导致的

  • 如果两台一样的机器一样的流量,Load有一台偏高的话检查硬件信息,比如CPU被降频了,QPI,内存效率等等,这个时候可能需要硬件相关同学加入一起排查了,当然牛逼的工程师能把这块也Cover了排查效率自然更高

此文来自阿里巴巴同事:蛰剑


  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据网友提供代码,逆向画出来的。包含CPU使用率、内存使用率、虚拟内存使用率、内存总量等。数据比较符合靠谱。 ***************************************************************************** using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Diagnostics; using System.Threading; using System.Runtime.InteropServices; using System.Management; namespace Cpu_Test { public partial class Form1 : Form { public Form1() { InitializeComponent(); } Process[] MyProcesses; Thread td; private void myUser() { ManagementObjectSearcher searcher = new ManagementObjectSearcher("select * from Win32_Processor"); foreach (ManagementObject myobject in searcher.Get()) { tssluse.Text = myobject["LoadPercentage"].ToString() + " %"; lblCPU.Text = myobject["LoadPercentage"].ToString() + " %"; mheight = Convert.ToInt32(myobject["LoadPercentage"].ToString()); if (mheight == 100) panel3.Height = 100; CreateImage(); Memory(); } } private void Memory() { Microsoft.VisualBasic.Devices.Computer myInfo = new Microsoft.VisualBasic.Devices.Computer(); //获取物理内存总量 pbMemorySum.Maximum = Convert.ToInt32(myInfo.Info.TotalPhysicalMemory / 1024 / 1024); pbMemorySum.Value = Convert.ToInt32(myInfo.Info.TotalPhysicalMemory / 1024 / 1024); lblSum.Text = (myInfo.Info.TotalPhysicalMemory / 1024).ToString(); //获取可用物理内存总量 pbMemoryUse.Maximum = Convert.ToInt32(myInfo.Info.TotalPhysicalMemory / 1024 / 1024); pbMemoryUse.Value = Convert.ToInt32(myInfo.Info.AvailablePhysicalMemory / 1024 / 1024); lblMuse.Text = (myInfo.Info.AvailablePhysicalMemory / 1024).ToString(); //获取虚拟内存总量 pbVmemorysum.Maximum = Convert.ToInt32(myInfo.Info.TotalVirtualMemory / 1024 / 1024); pbVmemorysum.Value = Convert.ToInt32(myInfo.Info.TotalVirtualMemory / 1024 / 1024); lblVinfo.Text = (myInfo.Info.TotalVirtualMemory / 1024).ToString(); //获取可用虚拟内存总量 pbVmemoryuse.Maximum = Convert.ToInt32(myInfo.Info.TotalVirtualMemory / 1024 / 1024); pbVmemoryuse.Value = Convert.ToInt32(myInfo.Info.AvailableVirtualMemory / 1024 / 1024); lblVuse.Text = (myInfo.Info.AvailableVirtualMemory / 1024).ToString(); } private void Form1_Load(object sender, EventArgs e) { CheckForIllegalCrossThreadCalls = false; MyProcesses = Process.GetProcesses(); //tsslNum.Text = "进程数: "; tsslNum.Text = "进程数: "+ MyProcesses.Length.ToString()+ " CPU使用: "; myUser(); } private void timer1_Tick(object sender, EventArgs e) { Control.CheckForIllegalCrossThreadCalls = false; MyProcesses = Process.GetProcesses(); tsslNum.Text = "进程数: " + MyProcesses.Length.ToString() + " | CPU使用:"; td = new Thread(new ThreadStart(myUser)); td.Start(); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { if (td != null) { td.Abort(); } } int mheight = 0; private void CreateImage() { int i = panel3.Height / 100; Bitmap image = new Bitmap(panel3.Width, panel3.Height); Graphics g = Graphics.FromImage(image); g.Clear(Color.Green); SolidBrush mybrush = new SolidBrush(Color.Lime); g.FillRectangle(mybrush, 0, panel3.Height - mheight * i, 26, mheight * i); panel3.BackgroundImage = image; } } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值