摘 学习笔记

 

1、Linux并发(任务并行)的实质:Linux 作为一个多任务操作系统,将每个 CPU 的时间划分为很短的时间片,再通过调度器轮流分配给各个任务使用

2、cpu的维护,通过实先定义的节拍率(内核用赫兹HZ标示)触发时间判断(全局变量jiffies记录)。

3、节拍率是内核态运行,属于内核空间节拍率;用户空间节拍率( USER_HZ)是一个固定设置 [root@dbayang ~]# grep 'CONFIG_HZ=' /boot/config-$(uname -r) CONFIG_HZ=1000

4、/proc/stat 提供的就是系统的 CPU 和任务统计信息;

/proc/[pid]/stat展示进程的CPU和任务统计信息

5、cpu的使用率={1-(idle_time/total_cpu_time)}/sample_time

6、性能分析工具给出的都是间隔一段时间的平均 CPU 使用率,所以要注意间隔时间的设置。

top默认为3s,ps使用的是进程运行时间。

7、top、vmstat、mpstat等命令种关于cpu性能相关指标的含义

8、pidstat命令含义

9、perf 以前用到的一堆[n]trace分析工具,perf的直观易用。

perf top、

perf record、perf report 对进程进行跟踪分析其调用

perf top -g -p <mysqlpid>

10、今天用到测试工具:ab

 

针对“幽灵”进程的发掘:

1,在top中,可见用户态cpu使用率很高,但未见相关有问题的进程;

2,尝试pidstat 1 找出问题进程,无果;

3,再次top,从load average 可见负载高,shift + f ,然后选择以s (进程状态)排序,按R倒序,可见running的进程主要就是几个stress进程,观察发现,running的stress进程的pid一直在变化;

4,watch -d 'ps aux | grep stress | grep -v grep' 发现多个stress进程在不断生成,由R变S再变Z(由于watch的时间间隔是1秒,所以只是看到有多个stress进程,有的状态是R有的是S有的是Z,所以我推断其生命周期是如此)

5,进程Pid再不断变化,有以下两个原因:

5.1,进程在不断崩溃重启,如因为段错误,配置错误等,这时进程在退出后又被监控系统自动重启

5.2,这些都是短进程,即在应用内部通过exec调用外部命令。这些命令一般只运行很短的时间就会结束,很难用时间间隔长的工具,如top去发现

6,用pstress去找其父进程

7,发现是php容器,故查看php源码 # 拷贝源码到本地 $ docker cp phpfpm:/app . # grep 查找看看是不是有代码在调用 stress 命令 $ grep stress -r app

8,从源代码中找相关字段

9,stress -t 1 -d 1 是模拟IO压力的,但在之前的top中,未见%iowait异常;

10,通过代码中的判断字段,手动赋值访问 curl http://192.168.0.10:10000?verbose=1 Server internal error: Array ( [0] => stress: info: [19607] dispatching hogs: 0 cpu, 0 io, 0 vm, 1 hdd [1] => stress: FAIL: [19608] (563) mkstemp failed: Permission denied [2] => stress: FAIL: [19607] (394) <-- worker 19608 returned error 1 [3] => stress: WARN: [19607] (396) now reaping child worker processes [4] => stress: FAIL: [19607] (400) kill error: No such process [5] => stress: FAIL: [19607] (451) failed run completed in 0s )

11,从这里可以猜测,由于权限错误,大量的stress进程在启动时初始化失败,结合第4点,我认为CPU消耗在进程上下文切换,从vmstat可见cs由问题出现前的100多骤升并稳定维持在3000多 [root@master ~]

# vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 9 0 0 6932288 2160 790400 0 0 20 24 44 71 8 5 87 0 0 8 0 0 6932784 2160 790560 0 0 0 0 4027 3512 71 27 3 0 0 11 0 0 6934920 2160 790488 0 0 0 0 4170 3646 72 28 1 0 0 但pidstat -w |grep stress 却未见异常,因为同名进程一直在更换,所以用pidstat -w在这里是不太适用的 [root@master ~]# pidstat -w 2 | grep stress 09:55:29 AM 1 18583 0.50 0.50 stress 09:55:29 AM 1 18584 0.50 0.50 stress 09:55:29 AM 1 18586 0.50 0.00 stress

 

其他JVM分析:

处理CPU高的流程如下(大数据,基本都是jvm):

  • 通过top查看cpu使用率比较高的进程
  • pid top -H $pid 造成cpu使用率的线程 tid (top第一列,列明还是PID)
  • printf 0x%x $tid 获得16进制的tid
  • jstack $pid 查找 nid=16进制tid,相应线程的就找到了

PS:现在大多是docker 环境,在宿主机无法直接通过jstack获取到容器内的jvm 线程信息,可以进入容器再jstack 或者在宿主机上使用jdk 10;容器内无法使用jtack 之类命令,那么需要添加容器参数 privileged