TypechoJoeTheme

Clover 的博客

统计
登录
用户名
密码
/
注册
用户名
邮箱

CloverYou

日出于东却落于西,相识人海却散于席。

性能与压力测试

2022-01-02
/
0 评论
/
29 阅读
/
正在检测是否收录...
01/02

压力测试

压力测试可以考察但前硬件环境下系统所能承受的最大负荷并帮助找出系统瓶颈所在。压测都是为了系统在线上的处理能力和稳定性维持在一个标准范围内。

使用压力测试,我们希望找到很多种用其它测试方法更难发现的错误。有两种错误类型,它们分别是:

  • 内存泄漏
  • 并发同步

有效的压力测试系统将应用以下这些关键条件:重复、并发、量级、随机变化

性能指标

  • 响应时间(Response Time:RT)

响应时间指,用户从客户端发起一个请求开始,到客户端接收到从服务端返回的响应结束,整个过程所消耗的时间。

  • HPS(Hits Per Second):每秒的点击数,单位是次/秒
  • TPS(Transaction Per Second):系统每秒处理交易数,单位是笔/秒
  • QPS(Query Per Second):系统每秒处理查询次数,单位是次/秒。

对于互联网业务中,如果某些业务有且仅有一个请求连接,那么 TPS=QPS=HPS,一般情况下用 TPS 来衡量整个业务流程,用 QPS 来衡量接口查询次数,用 HPS 来表示对服务器点击请求。

  • 无论 TPS、QPS、HPS,此指标是衡量系统处理能力非常重要的指标,越大越好,一般情况下:

    1. 金融行业:1000TPS~50000TPS,不包括互联网化的活动
    2. 保险行业:100TPS~100000TPS,不包括互联网化的活动
    3. 制造行业:10TPS~5000TPS
    4. 互联网电子商务:10000TPS~1000000TPS
    5. 互联网中型网站:1000TPS~50000TPS
    6. 互联网小型网站:500TPS~10000TPS
  • 最大响应时间(MAX Response Time)指用户发出请求或者指令到系统做出反应(响应)的最大时间。
  • 最少响应时间(Minimum Responsen Time)指用户发出请求或指令到系统做出反应(响应)的最少时间。
  • 90%响应时间(90% Response Time)是指所有用户的响应时间进行排序,第90%的响应时间。
  • 从外部看,性能测试主要关注如下三个指标

    1. 吞吐量:每秒钟系统能够处理的请求数、任务数
    2. 响应时间:服务处理一个请求或一个任务的耗时
    3. 错误率:一批请求中结果出错的请求所占比例

JMeter

使用 jmeter 做压力测试。使用它需要有 java 环境,因为它是使用java开发的。

安装

官网下载,JMeter官网网址:https://jmeter.apache.org

点击左侧菜单的 Download Releases

找到 Binaries 这一栏,点击下图标出来的地方就可以下载

解压后双击 jmeter.sh,如果是windows就打开jmeter.bat

apache 已经做好了国际化工作,如果需要切换语言可以到 Choose Language 中切换

使用

新建一个测试计划

模拟有多少用户来请求某个指定接口,用来测试该接口的性能。右键测试计划,添加 ===>> 线程 ===>> 线程组

创建200个用户,一共发送2w个请求的现场组

  • 线程数:模拟用户数
  • Ramp-Up时间:指定时间内将现场创建完成
  • 循环次数:每个线程发送多少次请求

添加一个取样器,选择我们当前需要进行的测试类型

例如我们对百度发起压力测试

  • 协议:我们要进行测试的协议,http或者https
  • 服务器名称或IP:需要进行测试的目标服务器地址
  • 端口:对哪个端口发起请求
  • 路径:如果需要对指定服务器下的某个地址进行测试,可以在这指定

如果测试完后需要看测试指标,还需要添加一个结果树监听器

再添加一个汇总报告 ,里面有很多种指标可以供我们参考

全部设置好后点执行就可以

结果分析

  • 有错误率同开发确认,确定是否允许错误的发生或者错误率允许在多大的范围内;
  • Throughput 吞吐量每秒请求的数大于并发数,则可以慢慢的往上面增加;若在压测的机
    器性能很好的情况下,出现吞吐量小于并发数,说明并发数不能再增加了,可以慢慢的

往下减,找到最佳的并发数;

  • 压测结束,登陆相应的 web 服务器查看 CPU 等性能指标,进行数据的分析;
  • 最大的 tps,不断的增加并发数,加到 tps 达到一定值开始出现下降,那么那个值就是
    最大的 tps。
  • 最大的并发数:最大的并发数和最大的 tps 是不同的概率,一般不断增加并发数,达到
    一个值后,服务器出现请求超时,则可认为该值为最大的并发数。
  • 压测过程出现性能瓶颈,若压力机任务管理器查看到的 cpu、网络和 cpu 都正常,未达到 90%以上,则可以说明服务器有问题,压力机没有问题。
  • 影响性能考虑点包括:
    数据库、应用程序、中间件(tomact、Nginx)、网络和操作系统等方面
  • 首先考虑自己的应用属于 CPU 密集型还是 IO 密集型

性能监控

  • 程序计数器 Program Counter Register

    • 记录的是正在执行的虚拟机字节码指令的地址
    • 此内存区域是唯一一个在JAVA虚拟机规范中没有规定任何 OutOfMemoryError 的区域
  • 虚拟机 VM Stack

    • 描述的是 Java 方法执行的内存模型,每个方法在执行的时候都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法接口等信息。
    • 局部变量表存储了编译期可知的各种基本数据类型、对象引用
    • 线程请求的栈深度不够会报 StackOverflowError 异常
    • 栈动态扩展的容量不够会报 OutOfMemoryError 异常
    • 虚拟机栈是线程隔离的,即每个线程都有自己独立的虚拟机栈
  • 本地方法:Native Stack

    • 本地方法栈类似于虚拟机栈,只不过本地方法栈使用的是本地方法
  • 堆:Heap

    • 几乎所有的对象实例都在堆上分配内存

所有的对象实例以及数组都要在堆上分配,堆事垃圾收集器管理的主要区域,也被称为 “GC堆” 。也是我们优化考虑的地方

堆可以细分为:

  • 新生代

    • Eden 空间
    • From Survivor 空间
    • To Suvivor 空间
  • 老年代
  • 永久代/元空间(< JDK1.8)

    • Java8 以前永久代,受 jvm 管理,java8以后元空间,直接使用物理内存,因此,默认情况下,元空间的大小仅受本地内存限制。

垃圾回收

创建对象,首先会在新生代分配内存。检查 Eden 元区能不能放下当前对象,如果放得下就放,放不下则进行一次minorGC,这次GC主要清理新生代空间,这个GC非常快。如果GC后 Eden 元区还存在对象,那么会将这些对象放到幸存者区,如果幸存者区也没有内存,那么会将幸存者区中达到阈值的对象放到老年代区(每次GC都会刷新阈值,类似版本迭代)。GC之后再检查,如果还是放不下那么当前对象会被视为大对象,尝试将其放到老年代。老年代如果能放下那么会直接分配内存,如果放不下,则会进行一次 FULL GC ,这是一次全面GC,耗时非常久。如果老年代也放不下,那么会报内存溢出异常 OutOfMemoryError

jconsole与jvisualvm

JDK 提供的两个小工具 jconsole、jvisualvm(升级版的jconsole)。通过命令行启动,可监控本地和远程应用。

在控制台中输入 jconsole 打开 jconsole 控制台。选择指定服务,然后连接

可以查看程序的各种详情信息

jvisualvm

jvisualvm 可以监控内存泄漏、跟踪垃圾回收、执行内存、CPU分析、线程分析等工作。通过 jvisualvm 命令打开 jvisualvm 控制台

安装插件

在菜单栏中点击工具===>>插件

选择对应的差距,然后点安装即可,这个 Visual GC 插件是用来监视垃圾回收的,安装完后重启 jvisualvm

性能压测

由于微服务请求是一层一层往下传递:

在真正功能执行之前,请求需要经过许多中间件,需要测试中间件对性能到底有没有影响

以下数据测试有误,以表格为准

nginx

添加一个对nginx测试的配置,循环数设置为永远,因为我们需要持续不断的监控性能指标

我nginx是在linux中的docker中安装,可以使用 docker stats 命令监控CPU使用率、内存等信息

经过测试,发现nginx对CPU占用率极高,因为它不需要处理什么业务,所有请求都是交由别人来处理,需要的是更多的线程去处理并发。

网关

单独对网关进行压测

其实网关和nginx一样,都是自身没什么业务,对并发要求极高

简单服务

没有任何中间件,直接请求接口(原生)

@ResponseBody
@GetMapping("/hello")
public String hello() {
  return "hello world";
}

网关+简单服务

修改网关配置,让网关直接转发到指定服务

spring:
  application:
    name: gulimall-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 172.16.34.128:8848
    gateway:
      routes:        
                - id: product_route
          uri: lb://gulimall-product
          predicates:
            - Path=/api/product/**,/hello
          filters:
            - RewritePath=/api/(?<path>.*),/$\{path}

页面全量数据

在测试页面的时候,默认情况下只是发送请求到服务器返回页面html的时间,并不包括页面中的脚本、图片等资源。如果需要测全量数据,可以在取样器中配置,如:

中间件指标

  • 当前正在运行的线程数不能超过设定的最大值,一般情况下系统性能较好的情况下,线程数最小值设置50,最大值设置200比较合适
  • 但前运行的JDBC连接数不能超过设定的最大值,一般情况下系统性能较好的情况下,JDBC 最小值设置50和最大值设置200比较合适
  • GC 频率不能频繁,特别是 FULL GC 频率更不能频繁,一般情况下系统性能较好的情况下, JVM 最小堆大小和最大堆大小分别设置 1024M 比较合适
  • 中间件越多,性能损失越大,大多都损失在网络交互
  • 业务

    • 数据库(MySQL优化)
    • 模板的渲染速度(打开缓存)
    • 静态资源

数据库指标

  • SQL 耗时越少越好,一般情况下微妙级别
  • 命中率越高越好,一般情况下不能低于 95%
  • 锁等待次数越低越好,等待时间越短越好

压测与优化结果

虚拟机2核3G

压测内容压测线程数吞吐量/s90%响应时间99%响应时间
Nginx5057641171
网关502165738
简单服务503769823
网关+简单服务5010886822
全链路(简单)50270344772
首页50750(db、thymeleaf)91151
首页(打开模板缓存)5098066115
首页(打开模板缓存、日志级别debug -> error)5011825288
首页全量数据(全链路)502(db、thymeleaf、资源)2546036744
首页全量数据(全链路,动静分离)5061085413073
三级分类获取5020(频繁gc、db)31723463
三级分类获取(优化数据库加索引)502719902092
三级分类获取(优化查询数据库业务代码)5024011682

如果GC过于频繁,可以适当的调整内存

-Xmx1024m 最大占用内存

-Xms1024m 初始内存

-Xmn512m 新生代内存

JAVA随笔
朗读
赞(0)
版权属于:

Clover 的博客

本文链接:

https://www.ctong.top/index.php/archives/73/(转载时请注明本文出处及文章链接)

评论 (0)
CloverYou
日出于东却落于西,相识人海却散于席。
88 文章数
11 评论量
IP信息

人生倒计时

今日已经过去小时
这周已经过去
本月已经过去
今年已经过去个月

最新回复

  1. 缓存一致性 - 点击领取
    2022-01-06
  2. 宝宝
    2022-01-02

标签云