压力测试
在浅谈性能优化之前呢,先介绍一下压力测试。项目在上生产环境之前呢,需要先进行压力测试,模拟并发,看看系统的吞吐量大概是多少,告知运维人员的系统吞吐量瓶颈,与实际业务场景对比,再决定是否继续优化业务逻辑,升级硬件环境。
概念
压力测试考察当前软硬件系统的最大负荷以及瓶颈所在,是为了系统在线上的处理能力和稳定性维持在一个合理范围内,做到心中有数。
错误类型
内存泄漏
比如一个接口我们写好,在一个循环内大量创建对象,没有复用对象,当并发量一上来,我们的对象就会不断的进行创建,以至于导致我们的内存泄漏。
并发和同步
当我们单线程跑起来没有问题,当我们的并发量一上来,就会出现各种线程不安全的情况。
压力测试的性能指标
当我们单线程跑起来没有问题,当我们的并发量一上来,就会出现各种线程不安全的情况。
压力测试的性能指标
- 响应时间(response time: RT)
- HPS(hits per Second):每秒的点击数;
- TPS(transaction per second):系统每秒处理的交易数(一个完整接口下的业务链条)
- QPS(query per second):系统每秒处理的查询次数
金融行业 :1000TPS-50000TPS:不包括互联网化的活动,5万
保险行业:100TPS-100000TPS:不包括互联网化的活动,10万
制造行业:10TPS-5000TPS,5K
互联网电子商务:10000TPS-1000000TPS,100w
互联网中型网站:1000-5wTPS
互联网小型网站:500-1wTPS
最大响应时间:我们测试了100w的请求,其中有个请求响应时间为90s;
从外部看,性能测试主要关注如下三个指标
- 吞吐量:每秒系统能处理的请求数和任务数(qps和tps)
- 响应时间:服务处理一个请求或者是一个任务的耗时
- 错误率:一批请求中结果出错的请求所占的比例
压力测试工具-JMeter
压力测试吞吐量比较小,我们可以调整JVM内存
windows端口占用报错及其解决方式:
影响web性能的主要因素
数据库
应用程序
中间件(tomcat、nginx、gateway网关)
网络IO(当前网速慢,或是服务器压力大,或是当前带宽只有1M--10000请求,每个请求1KB的数据=10MB,会受带宽影响)
操作系统(不同系统,内核不同,处理方式不同)等方面。
影响性能的因素分类
首先考虑自己的应用属于CPU密集型(大量计算排序)还是IO密集型(网络IO和磁盘读写IO);
看监控:cpu和io和内存和网络流量的占用情况;
如果是CPU密集型:升级服务器硬件| 增加服务器台数
如果是IO密集型:换固态硬盘+内存条+使用缓存技术+提高网卡传输效率,单纯加cpu无法解决问题。
性能的监控与分析
java的内存模型分析
程序计数器:Program Counter Register
·记录的是正在执行的虚拟机字节码的指令地址;
·此内存区域是唯一一个在JAVA虚拟机规范中没有规定任何OutOfMemeoryError的区域。
虚拟机栈:VM Stack
·描述的是JAVA方法执行的内存模型,每个方法在执行的时候都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法接口等信息。
·局部变量表存储了编译器可知的各种基本数据类型,对象引用。
·线程请求的栈深度不够会报StackOverFlowError异常。
·栈动态扩展的容量不够会报OutOfMemeoryError异常。
·虚拟机栈是线程隔离的,即每个线程都有自己独立的虚拟机栈。
本地方法栈:Native Stack
本地方法栈类似于虚拟机栈,只不过本地方法栈使用的是本地方法。
堆:Heap
几乎所有的对象实例及数组都在堆上分配内存;堆是垃圾收集器管理的主要区域,也被成为“GC”堆,也是我们优化最多考虑的地方。
关于堆内存回收流程
所有对象实例以及数组都要在堆上分配。堆是垃圾回收器的主要区域,也被成为GC堆,也是我们优化最多的地方。JVM使用C语言写的,可以开辟空间,释放内存很麻烦。基于C再封装,写了个执行引擎,去来翻译写的java代码。
堆可以细分为
- 新生代
- Eden空间:新分配的对象到了eden区,先看看内存够不够,如果够呢,就直接分配内存;如果不够,就要进行一次GC,(进行一次young GC,也叫MinorGC,主要进行清理新生代的空间,eden里边存了10个对象,一个对象在用,其余9个对象不再用了,就把这9个踢出来,这一个对象呢我们还会把它放到幸存者区域里边。如果minorGC之后还放不下呢,我们呢就认为这个对象就是个大对象,我们尝试呢把它放到老年代-->老年代就是我们新生代无法进行处理的情况下才进入老年代的。如果老年代还是放不下呢,那么我们就要进行一次fullGC,大屠杀,把新生代和老年代所有区域的数据,如果没有用处了,全部都踢出去,踢出去以后呢,如果还放不下,那么就报错内存溢出了。oom-outofmemory内存溢出 )如果幸存者区域的的对象存活时间超过了阈值(小屠杀了十几次都还活着),就把他搬家到老年区。
- from suivivor空间【s0】
- to sruvivor空间【s1】
- 老年代
- 永久代/元空间
java8以前永久代,受jvm管理,java8以后改为了元空间,直接使用物理内存。因此,默认情况下,元空间的大小仅仅受本地内存限制。
利用java内存监控工具进行调优
jconsole与jvisualvm
jvisualvm能干什么
监控内存泄漏,跟踪垃圾回收,执行时内存,cpu分析,线程分析等。
线程的状态
运行:正在运行的;
休眠:sleep
等待:wait
驻留:线程池里边的空闲线程
监视:阻塞的线程,正在等待锁
监控所有docker容器的cpu使用率 docker stats
由上图可以看出,nginx比较浪费cpu;
JMeter模拟分析并发请求
中间件越多,性能损耗越大,大多都损失在中间件之间的网络交互了。
- 先让中间件本身的吞吐量进行提高
- 中间件之间的传输效率进行提高(网线,网卡,传输协议)
业务:
db:MYSQL优化
模板的渲染速度(thymeleaf的缓存开启,CPU,内存)
Nginx的动静分离
总结下提高性能的方法:
- 开启thymeleaf的缓存(开发时要关闭,运行时要开启)
- 关闭服务器日志(不建议用)
- nginx进行动静分离
- 数据库加索引
- 减少数据库交互(把数据全部请求过来再用java进行处理)【优化业务】
- 提高内存,jvm的新生代调大等
- 加缓存
下一篇:
引入redis缓存出现的问题以及解决方式
标签:web,请求,对象,虚拟机,线程,内存,测试,优化,浅谈 From: https://blog.51cto.com/u_15890333/5883995