浅谈 Linux 高负载的系统化分析

简介: 浅谈 Linux 高负载的系统化分析,阿里云系统组工程师杨勇通过对线上各种问题的系统化分析。

讲解 Linux Load 高如何排查的话题属于老生常谈了,但多数文章只是聚焦了几个点,缺少整体排查思路的介绍。所谓 “授人以鱼不如授人以渔”。本文试图建立一个方法和套路,来帮助读者对 Load 高问题排查有一个更全面的认识。

从消除误解开始

没有基线的 Load,是不靠谱的 Load

从接触 Unix/Linux 系统管理的第一天起,很多人就开始接触 System Load Average 这个监控指标了,然而,并非所有人都知道这个指标的真正含义。一般说来,经常能听到以下误解:

  • Load 高是 CPU 负载高……
    传统 Unix 于 Linux 设计不同。Unix 系统,Load 高就是可运行进程多引发的,但对 Linux 来说不是。对 Linux 来说 Load 高可能有两种情况:
  • 系统中处于 R 状态的进程数增加引发的
  • 系统中处于 D 状态的进程数增加引发的
  • Loadavg 数值大于某个值就一定有问题……
    Loadavg 的数值是相对值,受到 CPU 和 IO 设备多少的影响,甚至会受到某些软件定义的虚拟资源的影响。Load 高的判断需要基于某个历史基线 (Baseline),不能无原则的跨系统去比较 Load。
  • Load 高系统一定很忙…..
    Load 高系统可以很忙,例如 CPU 负载高,CPU 很忙。但 Load 高,系统不都很忙,如 IO 负载高,磁盘可以很忙,但 CPU 可以比较空闲,如 iowait 高。这里要注意,iowait 本质上是一种特殊的 CPU 空闲状态。另一种 Load 高,可能 CPU 和磁盘外设都很空闲,可能支持锁竞争引起的,这时候 CPU 时间里,iowait 不高,但 idle 高。

Brendan Gregg 在最近的博客 [Linux Load Averages: Solving the Mystery] (http://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html) 中,讨论了 Unix 和 Linux Load Average 的差异,并且回朔到 24 年前 Linux 社区的讨论,并找到了当时为什么 Linux 要修改 Unix Load Average 的定义。文章认为,正是由于 Linux 引入的 D 状态线程的计算方式,从而导致 Load 高的原因变得含混起来。因为系统中引发 D 状态切换的原因实在是太多了,绝非 IO 负载,锁竞争这么简单!正是由于这种含混,Load 的数值更加难以跨系统,跨应用类型去比较。所有 Load 高低的依据,全都应该基于历史的基线。本微信公众号也曾写过一篇相关文章,可以参见Linux Load Average那些事儿。

5F2A9870-D53D-4d13-9A1F-FBBD6618AACC.png

如何排查 Load 高的问题

如前所述,由于在 Linux 操作系统里,Load 是一个定义及其含混的指标,排查 loadavg 高就是一个很复杂的过程。其基本思路就是,根据引起 Load 变化的根源是 R 状态任务增多,还是 D 状态任务增多,来进入到不同的流程。

这里给出了 Load 增高的排查的一般套路,仅供参考:

3352EB78-4756-4cec-ACFA-22269523B310.png

在 Linux 系统里,读取 /proc/stat 文件,即可获取系统中 R 状态的进程数;但 D 状态的任务数恐怕最直接的方式还是使用 ps 命令比较方便。而 /proc/stat 文件里 procs_blocked 则给出的是处于等待磁盘 IO 的进程数:

7719CAEA-5C84-4ba7-8600-4528E45D0E38.png

通过简单区分 R 状态任务增多,还是 D 状态任务增多,我们就可以进入到不同的排查流程里。下面,我们就这个大图的排查思路,做一个简单的梳理。

R 状态任务增多

即通常所说的 CPU 负载高。此类问题的排查定位主要思路是系统,容器,进程的运行时间分析上,找到在 CPU 上的热点路径,或者分析 CPU 的运行时间主要是在哪段代码上。

CPU user 和 sys 时间的分布通常能帮助人们快速定位与用户态进程有关,还是与内核有关。另外,CPU 的 run queue 长度和调度等待时间,非主动的上下文切换 (nonvoluntary context switch) 次数都能帮助大致理解问题的场景。

因此,如果要将问题的场景关联到相关的代码,通常需要使用 perf,systemtap, ftrace 这种动态的跟踪工具。

关联到代码路径后,接下来的代码时间分析过程中,代码中的一些无效的运行时间也是分析中首要关注的,例如用户态和内核态中的自旋锁 (Spin Lock)。

当然,如果 CPU 上运行的都是有非常意义,非常有效率的代码,那唯一要考虑的就是,是不是负载真得太大了。

D 状态任务增多

根据 Linux 内核的设计, D 状态任务本质上是 TASK_UNINTERRUPTIBLE 引发的主动睡眠,因此其可能性非常多。但是由于 Linux 内核 CPU 空闲时间上对 IO 栈引发的睡眠做了特殊的定义,即 iowait,因此iowait 成为 D 状态分类里定位是否 Load 高是由 IO 引发的一个重要参考。

当然,如前所述, /proc/stat 中的 procs_blocked 的变化趋势也可以是一个非常好的判定因 iowait引发的 Load 高的一个参考。

CPU iowait 高

很多人通常都对 CPU iowait 有一个误解,以为 iowait 高是因为这时的 CPU 正在忙于做 IO 操作。其实恰恰相反, iowait 高的时候,CPU 正处于空闲状态,没有任何任务可以运行。只是因为此时存在已经发出的磁盘 IO,因此这时的空闲状态被标识成了 iowait ,而不是 idle。

但此时,如果用 perf probe 命令,我们可以清楚得看到,在 iowait 状态的 CPU,实际上是运行在 pid 为 0 的 idle 线程上:

3B99775A-E695-4fdf-87C2-BE233D0D5BB2.png

相关的 idle 线程的循环如何分别对 CPU iowait 和 idle 计数的代码,如下所示:

2AB5D952-30F5-4a06-8D8E-39C3DF6B414B.png

而 Linux IO 栈和文件系统的代码则会调用 io_schedule,等待磁盘 IO 的完成。这时候,对 CPU 时间被记为 iowait 起关键计数的原子变量 rq->nr_iowait 则会在睡眠前被增加。注意,io_schedule 在被调用前,通常 caller 会先将任务显式地设置成 TASK_UNINTERRUPTIBLE 状态:

63C5CE5E-8254-48e5-8DCA-A2414F0B52E1.png

CPU idle 高

如前所述,有相当多的内核的阻塞,即 TASK_UNINTERRUPTIBLE 的睡眠,实际上与等待磁盘 IO 无关,如内核中的锁竞争,再如内存直接页回收的睡眠,又如内核中一些代码路径上的主动阻塞,等待资源。

Brendan Gregg 在最近的博客 [Linux Load Averages: Solving the Mystery] (http://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html)中,使用 perf 命令产生的 TASK_UNINTERRUPTIBLE 的睡眠的火焰图,很好的展示了引起 CPU idle 高的多样性。本文不在赘述。

因此,CPU idle 高的分析,实质上就是分析内核的代码路径引起阻塞的主因是什么。通常,我们可以使用 perf inject 对 perf record 记录的上下文切换的事件进行处理,关联出进程从 CPU 切出 (swtich out) 和再次切入 (switch in) 的内核代码路径,生成一个所谓的 Off CPU 火焰图.

当然,类似于锁竞争这样的比较简单的问题,Off CPU 火焰图足以一步定位出问题。但是对于更加复杂的因 D 状态而阻塞的延迟问题,可能 Off CPU 火焰图只能给我们一个调查的起点。

例如,当我们看到,Off CPU 火焰图的主要睡眠时间是因为 epoll_wait 等待引发的。那么,我们继续要排查的应该是网络栈的延迟,即本文大图中的 Net Delay 这部分。

至此,你也许会发现,CPU iowait 和 idle 高的性能分析的实质就是 延迟分析。这就是大图按照内核中资源管理的大方向,将延迟分析细化成了六大延迟分析:

  • CPU 延迟
  • 内存延迟
  • 文件系统延迟
  • IO 栈延迟
  • 网络栈延迟
  • 锁及同步原语竞争

任何上述代码路径引发的 TASK_UNINTERRUPTIBLE 的睡眠,都是我们要分析的对象!

以问题结束

限于篇幅,本文很难将其所涉及的细节一一展开,因为读到这里,你也许会发现,原来 Load 高的分析,实际上就是对系统的全面负载分析。怪不得叫 System Load 呢。这也是 Load 分析为什么很难在一篇文章里去全面覆盖。

本文也开启了浅谈 Linux 性能分析系列的第一章。后续我们会推出系列文章,就前文所述的六大延迟分析,一一展开介绍,敬请期待……

关于作者

杨勇 (Oliver Yang),Linux 内核工程师,来自阿里云系统组。曾就职于 EMC,Sun 中国工程研究院,在存储系统和 Solaris 内核开发领域工作。

原文链接

本文为阿里云原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/news/512589.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用c语言程序写一段英文字母,菜鸟求助,写一个随机输出26个英文字母的程序...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼#include #include // 用srand、rand函数了#include // 用time函数了#define LEN 32// 产生min~max的随机数 (包含min和max)// rand函数产生0 ~ RAND_MAX 的随机数// 一般上不同编译器要求 RAND_MAX 的值(至少)为 32767#define RAN…

AI、元宇宙技术方兴未艾,软件测试重装上阵

Larry Bernstain 曾说过“在系统测试阶段找出并修正错误,要比开发者自己完成这一工作多付出 2 倍的努力。而当系统已经交付使用之后找出并修正错误,要比系统测试阶段多付出 9 倍的努力。” 测试用例总结,图片来源:Applause以上我们…

如何快速搭建云原生企业级数据湖架构及实践分享

简介: 众所周知,数据湖技术在大数据领域炙手可热,随着在云上的广泛部署和应用,其业务价值逐渐获得业界共识。如何快搭建数据湖架构被越来越多的企业探讨。本文主要分享快速搭建云原生企业级数据湖架构及实践分享。 王震&#xff0…

设置android应用闪屏图片_Android实现启动页面(闪屏页面)

不难发现,我们手机上的很多app都有启动页面,例如打开简书App在显示主页文章前会有一个启动页面,如下所示:简书启动页面随后是一个广告页面,最后才进入到主页去。那么我们自己怎么实现这个效果呢?下面开始讲…

5分钟搞定AlertManager接入短信、语音等10+种通知渠道

简介: Alert Manager是开源监控系统Prometheus中用于处理告警信息的服务,通过将日志服务开放告警配置为Alert Manager中的一个Receiver,可以将Alert Manager产生的告警消息发送到日志服务。 SLS告警管理 AlertManager作为Prometheus生态系统…

c语言编程输出数组元素之和,C语言 输出一个数组中,所有元素之和为0的子序列...

本程序用到了一个时间种子,来随机产生10个整数[-5~5],函数是randData( )。还有一个计算子序列为0的函数ZeroSubarray( )。randData( )如下:int arr[10];void randData(int a[], int start, int end){srand(time(NULL));for (int i start; i …

小米百万美金大奖花落机器狗团队,5 年千亿重砸研发鼓励创新

1月4日,第三届小米百万美金技术大奖公布,CyberDog铁蛋四足仿生机器人在 68个参评项目中脱颖而出,一举获得最高奖。值得一提的是,该团队拥有两名 2020 年应届毕业生成员。 小米集团创始人、董事长兼CEO雷军在微博高兴地说道&#x…

日志审计携手DDoS防护助力云上安全

简介: 本文主要介绍日志审计结合DDoS防护保障云上业务安全的新实践。 日志审计携手DDoS防护助力云上安全 1 背景介绍 设想一下,此时你正在高速公路上开车去上班,路上还有其他汽车,总体而言,大家都按照清晰的合法速度…

linux推出超级用户_linux添加root权限用户

方法一:1.添加普通用户并设置密码[rootcentos6 ~]# useradd ggg[rootcentos6 ~]# passwd gggChanging password for user ggg.Newpassword:BADPASSWORD: it is WAY too shortPASSWORD: is a palindromeRetype new password:passwd: all authentication tokens updat…

日期天数转换c语言程序,C语言 ---计算连个日期之间的天数转换

/* 返回绝对值 */int abs(int a,int b){if(a>b)return (a-b);elsereturn (b-a);}/* 判断是否为闰年:是,返回 1 ; 不是, 返回 0 . */int IsLeap(int year){if(((year%40)&&(year%100!0))||year%4000)return 1;elsereturn 0;}/* 判断某个日期从年初(y年1月1日)到该天(…

MySQL 深潜 - 一文详解 MySQL Data Dictionary

简介: 在 MySQL 8.0 之前,Server 层和存储引擎(比如 InnoDB)会各自保留一份元数据(schema name, table definition 等),不仅在信息存储上有着重复冗余,而且可能存在两者之间存储的元…

中国加速计算市场第二名,宁畅正领跑“智能算力定制”赛道

构建“元宇宙”最缺什么?对此,服务器新一线厂商宁畅给出的答案是“定制化算力”。 2022年1月6日,在“创立两周年媒体会”上宁畅透露,伴随IT头部企业进入“元宇宙”赛道,以及宁畅“智定”战略推进,2021年宁…

filter动态参数 maven_使用Profile和Resources Filter隔离测试环境

Maven能够帮我们很好的管理测试,我们可以在src/test/java和 src/test/resources下面使用JUnit或者TestNG 编写单元测试和集成测试,然后在命令行运行 mvn test,测试就会自动运行,同时产生详细的测试报告。对只有一两个人的项目来说…

CPU Burst有副作用吗?让数学来回答!| 龙蜥技术

简介: 使用CPU Burst的副作用是什么?是否有不适用的场景呢?戳我给你答案~ 编者按:CPU Burst 特性已合入 Linux 5.14,Anolis OS 8.2、Alibaba Cloud Linux2、Alibaba Cloud Linux3也都支持CPU Burst特性。 在系列文章的…

c语言动态规划公共字符串,最长公共子串 C语言 动态规划

给定两个字符串 text1 和 text2,返回这两个字符串的最长公共子序列。一个字符串的 子序列是指这样一个新的字符串:它是由原字符串在不改变字符的相对顺序的情况下删除某些字符(也可以不删除任何字符)后组成的新字符串。 例如,“ace”是 “abc…

用了 HTTPS,没想到还是被监控了!

作者 | 轩辕之风来源 | 编程技术宇宙大家好,我是轩辕。上周,微信里有个小伙伴儿给我发来了消息:随后,我让他截了一个完整的图,我一瞅,是HTTPS啊!没用HTTP!再一瞅,是www.b…

AI让边缘更智能 边缘让AI无处不在

简介: 城市管理和城市服务逐步走向智能化,智慧化。到2019底,全国100%的副省级城市,95%以上的地级市,以及50%以上的县级市均提出建设新型智慧城市,并已经有32个主要城市成立了专门的大数据管理机构&#xff…

wepy组件子父传值_【WePY小程序框架实战三】-组件传值

父子组件传值静态传值静态传值为父组件向子组件传递常量数据,因此只能传递String字符串类型。父组件 (parent.wpy)子组件(child.wpy){{name}}props{name:String}onLoad(){console.log(this.name);//leinov}动态传值sync修饰符来达到父组件数据绑定至子组件的效果也可…

开源自建/托管与商业化自研 Trace,如何选择?

简介: 随着微服务架构的兴起,服务端的调用依赖愈加复杂,为了快速定位异常组件与性能瓶颈,接入分布式链路追踪 Trace 已经成为 IT 运维领域的共识。但是,开源自建、开源托管或商业化自研 Trace 产品之间到底有哪些差异&…

python 覆盖list_【Python妙招】gt;gt;gt;看腻了能不能换成别的啊……当然可以啦:)...

原文作者:站在两个世界边缘 & 小象编辑:VL今天给大家介绍几个Python里(可能没那么广为人知的)小知识,希望能给大家带来帮助,让编程更有乐趣。1.如何修改解释器提示符正常情况下,我们在终端下执行Python 命令是这样…