线上性能问题初步排查方法

本文首发于并发网,作者:方腾飞

引言

有时候有很多问题只有在线上或者预发环境才能发现,而线上又不能Debug,所以线上问题定位就只能看日志,系统状态和Dump线程,本文只是简单的介绍一些常用的工具,帮助定位线上问题。

问题定位

1: 首先使用TOP命令查看每个进程的情况,显示如下:

top - 22:27:25 up 463 days, 12:46, 1 user, load average: 11.80, 12.19, 11.79
 Tasks: 113 total, 5 running, 108 sleeping, 0 stopped, 0 zombie
 Cpu(s): 62.0%us, 2.8%sy, 0.0%ni, 34.3%id, 0.0%wa, 0.0%hi, 0.7%si, 0.2%st
 Mem: 7680000k total, 7665504k used, 14496k free, 97268k buffers
 Swap: 2096472k total, 14904k used, 2081568k free, 3033060k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
 31177 admin 18 0 5351m 4.0g 49m S 301.4 54.0 935:02.08 java
 31738 admin 15 0 36432 12m 1052 S 8.7 0.2 11:21.05 nginx-proxy

我们的程序是Java应用,所以只需要关注COMMAND是Java的性能数据,COMMAND表示启动当前进程的命令,在Java进程这一行里可以看到CPU利用率是300%,不用担心,这个是当前机器所有核加在一起的CPU利用率。

2: 再使用Top的交互命令数字1查看每个CPU的性能数据。

top - 22:24:50 up 463 days, 12:43, 1 user, load average: 12.55, 12.27, 11.73
 Tasks: 110 total, 3 running, 107 sleeping, 0 stopped, 0 zombie
 Cpu0 : 72.4%us, 3.6%sy, 0.0%ni, 22.7%id, 0.0%wa, 0.0%hi, 0.7%si, 0.7%st
 Cpu1 : 58.7%us, 4.3%sy, 0.0%ni, 34.3%id, 0.0%wa, 0.0%hi, 2.3%si, 0.3%st
 Cpu2 : 53.3%us, 2.6%sy, 0.0%ni, 34.1%id, 0.0%wa, 0.0%hi, 9.6%si, 0.3%st
 Cpu3 : 52.7%us, 2.7%sy, 0.0%ni, 25.2%id, 0.0%wa, 0.0%hi, 19.5%si, 0.0%st
 Cpu4 : 59.5%us, 2.7%sy, 0.0%ni, 31.2%id, 0.0%wa, 0.0%hi, 6.6%si, 0.0%st
 Mem: 7680000k total, 7663152k used, 16848k free, 98068k buffers
 Swap: 2096472k total, 14904k used, 2081568k free, 3032636k cached

命令行显示了CPU4,说明这是一个5核的虚拟机,平均每个CPU利用率在60%以上。如果这里显示CPU利用率100%,则很有可能程序里写了一个死循环。这些参数的含义,可以对比下表:


 us


用户空间占用CPU百分比


1.0% sy


内核空间占用CPU百分比


0.0% ni


用户进程空间内改变过优先级的进程占用CPU百分比


98.7% id


空闲CPU百分比


0.0% wa


等待输入输出的CPU时间百分比

3: 使用Top的交互命令H查看每个线程的性能信息。

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
 31558 admin 15 0 5351m 4.0g 49m S 12.2 54.0 10:08.31 java
 31561 admin 15 0 5351m 4.0g 49m R 12.2 54.0 9:45.43 java
 31626 admin 15 0 5351m 4.0g 49m S 11.9 54.0 13:50.21 java
 31559 admin 15 0 5351m 4.0g 49m S 10.9 54.0 5:34.67 java
 31612 admin 15 0 5351m 4.0g 49m S 10.6 54.0 8:42.77 java
 31555 admin 15 0 5351m 4.0g 49m S 10.3 54.0 13:00.55 java
 31630 admin 15 0 5351m 4.0g 49m R 10.3 54.0 4:00.75 java
 31646 admin 15 0 5351m 4.0g 49m S 10.3 54.0 3:19.92 java
 31653 admin 15 0 5351m 4.0g 49m S 10.3 54.0 8:52.90 java
 31607 admin 15 0 5351m 4.0g 49m S 9.9 54.0 14:37.82 java

在这里可能会出现三种情况:

  1. 第一种情况,某个线程一直CPU利用率100%,则说明是这个线程有可能有死循环,那么请记住这个PID。
  2. 第二种情况,某个线程一直在TOP十的位置,这说明这个线程可能有性能问题。
  3. 第三种情况,CPU利用率TOP几的线程在不停变化,说明并不是由某一个线程导致CPU偏高。

如果是第一种情况,也有可能是GC造成,我们可以用jstat命令看下GC情况,看看是不是因为持久代或年老代满了,产生Full GC,导致CPU利用率持续飙高,命令如下。

sudo /opt/java/bin/jstat -gcutil 31177 1000 5
 S0 S1 E O P YGC YGCT FGC FGCT GCT
 0.00 1.27 61.30 55.57 59.98 16040 143.775 30 77.692 221.467
 0.00 1.27 95.77 55.57 59.98 16040 143.775 30 77.692 221.467
 1.37 0.00 33.21 55.57 59.98 16041 143.781 30 77.692 221.474
 1.37 0.00 74.96 55.57 59.98 16041 143.781 30 77.692 221.474
 0.00 1.59 22.14 55.57 59.98 16042 143.789 30 77.692 221.481

我们还可以把线程Dump下来,看看究竟是哪个线程,执行什么代码造成的CPU利用率高。执行以下命令,把线程dump到文件dump17里。

sudo -u admin /opt/java/bin/jstack  31177 > /home/tengfei.fangtf/dump17

dump出来内容的类似下面这段:

"http-0.0.0.0-7001-97" daemon prio=10 tid=0x000000004f6a8000 nid=0x555e in Object.wait() [0x0000000052423000]
   java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on  (a org.apache.tomcat.util.net.AprEndpoint$Worker)
        at java.lang.Object.wait(Object.java:485)
        at org.apache.tomcat.util.net.AprEndpoint$Worker.await(AprEndpoint.java:1464)
        - locked  (a org.apache.tomcat.util.net.AprEndpoint$Worker)
        at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1489)
        at java.lang.Thread.run(Thread.java:662)

dump出来的线程ID(nid)是十六进制的,而我们用TOP命令看到的线程ID是10进制的,所以我们要printf命令转换一下进制。然后用16进制的ID去dump里找到对应的线程。


printf "%x\n" 31558
 输出:7b46

优化实战

1:查看下TCP连接状态,建立了800多个连接,需要尽量降低ESTABLISHED。


[tengfei.fangtf@ifeve ~]$ netstat -nat | awk '{print $6}' | sort | uniq -c | sort -n
 1 established)
 1 Foreign
 3 CLOSE_WAIT
 7 CLOSING
 14 FIN_WAIT2
 25 LISTEN
 39 LAST_ACK
 609 FIN_WAIT1
 882 ESTABLISHED
 10222 TIME_WAIT 

2:用jstack dump看看这些线程都在做什么。

sudo -u admin /opt/ifeve/java/bin/jstack 31177 > /home/tengfei.fangtf/dump17

3:统计下所有线程分别处于什么状态,发现大量线程处于WAITING(onobjectmonitor)状态

[tengfei.fangtf@ifeve ~]$ grep java.lang.Thread.State dump17 | awk '{print $2$3$4$5}' | sort | uniq -c
 39 RUNNABLE
 21 TIMED_WAITING(onobjectmonitor)
 6 TIMED_WAITING(parking)
 51 TIMED_WAITING(sleeping)
 305 WAITING(onobjectmonitor)
 3 WAITING(parking)

4:查看处于WAITING(onobjectmonitor)的线程信息,主要是jboss的工作线程在await。

"http-0.0.0.0-7001-97" daemon prio=10 tid=0x000000004f6a8000 nid=0x555e in Object.wait() [0x0000000052423000]
 java.lang.Thread.State: WAITING (on object monitor)
 at java.lang.Object.wait(Native Method)
 - waiting on <0x00000007969b2280> (a org.apache.tomcat.util.net.AprEndpoint$Worker)
 at java.lang.Object.wait(Object.java:485)
 at org.apache.tomcat.util.net.AprEndpoint$Worker.await(AprEndpoint.java:1464)
 - locked <0x00000007969b2280> (a org.apache.tomcat.util.net.AprEndpoint$Worker)
 at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1489)
 at java.lang.Thread.run(Thread.java:662)

5:找到jboss的线程配置信息,将maxThreads降低到100

<maxThreads="250" maxHttpHeaderSize="8192"
 emptySessionPath="false" minSpareThreads="40" maxSpareThreads="75" maxPostSize="512000" protocol="HTTP/1.1"
 enableLookups="false" redirectPort="8443" acceptCount="200" bufferSize="16384"
 connectionTimeout="15000" disableUploadTimeout="false" useBodyEncodingForURI="true">

6:重启jboss,再dump线程信息,然后统计,WAITING(onobjectmonitor)的线程减少了170。

[tengfei.fangtf@ifeve ~]$ grep java.lang.Thread.State dump17 | awk '{print $2$3$4$5}' | sort | uniq -c
 44 RUNNABLE
 22 TIMED_WAITING(onobjectmonitor)
 9 TIMED_WAITING(parking)
 36 TIMED_WAITING(sleeping)
 130 WAITING(onobjectmonitor)
 1 WAITING(parking)

其他命令

  • 查看CPU信息 cat /proc/cpuinfo
  • 查看内存信息 cat /proc/meminfo
  • 查看Java线程数 ps -eLf | grep java -c
  • 查看linux系统里打开文件描述符的最大值 ulimit -u
  • 找到日志里TOP10的异常:grep ‘Exception’ /home/admin/logs/XX.log |awk -F':|,’ ‘{print $2}’|sort |uniq -c |sort -nr|head -10,找到之后可以再用-A 2 -B 2,看定位出日志的前面2行和后面两行。
时间: 2024-12-30 23:52:36

线上性能问题初步排查方法的相关文章

php异步调试和线上调试网站程序的方法

下面分享一种方法同时满足这两种条件,既方便网站程序错误调试,又不影响网站的正常运行的调试方法.将下面的php语句复制到公共代码顶部即可.  代码如下 复制代码 //ini_set('error_reporting',E_ALL ^ E_NOTICE);//显示所有除了notice类型的错误信息 ini_set('error_reporting',E_ALL);//显示所有错误信息 ini_set('display_errors',off);//禁止将错误信息输出到输出端 ini_set('log

排查Java线上服务故障的方法和实例分析

前言 作为在线系统负责人或者是一个技术专家,你可能刚刚接手一个项目就需要处理紧急故障,或者被要求帮忙处理一些紧急的故障,这个时候的情景是: (1)你可能对这个业务仅仅是听说过,而不怎么真正了解: (2)你可能没有这个故障的详细信息,比如可能仅仅是有使用方反馈服务中断了10分钟: (3)你对代码细节还没有仔细研究过. 这个时候该怎么解决问题呢?根据以前的经验,工程师们常常倾向于直接登上服务器检查代码,试图立刻修改问题.或者是把某些可能是问题的配置做修改,但并不是100%确认这就是问题的根本原因.但

【原创】线上环境 SYN flooding 问题排查

问题描述:       线上环境中,公司自研即时通讯软件不定时掉线.  问题排查:       由运维和测试人员发现并报告,线上环境出现网络异常,具体表现为登录服务器虚拟 IP 地址无法 ping 通,即时通讯工具不定时掉线:       在此情况下,现场人员第一反应就是受到了外部攻击(因为以前遇到过攻击情况),因为看到了如下信息  ... Apr 20 18:21:48 localhost kernel: possible SYN flooding on port 80. Sending co

开启PHP的error_log排查线上遇到的错误

做开发的经常碰到这种情况,在线下测试的挺好的程序,上传到线上(生产环境)就会出现奇奇怪怪的错误,比如出现个空白页面,也不知道是哪里出问题了,而线上又不允许调试,那该如何去解决这个问题呢?除了在仔细一遍遍的检查代码外,还可以通过开启php的error_log来排查错误. 大家应该都知道当php.ini中的display_errors设置为on的时候,运行程序的时候经常会看到满屏的notice warning啊什么的. 开启error_log的情况下也会记录这些notice warning信息,但是

线上PHP问题排查思路与实践

前言 前几天,在一淘网,腾讯网媒和微博商业技术联合组织的技术分享大会上,我分享了<在线PHP问题排查思路与实践>.此博文除了对PPT提供下载外,还会对ppt做简单的注释说明.主题分为三部分,常见问题,解决思路和案例分析. 常见问题 不同用户看到的错误可能不一样.一般用户看到的错误都是表层的现象.如,裸奔的错误页面: <img src="http://www.bo56.com/wp-content/uploads/2015/09/luoben.png" alt=&quo

线上Java应用排查和诊断规范

线上Java应用排查和诊断规范 http://www.iteye.com/topic/1132132 标准做法一:OOM触发HeadpDump 目的: OOM发生时,输出堆栈快照文件,供研发人员分析. 在JVM中,如果98%的时间是用于 GC 且可用的 Heap size 不足2%的时候,将抛出 OOM 异常. 配置操作: Resin/Tomcat 配置文件里追加 -XX:+HeapDumpOnOutOfMemoryError ,当 OutOfMemoryException 错误发生时,会自动生

thinkPHP线上自动加载异常与修复方法实例分析_php实例

本文实例讲述了thinkPHP线上自动加载异常与修复方法.分享给大家供大家参考,具体如下: 项目遇到一个奇怪的问题,本地代码正常,服务器上却不正常. 经过测试,应该是自动加载出了问题,尝试了各种方法, 1.手动加载,发现好麻烦,没完没了. 2.自己写自动加载,写不出来,尴尬. 3.修改配置,使其支持自动加载,发现还是不行. 后来进行调试, 发现本地支持 import('@.ORG.OSS\OssClient'); import('@.ORG.OSS\Core\OssUtil'); 而服务器上,不

一则线上MySql连接异常的排查过程

Mysql作为一个常用数据库,在互联网系统应用很多.有些故障是其自身的bug,有些则不是,这里以前段时间遇到的问题举例. 问题 当时遇到的症状是这样的,我们的应用在线上测试环境,JMeter测试过程中,发现每次压力测试开始时访问低前几个http request请求会超时,而之后的请求持续测试中都不会.最后一点是Tomcat的log并没有报什么错误. 压测的内容就是起200线程不停的向这个http页面发送请求,这个页面逻辑也比较简单,会在后端向数据库插入一条数据,连接池采用阿里的Druid(这个坑

浅谈地方论坛线上推广与线下推广方法

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 推广论坛比推广个人网站还要累,因为论坛注重的是人气,没有人气,什么都是空想杂谈.即使是口上说得未来多么多么牛都没用.因为根本没人知道这个论坛的存在,更别说是谈盈利了.所以论坛推广一定要注重两方面,只有这两方面结合起来,才能更有效更快速的把论坛推向大众,使大众知道有这以一个论坛存在,而且在论坛方面也要做好相应的措施,如内容,版块设置等一些细节,