性能优化是什么
性能优化就是发挥机器本来的性能
术语
- 系统吞吐量:指于一网络内单位时间所有终端传递的数据量的总和
- 平均响应时间:提交请求到返回该请求响应所使用的时间
- 平均响应时间越短,系统吞吐量越大;平均响应时间越长,系统吞吐量越小。但是,系统吞吐量越大,未必平均响应时间越短。因为在某些情况(例如:不增加任何硬件配置)吞吐量的增大,有时会把平均响应时间作为牺牲,来换取一段时间处理更多的请求
- TPS:
Transaction Per Second
,每秒事务处理量,每秒钟系统能够处理的交易或事务的数量 - QPS:
Queries Per Second
,每秒查询率,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准
性能优化的几个维度
CPU
命令 vmstat
1
2
3
4
[root@localhost ~]# vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 42520 2108 312920 0 0 10 5 26 29 0 0 100 0 0
vmstat 1
:表示 1 秒查看一次
首先检查 CPU,CPU 使用率要提升而不是减低
CPU 空闲并不一定是没事做,也有可能是锁或者外部资源瓶颈
命令 top
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
top - 04:26:18 up 5:49, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 98 total, 1 running, 97 sleeping, 0 stopped, 0 zombie
%Cpu0 : 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 481876 total, 42292 free, 124588 used, 314996 buff/cache
KiB Swap: 1048572 total, 1048572 free, 0 used. 300772 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1160 root 20 0 89632 2192 1160 S 0.3 0.5 0:00.15 master
2171 root 20 0 0 0 0 S 0.3 0.0 0:00.39 kworker/0:0
1 root 20 0 127928 6508 4088 S 0.0 1.4 0:02.53 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd
3 root 20 0 0 0 0 S 0.0 0.0 0:00.10 ksoftirqd/0
5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:+
7 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0
8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh
9 root 20 0 0 0 0 S 0.0 0.0 0:00.93 rcu_sched
10 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 lru-add-dr+
11 root rt 0 0 0 0 S 0.0 0.0 0:00.14 watchdog/0
13 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs
14 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 netns
15 root 20 0 0 0 0 S 0.0 0.0 0:00.01 khungtaskd
16 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 writeback
17 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kintegrityd
18 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 bioset
load average
:1 分钟、5 分钟、10 分钟的负载
查看 CPU 核数
- 在
top
命令下,按数字1
,显示每个 CPU 的负载情况 - 使用命令:
cat /proc/cpuinfo
,查看processor
属性,表示剩余 CPU 核数
CPU 负载高如何定位
-
top
找到 CPU 使用率高的进程- 原理:方法是由线程执行的,线程是在进程下运行的,找到进程下 CPU 使用率最高的线程就能定位到方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
top - 06:24:35 up 7:47, 4 users, load average: 0.87, 0.46, 0.73 Tasks: 101 total, 1 running, 100 sleeping, 0 stopped, 0 zombie %Cpu(s):100.0 us, 0.0 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 481876 total, 19420 free, 237800 used, 224656 buff/cache KiB Swap: 1048572 total, 1043956 free, 4616 used. 185260 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3311 root 20 0 2169984 130780 13196 S 92.0 27.1 0:38.10 java 1 root 20 0 127928 3804 2268 S 0.0 0.8 0:02.98 systemd 2 root 20 0 0 0 0 S 0.0 0.0 0:00.01 kthreadd 3 root 20 0 0 0 0 S 0.0 0.0 0:00.21 ksoftirqd/0 5 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:+ 7 root rt 0 0 0 0 S 0.0 0.0 0:00.00 migration/0 8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 rcu_bh 9 root 20 0 0 0 0 S 0.0 0.0 0:01.08 rcu_sched 10 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 lru-add-dr+ 11 root rt 0 0 0 0 S 0.0 0.0 0:00.18 watchdog/0 13 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs 14 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 netns 15 root 20 0 0 0 0 S 0.0 0.0 0:00.01 khungtaskd 16 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 writeback 17 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kintegrityd 18 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 bioset 19 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kblock
-
Shift+H
切换到线程模型,找到线程执行 CPU 高的线程号1 2 3 4 5 6 7 8 9 10
top - 06:24:57 up 7:48, 4 users, load average: 0.91, 0.50, 0.73 Threads: 142 total, 2 running, 140 sleeping, 0 stopped, 0 zombie %Cpu(s): 99.7 us, 0.3 sy, 0.0 ni, 0.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st KiB Mem : 481876 total, 19296 free, 237924 used, 224656 buff/cache KiB Swap: 1048572 total, 1043956 free, 4616 used. 185136 avail Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 3328 root 20 0 2169984 130780 13196 R 92.3 27.1 0:47.24 http-nio-8+ 3342 root 20 0 161980 2308 1624 R 0.3 0.5 0:00.07 top 1 root 20 0 127928 3804 2268 S 0.0 0.8 0:02.98 systemd
-
把线程号转换为 16 进制
1 2 3
# printf "%x \n" PID [root@localhost ~]# printf "%x \n" 3328 d00
-
用
jstack
导出线程的 dump,jstack 进程PID > p.txt
-
查看日志,使用 16 进制 PID 进行查询,
/16进制PID
1 2 3 4 5 6 7 8 9
vim p.txt # log "http-nio-8080-exec-1" #16 daemon prio=5 os_prio=0 tid=0x00007f2c807e2000 nid=0xd00 runnable [0x00007f2c4f8f9000] java.lang.Thread.State: RUNNABLE at com.test.controllers.HelloWorldController.cpu(HelloWorldController.java:30) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498)
Memory
命令 free
1
2
3
4
[root@localhost ~]# free -m
total used free shared buff/cache available
Mem: 470 121 41 5 307 293
Swap: 1023 0 1023
free -m
:单位为 MB
free -g
:单位为 G
buffers
:表示写
cached
:表示读
两者都是 RAM 中的数据,简单来说,
buffers
是即将要被写入磁盘的,cached
是被从磁盘中读出来的。这而是是为了提高 IO 性能的,并由 OS 管理,并非应用自己分配的内存,而是 OS 自己根据需要对空闲内存进行的额外利用。因为这部分知识缓存,降低 IO,提升性能,只要应用程序有需要,OS 可以直接将buffers
写入磁盘,将cached
删掉来得到空闲内存给应用程序使用。
buffers
是用于存储速度不同步的设备或优先级不同的设备之间传输数据的区域,缓冲(buffers
)是根据磁盘的读写设计的,把分散的写操作集中进行,减少磁盘碎片和磁盘的反复寻道,从而提高系统性能。
cached
经常被用在磁盘的 I/O 请求上,如果有多个进程都要访问某个文件,该文件便被做成cached
,以方便下次被访问,这样可提高系统性能。缓存(cached
)是把读取过的数据保存起来,重新读取时若命中(找到需要的数据),就不要去读硬盘了,若没有命中就读硬盘。其中的数据会根据读取频率进行组织,把最频繁读取的内容放在最容易找到的位置,把不再读的内容不断往后排,直至从中删除。
-/+ buffers/cache
的含义即:使用内存是当前实际使用内存减去buffers
、cached
之和,空闲内存是实际空闲内存加上buffers
、cached
之和。所以是-/+
查看空闲内存,确定应用是否由内存泄露时,只能以
free
的第三行为依据,第二行其实作用不大,只是可以看到 OS 当前的buffers
和cached
大小
IO
命令 iostat
CentOS 安装:yum -y install sysstat
1
2
3
4
5
6
7
[root@localhost ~]# iostat -xd 1
Linux 3.10.0-862.el7.x86_64 (localhost.localdomain) 2019年07月26日 _x86_64(1 CPU)
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.00 0.02 0.30 0.12 9.94 4.64 68.99 0.00 0.73 0.60 1.05 0.38 0.02
dm-0 0.00 0.00 0.20 0.14 9.45 4.55 81.33 0.00 0.94 0.81 1.14 0.43 0.01
dm-1 0.00 0.00 0.00 0.00 0.11 0.00 47.40 0.00 0.31 0.31 0.00 0.23 0.00
iostat -dx 1
:每秒查询一次
df -h
:查看系统磁盘使用情况
du -h 文件夹
:查看文件大小
Network
命令 nicstat
1
2
3
4
5
6
7
8
9
# 安装
wget http://sourceforge.net/projects/nicstat/files/nicstat-1.95.tar.gz
tar -zxvf nicstat-1.95.tar.gz
cd nicstat-1.95
mv Makefile.Linux Makefile
vim Makefile
# CFLAGS = $(COPT) -m32 # 将此行修改为如下,目前主流是 64 位 Linux,如果是 32 位可以不用更改
CFLAGS = $(COPT)
make && make install
1
2
3
4
5
6
7
8
9
10
11
12
13
# 查看网卡速度 -l
[root@localhost ~]# nicstat -l
Int Loopback Mbit/s Duplex State
lo Yes - unkn up
ens33 No 1000 full up
# 间隔 3 秒,查看 2 次结果
[root@localhost ~]# nicstat 3 2
Time Int rKB/s wKB/s rPk/s wPk/s rAvs wAvs %Util Sat
04:09:31 lo 0.00 0.00 0.00 0.00 86.94 86.94 0.00 0.00
04:09:31 ens33 0.57 0.03 0.65 0.23 903.3 117.8 0.00 0.00
Time Int rKB/s wKB/s rPk/s wPk/s rAvs wAvs %Util Sat
04:09:34 lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
04:09:34 ens33 0.02 0.11 0.33 0.33 66.00 342.0 0.00 0.00
- Time : 表示当前采样的响应时间
- Int:lo、ens33,网卡名称
- rKB/s : 每秒接收到千字节数
- wKB/s : 每秒写的千字节数
- rPk/s : 每秒接收到的数据包数目
- wPk/s : 每秒写的数据包数目
- rAvs : 接收到的数据包平均大小
- wAvs : 传输的数据包平均大小
- %Util : 网卡利用率(百分比)
- Sat : 网卡每秒的错误数.网卡是否接近饱满的一个指标.尝试去诊断网络问题的时候,推荐使用
-x
选项去查看更多的统计信息
1
2
3
4
5
6
7
8
9
10
11
12
# 查看扩展信息,-x 和 -s
[root@localhost ~]# nicstat 3 2 -x
04:15:06 RdKB WrKB RdPkt WrPkt IErr OErr Coll NoCP Defer %Util
lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
ens33 0.56 0.03 0.64 0.22 0.00 0.00 0.00 0.00 0.00 0.00
04:15:09 RdKB WrKB RdPkt WrPkt IErr OErr Coll NoCP Defer %Util
lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
ens33 0.02 0.11 0.33 0.33 0.00 0.00 0.00 0.00 0.00 0.00
[root@localhost ~]# nicstat -s
Time Int rKB/s wKB/s
04:15:14 lo 0.000 0.000
04:15:14 ens33 0.562 0.026
1
2
3
4
# 查看 TCP 相关信息,-t
[root@localhost ~]# nicstat -t
04:16:30 InKB OutKB InSeg OutSeg Reset AttF %ReTX InConn OutCon Drops
TCP 0.00 0.00 0.31 0.18 0.00 0.00 0.000 0.00 0.00 0.00
- InKB : 表示每秒接收到的千字节.
- OutKB : 表示每秒传输的千字节.
- InSeg : 表示每秒接收到的TCP数据段(TCP Segments).
- OutSeg : 表示每秒传输的TCP数据段(TCP Segments).
- Reset : 表示TCP连接从ESTABLISHED或CLOSE-WAIT状态直接转变为CLOSED状态的次数.
- AttF : 表示TCP连接从SYN-SENT或SYN-RCVD状态直接转变为CLOSED状态的次数,再加上TCP连接从SYN-RCVD状态直接转变为LISTEN状态的次数
- %ReTX : 表示TCP数据段(TCP Segments)重传的百分比.即传输的TCP数据段包含有一个或多个之前传输的八位字节.
- InConn : 表示TCP连接从LISTEN状态直接转变为SYN-RCVD状态的次数.
- OutCon : 表示TCP连接从CLOSED状态直接转变为SYN-SENT状态的次数.
- Drops : 表示从完成连接(completed connection)的队列和未完成连接(incomplete connection)的队列中丢弃的连接次数.
1
2
3
4
# 查看 UDP 相关信息,-u
[root@localhost ~]# nicstat -u
04:18:12 InDG OutDG InErr OutErr
UDP 0.02 0.03 0.00 0.00
- InDG : 每秒接收到的UDP数据报(UDP Datagrams)
- OutDG : 每秒传输的UDP数据报(UDP Datagrams)
- InErr : 接收到的因包含错误而不能被处理的数据包
- OutErr :因错误而不能成功传输的数据包.
1
2
3
4
5
# 默认以 KB 为单位,现在以 M 单位查看
[root@localhost ~]# nicstat -M
Time Int rMbps wMbps rPk/s wPk/s rAvs wAvs %Util Sat
04:20:39 lo 0.00 0.00 0.00 0.00 86.94 86.94 0.00 0.00
04:20:39 ens33 0.00 0.00 0.64 0.22 890.8 118.2 0.00 0.00
1
2
3
4
5
6
7
8
9
# 使用 -a 与 -x -t -u 相当
[root@localhost ~]# nicstat -x -t -u
04:21:15 InKB OutKB InSeg OutSeg Reset AttF %ReTX InConn OutCon Drops
TCP 0.00 0.00 0.31 0.18 0.00 0.00 0.000 0.00 0.00 0.00
04:21:15 InDG OutDG InErr OutErr
UDP 0.02 0.03 0.00 0.00
04:21:15 RdKB WrKB RdPkt WrPkt IErr OErr Coll NoCP Defer %Util
lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
ens33 0.55 0.03 0.64 0.22 0.00 0.00 0.00 0.00 0.00 0.00
监控软件
性能测试分析与调优
性能测试概念
用最低的资源换最高的处理能力和低的响应时间
- 在一定环境下做性能需求
- 环境是很难真实的
- 需求是很模糊的
- 响应时间
- 完成一个业务所需要的时间总和,越短越好
- 吞吐量
- 单位时间内处理的业务,越多越好
- 资源利用率
- 完成业务需要开销,CPU、内存、IO
行业内做性能测试
TPC
Transaction Processing Performance Council,事务处理性能委员会
高考一样,消耗多少资源换多少处理能力,Oracle是世界上最快的数据库
- 给一个标准的业务
- 比较完成业务的能力
- 强调业务处理处理能力
事务处理性能委员会是由数十家会员公司创建的非盈利组织,总部设在美国。TPC的成员主要是计算机软硬件厂家,而非计算机用户,其功能是制定商务应用基准程序的标准规范、性能和价格度量,并管理测试结果的发布。
TPC不给出基准程序的代码,而只给出基准程序的标准规范。任何厂家或其他测试者都可以根据规范,最优地构造出自己的测试系统(测试平台和测试程序)。为保证测试结果的完整性,被测试者(通常是厂家)必须提交给TPC一套完整的报告(Full Disclosure Report),包括被测系统的详细配置、分类价格和包含5年维护费用在内的总价格。该报告必须由TPC授权的审核员核实(TPC本身并不做审计)。TPC在全球只有不到10名审核员,全部在美国。
TPC推出过11套基准程序,分别是正在使用的TPC-App、TPC-H、TPC-C、TPC-W,过时的TPC-A、TPC-B、TPC-D和TPC-R,以及因为不被业界接受而放弃的TPC-S(Server专门测试基准程序)、TPC-E(大型企业信息服务测试基准程序)和TPC-Client/Server。而目前最为“流行”的TPC-C是在线事务处理(OLTP)的基准程序,于1992年7月完成,后被业界逐渐接受。
SPEC
智商考试,你正常的基础处理能力指标,硬盘的读取速度
- 物理处理能力
- 比较固定业务换算的指标
- 强调资源处理能力
SPEC 指标体系由 Standard Performance Evaluation Corporation(标准绩效评估公司)制定,目前主要包括针对 CPU 性能的 SPEC CPU2000(已有CPU2006,但尚无数据)、针对 Web 服务器的 SPECweb2005、针对高性能计算的 SPEC HPC2002 与 SPEC MPI2006、针对 Java 应用的 jAppServer2004 与 JBB2005 以及对图形系统、网络和邮件服务器的测试指标。
性能的难点
- 用户总希望在最小的代价下换回最大的收益
- 实际上一旦确定了架构,性能也就确定了
- 如果遵守规范体系能够达到默认架构的性能
- 大多数的开发会违背架构,拖后提
性能测试实现原理
- 模拟客户端对服务器进行多连接
- 伪造报文欺骗服务器认证机制
- 了解服务器认证机制
- 了解客户、服务器之间的交流报文结构
- 合理的技术构造报文结构
如何做性能测试
- 模拟客户端对服务端的多线程调用
- Testng 的多线程来做性能测试
- 效率低,还不支持分布式
- 工具
- 协议模拟
- 接口调用
- 协议基础
- 报文体系
- 抓包工具:浏览器 F12、fiddler
- 发包工具:Postman、curl、HttpClient
- 报文结构
- request:header、body
- response:header、body
- 报文体系
- 性能工具所要解决的问题
- 负载(并发负载用户):为什么要并发这么多用户
- 参数化:避免缓存带来的性能问题
- 关联:业务前后依赖:token、主键关键字
- 事务:通过函数来明确具体业务的时间范围
- 监控
- 监控负载:响应时间、吞吐量的监控
- 监控资源:系统资源的监控(运维)
- JVM 监控工具:jrock/jmap/jprofile
- Zabbix/ELK/Promentheus/top
- 性能测试实施
- 性能需求
- 测试方式
- 结果如何收集
- 报告如何编写
性能测试模型
理发师模型,通过理发师模型了解性能测试模型,负载与相应时间的关系,负载与吞吐量的关系,负载状态的判断
有一个理发店有 3 个 master,每个 master 理发需要 1 小时,用户最多等 2 个小时
Vuser | Wait time | Response time | TPS | Resource |
---|---|---|---|---|
1 | 0 | 1 | 1 | 1/3 |
2 | 0 | 1 | 2 | 2/3 |
3 | 0 | 1 | 3 | 1 |
4 | 1 | 2 | 3 | 1 |
5 | 1 | 2 | 3 | 1 |
6 | 1 | 2 | 3 | 1 |
7 | 2 | 3 | 3 | 1 |
8 | 2 | 3 | 3 | 1 |
9 | 2 | 3 | 3 | 1 |
正常的折线图,资源去维护队列了,没时间去处理业务,所有的系统都遵守此过程
- 做单用户的单业务串行测试
- 评估单独业务的响应时间
- 多用户的并发测试
- 了解响应时间的转折点:队列、资源不足、处理能力的峰值
- 模型结论
- 响应时间随着负载的上升先稳定后上升,并且上升越来越快
- TPS 随着负载的上升先到峰值,后稳定,然后下降
- 注意事项
- 调优思路:ABC 三点右移
- A 点加用户,响应时间开始变长的点,说明负载导致了队列产生
- B 点足够了,TPS 开始下降,说明处理能力已经不能完全占用资源
- C 点用户不接受,响应时间超过用户接受范围,响应时间超时
- 如果系统在 A 点说明负载小,在 B 点说明是系统最佳在线用户,在 C 点说明系统不能用,所以正常系统应该一直在 A 和 B 之间,最好不要超过 B,特殊情况可以在 A 和 C 之间,但不能超过 C
- 响应时间变化
- 细分请求明确每一个元素的变化情况
- 找到与响应时间同步的部分来评估定位性能瓶颈,99% 都是数据库
profile
或执行计划spotlight
性能配置测试与基准测试
- 配置测试:通过不同配置获取数据
- 基准测试:通过不同配置比较结果
性能优化
- 用自己的方式实现,基于实现为基础
- 用规范的方式实现,基于遵守规范为基础
- 用超越规范的方式实现,基于定制化规范为基础
常见优化
- 点播为广播
- 减少每一个业务的计算量
- 提高 cache 命中率
- 改 get 为 push
- 同步为异步
- 减少立即处理所带来的阻塞
- 通过队列形式来预防系统崩溃
- 实时计算为预计算
- 减少动态请求
- 可预估数据先计算
- 削减峰值
- 遵守规范:使用符合框架规范的处理机制
JMeter
- 负载:线程组
- 参数化:CSV、Data、Set、Config
- 关联:正则表达式提取器
- 事务:事务控制器
- 监控:聚合报告
创建测试
测试项目运行在虚拟机 CentOS 7 上,测试结果不具备任何价值,仅为使用 JMeter 演示。
-
添加线程组
-
配置线程组,定量长时间并发
-
添加Sampler -> HTTP请求(对jmeter不熟,可以先去postman测试接口)
-
配置 HTTP 请求
-
查看服务器响应,添加监听器 -> 查看结果树
-
查看响应时间,添加监听器 -> 聚合报告
-
运行完后查看聚合报告
-
查看长期结果,添加监听器 -> 图形结果
-
图形结果中的曲线越直则表示性能和稳定性较好
执行测试计划
1
2
3
4
# testplan/jmeter-test.jmx:测试计划文件
# testplan/result.txt:测试结果文件
# testplan/webreport:Web 报告保存路径
jmeter -n -t testplan/jmeter-test.jmx -l testplan/result.txt -e -o testplan/webreport
webreport/index.html Dashboard