一、性能测试
1、压测概念
1、压力测试考察当前软硬件环境下系统所能承受的最大负荷并帮助找出系统瓶颈所在。压测都是为了系统在线上的处理能力和稳定性维持在一个标准范围内,做到心中有数。
2、使用压力测试,我们有希望找到很多种用其他测试方法更难发现的错误。有两种错误类型是:内存泄漏、并发与同步
。
3、有效的压力测试系统将应用以下这些关键条件:重复、并发、量级、随机变化
。
影响性能考虑点包括:
1、数据库、应用程序、中间件(tomcat、Nginx)、网络和操作系统等方面。
2、首先要考虑自己的应用属于CPU密集型
还是IO密集型
。
2、性能指标
- 响应时间(Response Time: RT)
响应时间指用户从客户端发起一个请求开始,到客户端接收到从服务器端返回的响应结束,整个过程所耗费的时间。
- HPS (Hits Per Second) :每秒点击次数,单位是次秒。
- TPS (Transaction per Second):系統每秒处理交易数,单位是笔秒。
- QPS (Query per Second) :系统每秒处理查询次数,单位是次秒。
对于互联网业务中,如果某些业务有且仅有一个请求连接,那么TPS-QPS-HPS,一般情况下用TPS来衡量整个业务流程,用QPS来衡量接口查询次数,用HPS来表示对服务器单击请求。
- 无论TPS、QPS、HPS,此指标是衡量系统处理能力非常重要的指标,越大越好,根据经验,一般情况下:
金融行业:1000TPS-50000TPS,不包括互联网化的活动
保险行业:100TPS-100000TPS, 包括互联网化的活动
制造行业:10TPS-5000TPS
互联网电子商务:1000OTPS-1000000TPS
互联网中型网站:1000TPS-50000TPS
互联网小型网站:500TPS~1000TPS
- 最大响应时间(Max Resonse Time,指用户发出请求或者指令到系统做出反应(响应)的最大时间。
- 最少响应时间(Mininum RespanseTime)指用户发出请求或者指令到系统做出反应(响应)的最少时间。
- 90%响应时间(90% Response Time) 是指所有用户的响应时间进行排序,第90%的响应时间。
- 从外部看、性能测试主要关注如下三个指标
吞吐量:每秒钟系统能够处理的请求数、任务数。
响应时间:服务处理一个请求或一个任务的耗时。
错误率:一批请求中结果出错的请求所占比例。
3、压测软件
1、Jmeter
Jmeter官网
进入到下载页面,下载Java8版本的:
下载到本地,然后解压。
进入解压目录/bin/,如果是Windows系统,则直接点击 jmeter.bat启动即可。
命令行出现
================================================================================
Don't use GUI mode for load testing !, only for Test creation and Test debugging.
For load testing, use CLI Mode (was NON GUI):
jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder]
& increase Java Heap to meet your test requirements:
Modify current env variable HEAP="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m" in the jmeter batch file
Check : https://jmeter.apache.org/usermanual/best-practices.html
================================================================================
然后会 弹出下面的jmeter界面 :
修改中文
添加线程组模拟用户
模拟200个用户1s内启动,循环100次,即20000个请求
添加http请求
请求百度
添加查看结果树,汇总报告和聚合报告
点击执行按钮,得到测试结果
JMeter Address Already in use错误解决
Windows本身提供的端口访问机制的问题。
Windows提供给TCP/IP错接的端口为1024-5000,并且要四分钟来循环回收他们。就导致我们在短时间内跑大量的请求时将端口占落了。
1、cmd中,用regedit命令打开注册表。
2、在 HKEY LOCAL MACHINESYSTEM\CurrentControlSet\Services\Ticpip\lParameters 下。
1)右击parameters,添加一个新的DWORD.名字为MaxUserPort
2)然后双击MaxUserPort,输入数值数据为65534,基数选择十进制(如果是分布式运行的话,控制机器和负载机器都需要这样操作哦)
3)30s即回收端口 TCPTimedWaitDelay:30
3、修改配置完毕之后记得重启机器才会生效
微软帮助文档
4、堆内存与垃圾回收
1、jvm内存模型
堆
所有的对象实例以及数组都要在堆上分配,堆是垃圾收集器管理的主要区域,也被称为“GC对”;也是我们优化最多考虑的地方。
堆可以细分为:
- 新生代
- Eden空间(伊甸园区)
- From Survivor空间(幸存者区)
- To Survivor空间
- 老年区
- 永久代/元空间
JAVA堆的分类:
从内存回收的角度上看,可分为新生代(Eden空间,From Survivor空间、To Survivor空间)及老年代(Tenured Gen)。
从内存分配的角度上看,为了解决分配内存时的线程安全性问题,线程共享的JAVA堆中可能划分出多个线程私有的分配缓冲区(TLAB)。
JAVA堆可以处于物理上不连续的内存空间中,只要逻辑上是连续的即可。
可通过参数 -Xmx -Xms 来指定运行时堆内存的大小,堆内存空间不足也会抛OutOfMemoryError异常。
GC垃圾回收流程:
二、性能监控
Jdk的两个小工具 jconsole、jvisualvm(升级版的 jconsole);通过命令行启动,可监控本地和远程应用。远程应用需要配置。
jvisualvm 能干什么?
监控内存泄漏,跟踪垃圾回收,执行时内存、CPU分析、线程分析…
测试
只要安装了java环境,在cmd窗口输入jvsualvm就会弹出
线程监视名词解释:
- 运行:正在运行的
- 休眠:sleep
- 等待:wait
- 驻留:线程池里面的空闲线程
- 监视:阻塞的线程,正在等待锁
安装插件方便查看gc:
- 启动 jvisualvm
- 工具-》插件
如果报 503 错误提示,则需要更改源:
- 打开网址 https://visualvm.github.io/pluginscenters.html
- cmd 查看自己的jdk版本,找到对应的 visualVM
C:\Users\sukang>java -version
java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
我的Java版本号是:1.8.0_181,小版本号是 181, 那木就应该用对应区间的版本,即 131-231区间。
插件中心就用这个地址:
https://visualvm.github.io/uc/8u131/updates.xml.gz
更改设置中心的路径:
压测项目
Nginx服务是在虚拟机的docker上部署的,如何查看其性能呢?执行下面的命令就可以看到docker内存占用和CPU使用情况了。
docker status
Jmeter
打开Jmeter添加一个用户组:
设置线程属性:
在线程组添加取样器Http请求:
然后设置测试的HTTP相关参数,并开启线程组的监听器:
然后观察虚拟机中Nginx的统计情况:
我们可以看到 Nginx的CPU使用率非常高,占到了 90%。
然后再看我们的监听器的汇总报告:
聚合报告:
聚合报告满足符合正态分布。
三、性能优化
1、Nginx 动静分离
1、为何动静分离?
可以看到,我们项目的静态资源请求和动态请求都是经过Nginx反向代理后到我们后端的Tomcat服务器,然后再返回数据,如果请求量非常的大,则后端服务器Tomcat的压力也就非常大,经过测试发现,大多数请求都是静态资源的,所以,如果降静态资源放在Nginx下,不用再到Tomcat处理,那就可以大大减轻Tomcat的压力。
2、实施
将我们微服务项目下的静态资源放到Nginx 服务下
// 拷贝本地文件夹到Nginx远程服务器
scp -r /Users/kaiyiwang/Code/gulimall/gulimall-product/src/main/resources/static root@192.168.10.10:/mydata/nginx/html/
登录Nginx服务器,可以看到static文件夹已经上传成功了
[vagrant@localhost html]$ pwd
/mydata/nginx/html
[vagrant@localhost html]$ ls -l
total 0
drwxr-xr-x. 3 root root 19 Aug 31 06:37 static
可以看到已经上传成功了,将我们本地项目下的静态资源删掉。
替换原来模板文件 index.html 静态资源引入的路径:
href="/index/css/swiper-3.4.2.min.css"
// 替换为下边这个
href="/static/index/css/swiper-3.4.2.min.css"
修改Nginx配置文件 gulimall.conf:
[root@localhost conf.d]# cat gulimall.conf
server {
listen 80;
server_name gulimall.com;
#charset koi8-r;
#access_log /var/log/nginx/log/host.access.log main;
# 如果路径包含static,则直接访问nginx/html的静态路径资源,其余走proxy_pass代理
location /static/ {
root /usr/share/nginx/html;
}
location / {
#proxy_pass http://192.168.10.1:10000;
proxy_set_header Host $host;
proxy_pass http://gulimall; #use nginx.conf upstream load balancing
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
然后重启Nginx
docker restart nginx
访问商城gulimall.com:
可以看到我们的商城项目的静态资源已经可以成功地从Nginx访问了。