社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
在当今Docker等容器大行其道的年代,多数互联网公司的线上服务器都是使用Linux。当我们的服务部署在Linux上并出现问题时,都指望运维同学来排查是不切实际的,因此程序员必须具备一定的问题排查能力。
但是,大多数程序员并不清楚要如何排查常见的Linux线上问题。当然,能直接从业务系统的日志中得知问题所在,那还比较好办,但是如果遇到CPU高、内存高、IO高、网络问题等,很多人就会无从下手。
因此,笔者总结了一些常见线上问题排查的经验与大家分享。
对于CPU高,我们首先分为两种情况分析,一种是用户CPU高,另外一种是系统CPU高。用户CPU高通常是用户程序消耗了较多的CPU,如:程序的死循环、大量的CAS操作等。
而内核CPU高则是系统方法消耗了较多的CPU,如:上下文切换、页切换等。但归根到底,系统不会自己无缘无故出现这些情况,最终还是应用程序的系统调用等因素导致的。
Linux内核目前有300多个系统调用。这些系统调用主要分为几类:
文件和设备访问类 比如open/close/read/write/chmod等
进程管理类 fork/clone/execve/exit/getpid等
信号类 signal/sigaction/kill 等
内存管理 brk/mmap/mlock等
进程间通信IPC shmget/semget 信号量,共享内存等
网络通信 socket/connect/sendto/sendmsg 等
其他
首先,我们通过top
命令确定是用户CPU高还是系统CPU高,并且能找到CPU最高的进程PID。
如果是用户CPU高,我们会分为Java应用导致的高CPU和库函数调用导致的高CPU两种情况,并分别排查。
如果是系统CPU高,我们则直接确定是哪些系统调用导致的,并追踪对应的程序。
下面来看一个例子,我们可以使用top
命令来查看用户CPU和系统CPU的使用百分比:
很明显,用户程序使用了50.6%的CPU,并且占用CPU最高的是一个java进程。
对于用户CPU高,我们分别介绍Java应用导致和库函数调用导致两种情况下的问题排查。我们先使用上一小节的场景,排查Java应用CPU高的原因。
我们已经从top
命令中得知,导致用户CPU高的java应用PID是23517。但是这是不够的,我们还需要知道具体是什么代码导致的高CPU。因此,我们使用命令:top -Hp 23517
,列出进程中线程CPU的使用统计。
我们可以看到,占用CPU最高的线程PID是23518。然后,我们把这个PID转换为16进制,得到5bde
。
接着,我们输入命令jstack 23517 | grep -C 50 5bde
查看具体是哪个线程占用了这么多的CPU。
我们可以看到,在Test类的main方法中,第11行的代码造成了CPU高。
当然有时候我们会追踪到由于GC线程导致的高CPU,此时就需要再进行内存方面的诊断了。
当我们的程序频繁调用系统库函数,也会导致用户CPU高,此时我们可以使用ltrace
来跟踪进程调用库函数的情况,以下是比较常用的命令参数。
ltrace —— library call tracer
-T显示每一调用所耗的时间.
-f 跟踪由fork调用所产生的子进程.
-p 绑定一个由PID对应的进程.
-c 统计每一系统调用的所执行的时间,次数和出错的次数等.
-d 输出strace关于标准错误的调试信息.
-l 只打印某个库中的调用
-o 把输出定向到文件
…
以使用了-Tfp参数为例,最左边是PID,然后是被调用的系统函数库,右边是返回的结果和对应的耗时。
当分析出耗时最多的系统库函数时,就能很容易定位到是什么代码造成的CPU高。
内核CPU高是由于系统方法消耗了较多的CPU,因此我们可以使用strace
,跟踪进程的系统调用或信号产生的情况,用来确定内核CPU。
因为Linux进程不能直接去访问硬件设备,如:读取磁盘文件、接收网络数据等,但可以通过系统调用来实现。这时strace就可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间、调用次数,成功和失败的次数。
strace
和ltrace
的使用方式非常相似,因此就不再赘述。
如果是因为中断导致的CPU高,可以使用cat /proc/interrupts
查看每个CPU被中断的次数统计。
这次我们介绍了在Linux系统中的CPU问题诊断。后面我们会继续介绍内存、IO、网络等方面的诊断方法。
欢迎关注我们公众号
欢迎加入我们的知识星球,一起讨论技术问题
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!