1、概述
性能测试中,对服务端的指标监控也是很重要的一个环节。通过对各项服务器性能指标的监控分析,可以定位到性能瓶颈;后端性能指标有 CPU,内存,网络,jvm,I/O 等等
2.CPU瓶颈分析
(1)cpu 有没有正常工作
1:top 看 CPU 负载,vmstat 看 CPU 利用率。下面三种情况说明 cpu 没有正常工作,需要看 cpu 在做什么
1)负载过高,利用率过低
2)负载过低,利用率过高
3)负载过低,利用率也低
cpu 平均负载指的是单位时间内正在运行的不可中断的平均进程数,也就是是等待处理的任务队列。下图红圈显示的是 5 分钟,10 分钟,15 分钟内的cpu平均负载
负载不超过内核数就算正常。
再输入1 可查看cpu内核数。
(2)cpu 在做什么
1:vmstat命令 看 in 和 cs 是否过高,如果过高,说明中断和上下文切换频繁。
in:每秒产生的中断次数
cs:每秒产生的上下文切换次数
2:vmstat 看 usr 和 sys 百分比。
us:用户进程消耗的CPU时间百分比
sy:内核进程消耗的CPU时间百分比
1)如果 sy 百分比过高,说明内核消耗的CPU资源多;
- 如果 us 百分比过高,说明用户进程消耗的CPU时间多,但是如果长期超50%的使用,那么我们就该考虑优化程序算法。
us+sy 的利用率在 50 到 80 之间都算正常。
3:vmstat 看运行队列
1)运行队列 r 值远超 cpu 数,说明 cpu 负载过高,系统现在运行比较慢,有多数的进程等待CPU;
2)b 值过高,说明大量进程处于 IO 等待,IO 可能存在瓶颈。
(3)为什么 cpu 不正常工作
1:pidstat -p【pid】-w 1 10 查看进程的主动和被动切换。
1)如果主动切换(cswch/s)过高,说明可能 IO,内存资源可能不足
2)如果被动切换(nvcswch/s)过高,说明进程过多,cpu 时间片不足。
时间片即CPU分配给各个程序的时间,每个线程被分配一个时间段,称作它的时间片,即该进程允许运行的时间,使各个程序从表面上看是同时进行的。
总结:分析 cpu 问题先看负载,再看利用率,利用率分用户空间和内核空间。负载高可能是线程多导致的;用户CPU高可能是代码层面问题,需要开发人员优化程序。
3.数据库慢查询
大部分系统都会用到数据库,而数据库的操作往往是涉及到磁盘 I/O 的读写。大量的数据库读写操作,会导致磁盘 I/O 性能瓶颈,进而导致数据库操作的延迟性。对于有大量数据库读写操作的系统来说,数据库的性能优化是整个系统的核心。
在PostgreSQL中,带子查询的复杂SQL语句,如果用LIMIT和OFFSET进行分页,有很大概率会出现慢查询。
(1)追踪慢sql
如果活跃连接数的变化处于正常范围,则很大概率可能是当时有性能很差的SQL被大量执行导致。我们可以通过这个日志,定位到当时比较耗时的SQL来进一步做分析。但通常问题发生时,整个系统都处于停滞状态,所有SQL都慢下来,当时记录的>慢SQL可能非常多,并不容易排查罪魁祸首。这里我们介绍几种在问题发生时,即介入追查慢SQL的方法。
1)直接通过pg_stat_activity视图
--查询执行时间超过1秒的sql
select * from pg_stat_activity where state<>'idle' and now()-query_start > interval '1 s' order by query_start ;
-- 查询时间较长的SQL,idle :是空闲的;client backend:客户端请求后端
select pid,xact_start,now()-xact_start as t ,state,query,client_addr,datname,backend_type from pg_stat_activity where state <>'idle' and backend_type='client backend' and now()-query_start > interval '0.1 s' order by t desc limit 5;
2)从数据表上表扫描(Table Scan)的信息开始查起,查找缺失索引的表。数据表如果缺失索引,大部分热数据又都在内存时(例如内存8G,热数据6G),此时数据库只能使用表扫描,并需要处理已在内存中的大量的无关记录,而耗费大量CPU。特别是对于表记录数超100的表,一次表扫描占用大量CPU(基本把一个CPU占满),多个连接并发(例如上百连接),把所有CPU占满。
--查出使用表扫描最多的表(疯狂读写)
select * from pg_stat_user_tables where n_live_tup > 100000 and seq_scan > 0 order by seq_tup_read desc limit 10;
3)锁
-- 查询已经锁住的SQL
select *, now()-xact_start as t from pg_stat_activity where state='active' and wait_event_type like '%Lock%';
-- 查询锁表的SQL
select * from pg_stat_activity where wait_event_type like '%Lock%'
(2)优化sql(了解)
1)对查询涉及的表,执行ANALYZE <table>或VACUUM ANZLYZE <table>,更新表的统计信息,使查询计划更准确。注意,为避免对业务影响,最好在业务低峰执行。
2)执行explain (query text)或explain (buffers true, analyze true, verbose true) (query text)命令,查看SQL的执行计划(注意,前者不会实际执行SQL,后者会实际执行而且能得到详细的执行信息),对其中的Table Scan涉及的表,建立索引。
3)重新编写SQL,去除掉不必要的子查询、改写UNION ALL、使用JOIN CLAUSE固定连接顺序等到,都是进一步深度优化SQL的手段,这里不再深入说明。