48张图|手摸手教你性能监控、压测和调优

本文主要内容

一、何为压力测试

1.1、 大白话解释

  • 性能压测是什么:就是考察当前软件硬件环境下,系统所能承受的最大负荷,并帮助找出系统的瓶颈所在。

  • 性能压测的目的:为了系统在线上的处理能力稳定性维持在一个标准范围内,做到知己知彼,百战不殆。还可以发现内存泄漏、并发与同步的问题。

1.2、性能指标

  • RepsonseTime - RT:响应时间,用户从客户端发起一个请求开始计算,到客户端接收到服务端的响应结束,整个过程所耗费的时间。

  • Hits Per Second - HPS:用户每秒点击次数,也就是每秒向后台发送的请求次数。

  • QPS:系统每秒内处理查询的次数。

  • MaxRT:最大响应时间,指用户发出请求到服务端返回响应的最大时间。

  • MiniRT:最少响应时间,指用户发出请求到服务端返回响应的最少时间。

  • 90%响应时间:将所有用户的响应时间进行升序排序,取 90 % 的位置。

  • 性能测试关注点:

    • 吞吐量:每秒钟系统能处理的请求数、任务数。

    • 响应时间:服务处理一个请求或一个任务的耗时。

    • 错误率:一批请求中结果出过错的请求所占比例。

二、Jmeter 压测工具

1、Jmeter 工具

  • 下载和安装 Jmeter 工具

下载地址:

https://jmeter.apache.org/download_jmeter.cgi

我下载的版本是 apache-jmeter-5.3

  • 运行 JMeter 程序

打开批处理文件:\apache-jmeter-5.3\bin\jmeter.bat。如下图所示:

  • 添加线程组,如下图所示:

添加线程组
  • 1s 内启动 200 个线程,循环次数 100 次。2 w 个请求。如下图所示:

  • 测试 HTTP 请求,如下图所示:

配置要测试的协议、服务器地址、端口号。配置信息如下:

协议:使用 http 协议。

服务器名称或 IP: www.baidu.com (只是为了演示)。

端口号:80 端口。

如下图所示:

  • 添加查看结果树、汇总报告和聚合报告。如下图所示:

  • 开始压力测试。

    点击播放按钮就开始启动了。注意启动之前需要先设置线程组的参数配置和 HTTP 请求的配置。如下图所示:

  • 查看每个请求结果,如下图所示:

  • 查看汇总报告。

    主要关心平均值和吞吐量。

    200 个线程,每个线程调用 100 次,总共 2 w 次,可以看到下图中表格中的样本列也是 2 w,请求所耗费的时间是 151 ms,吞吐量是 880 个请求每秒。如下图所示:

  • 查看聚合报告。

主要看中位数和90%百分位,

中位数是 59 ms,说明大部分请求的响应时间是 59 ms。

90 % 的请求 都是在 271 ms 以内响应完成的。

异常 0.41% 说明 2 w 个请求中有 82 个请求异常(20000 * 0.0041 = 82 )。

吞吐量 880.2/sec 说明百度这个网站每秒能处理 880 个请求,性能一般(可能跟本地机器性能有关)。

如下图所示:

  • 查看汇总图。

查看汇总图时,需要先勾选想要查看的信息,如下图所示:

然后查看图形汇总:

可以看到勾选的几列在图表中是用不同颜色表示的,比如绿色的柱状条就是 90 % 百分位。

我们来测试下 PassJava(佳必过)的管理后台的性能,吞吐量接近 2000/s。如下图所示:

三、性能监控之 jconsole

jconsole 和 jvisualvm 是 Java JDK 的两个小工具,用来监控内存泄漏、跟踪垃圾回收、执行时的内存情况、对 CPU 进行分析、线程的分析。都可以通过命令行启动,而且可以监控本地和远程应用。而 jvisualvm 是升级版的 jconsole。我们先来看下 jconsole 的使用。

首先用 cmd 命令行的方式启动 jconsole。

启动 jconsole‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

命令行启动 jconsole

选择监控哪个应用

然后选择 passjava 项目的 question 服务。

选择 passjava-question 微服务

对应的就是下面这个微服务:passjava-question。

对应 passjava-question 微服务

概览

从监控界面上有 6 个菜单,首先看到的是概览功能,上面有堆内存使用量、线程数、类的使用情况、CPU 占用率,都是用趋势图来表示的,能很方便的看出当前性能的概览。注意:这些监控都是实时的。

概览

内存

下面是内存的使用情况,可以从下图中看到有个下拉框,里面可以选择不同的内存维度,然后下面的图标和柱状图也会跟着选择的维度而展示不同。

内存

下面是线程的使用情况,可以看到线程峰值和活动线程的总数量,目前看到的峰值是59,活动线程数是 57。下半部分可以看到具体是哪些线程,以及线程的堆栈信息,非常详细。

线程使用情况

下面是类的加载和卸载情况,已加载类总数是 10679,而已卸载的类是 1 个,所以当前已加装当前类的总数是 10679 - 1 = 10678 个。

类的加载和卸载情况

VM 概要

我们再来看下VM(虚拟机)的情况。如下图所示,可以看到虚拟机情况,线程、类、堆的概要信息,以及 VM 的参数,是不是很方便呀~

VM 概要

MBean 信息

接下来我们来看下 MBean 信息。对于 MBean,可能很多同学不知道是啥,下面做个解释:

MBean就是一种规范的JavaBean,通过集成和实现一套标准的Bean接口,这种叫MBean。MBean可以用来干嘛?就是可以有一套JDK级别的对外的服务接口。比如,你写了一个JVM允许状态辅助查询的Bean,你希望别人下载一个Jconsole就可以看到你写的杰作。那你就可以考虑用MBean规范来实现。很多垃圾收集器算法Bean就这么干的(说的就是这个类sun.management.MemoryImpl)。

MBean 信息

四、性能监控之 jvisualvm

jvisualvm 比 jconsole 更强大,界面展示的信息更丰富。还可以安装插件,太赞了。

启动 jvisualvm 和概述

启动方式和 jconsole 一样,也是通过 cmd 命令行启动。还是选择 passjava-question 微服务,然后选择第一个菜单栏:概述。可以看到 JVM 的版本,启动参数等信息。

启动jvisualvm

监视

监视 CPU、堆、类、线程的情况。整体显示的效果比 jconsole 更美观。

监视

线程

再来查下线程的情况。可以看到有 5 种状态的线程:

  • 运行:正在运行的线程。

  • 休眠:休眠状态的线程。

  • 等待:等待执行的线程。

  • 驻留:线程里面的空闲线程。

  • 监视:阻塞的线程,正在等待锁。

抽样器

另外我们也可以抽样器对 CPU 或内存进行抽样。如下图所示,对内存进行抽样。

抽样

插件的使用

安装Visual GC 插件

安装步骤:工具->插件->可用插件->Visual GC->安装。安装完成后,重启就可以使用插件功能了。

安装完成后,就可以看到

Visual GC 插件

下图是实时监控垃圾回收的情况。

Visual GC

五、对网关的性能测试

现在我想对 Passjava 系统的 question 微服务的接口进行一个压测,该如何进行呢?

首先我们来看下 passjava 的架构是怎么样的,如下图所示:

客户端分为手机端和 PC 端,http 请求先经过 API Gateway,然后再转发到 question 微服务。其中涉及到了中间件:Gateway 网关。

我们来对 Gateway 网关进行压力测试。

网关的端口号是 8060,我们配置下 JMeter。如下图所示:

配置每秒发送 200 个请求,一直循环执行,直到手动停止压测。如下图所示:

可以看下执行结果,吞吐量在 2422 个每秒,还是比较高的。

吞吐量:2422/s 。

90% 响应时间:142 毫秒。

99% 响应时间:281 毫秒。

我们再来看看垃圾回收的情况,Eden 区垃圾回收用时 2.7 s,用时太长了吧,看看这里怎么能优化下。

通常的优化方向是增大新生代堆内存配置。

六、对微服务的性能测试

根据上面的架构原理图,我们知道客户端请求都是经过 Gateway 转发了一次的,如果我们想单独看下微服务的性能该怎么测试呢?下面我来演示下如何测试 passjava-question 微服务的性能。

首先需要在 passjava-question 微服务中添加一个测试方法:

测试方法

有两种方式测试这个 api 是否添加正确。

第一种用 postman 测试下这个请求是否能正确响应,返回 “test” 则表示响应正确。

test api 是否能正确响应

第二种通过浏览器进行测试。浏览器地址栏输入以下链接后,回车,看下浏览器窗口是否显示 “test”,是则表示响应正确。

然后我们需要用 Jmeter 压测工具来测试这个微服务下的 api 的性能究竟如何。

单独压测微服务的 api的结果

吞吐量:3542/s 。

90% 响应时间:100 毫秒。

99% 响应时间:152 毫秒。

七、对网关+微服务的性能测试

如果我们想对这个整个请求链路进行性能测试该怎么做?

首先请求需要先经过网关,然后由网关转发到微服务。在之前的文章中,我已经将网关配置好了,所以要想通过网关转发到 test 请求,只需要对请求路径稍作修改即可,如下所示:

http://localhost:8060/api/question/v1/admin/question/test

然后在浏览器输入该网址,返回 “test” 即表示响应正确。

然后我们还是用 Jmeter 压测工具测试下 test api 的性能。测试结果如下图所示:

网关+微服务的压力测试结果

从结果可以看到:

吞吐量:982/s 。

90% 响应时间:437 毫秒。

99% 响应时间:790毫秒。

这里做个横向对比:

横向对比

说明微服务 api 经过网关转发一次后,性能至少下降了一半。可以得出结果:中间件越多,性能损失越大,大部分损失都是网络交互导致的。可以通过增强网络通信质量来减少网络的延迟。

八、对数据库查询进行优化

一般情况下,出现性能问题更多的是业务中查询数据库的耗时。接下来看下如何优化数据的查询。

下面是一个查询问题列表的 api:通过问题类型 type 字段过滤问题列表。api 路径如下:

http://localhost:11000/question/v1/admin/question/list?type=5

这个 api 的代码如下,很容易看懂。

查询问题列表的 api

我们加些测试代码:统计查询数据库的耗时。如下所示:

耗时统计

然后重启 passjava-question 服务,再次测试这个 api,耗时 43 ms

怎么对查询进行优化呢?很容易想到加索引,我们来试下加在 question 表加索引后的效果。给 type 字段加上普通索引,如下图所示:

添加索引

我们再来看下加了索引后的耗时情况:耗时 18 ms,确实比之前的 43 ms 快了很多。

加了索引后的情况

九、优化垃圾回收

我们可以通过 jvisulavm工具查看垃圾回收的情况,Eden 区频繁发生 GC,短时间(1分钟)内共造成了 480 次 stop the world。另外从压测工具中也可以看到,吞吐量为 275/s。

原因是 Eden 区的内存分配得太小了,只有 32 M,我们来调大一点。

32M Eden 区频繁进行垃圾回收

增大 Eden 区大小

通过在 IDEA 工具中配置以下参数,调整堆内存最大为 1024 M,新生代内存为 512 M。

-Xmx1024m -Xms1024m -Xmn512m

然后可以观察到在相当长的短时间(1分钟)内只进行了 92 次垃圾回收,说明垃圾回收的频率降低了。应用程序的性能也提升了。另外从压测工具中也可以看到,吞吐量为 347/s,吞吐量也有较大提升。

十、总结

本文通过压测工具 Jmeter 讲解压测如何实施,然后用性能监控工具 jconsole 和 jvisualvm 来监控 Java 应用程序的性能,以及如何用工具来优化开源项目 passjava 的性能,并且非常详细地介绍了每一步以及执行结果,通过对比的方式,更加清晰地知道如何做性能优化。

下面是对系统性能的常规优化手段:

  • 中间件较多时,优化网络通信质量。

  • 数据库查询耗时时,需要对查询进行优化,比如添加索引。

  • 模板的渲染速度,可以通过设置模板缓存。

  • 静态资源的获取,可以通过 Nginx 动静分离来解决。(下期再讲)

  • 日志太多,需要减少不必要的打 log 操作。

巨人的肩膀:

https://blog.csdn.net/u010833547/article/details/92806510
https://www.bilibili.com/video/BV1np4y1C7Yf
https://github.com/Jackson0714/PassJava-Platform
www.passjava.cn

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/544747.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java中intvalue_Java Float类intValue()方法与示例

java中intvalue浮动类intValue()方法 (Float class intValue() method) intValue() method is available in java.lang package. intValue()方法在java.lang包中可用。 intValue() method is used to return the value denoted by this Float object converted to type int (by…

JTable demo

简单讲就是在没有使用layout manager的时候用setSize,在使用了layout manager 的时候用setPreferredSize 并且setPreferredSize通常和setMinimumSize、setMaximumSize联系起来使用setSize()是你手动来设置组件的大小 Dimension 类封装单个对象中组件的宽度和高度&am…

C#操作Cookie

简单的存储Cookie和获取Cookie例子 public string SaveCookie(string name) {// 登陆成功要将必要数据存储到 Cookie 里HttpCookie httpCookie new HttpCookie("cookie");// 设置过期时间httpCookie.Expires DateTime.Now.AddHours(1);// 设置姓名httpCookie.Valu…

Java生成随机数的4种方式,以后就用它了!

作者 | 王磊来源 | Java中文社群(ID:javacn666)转载请联系授权(微信ID:GG_Stone)在 Java 中,生成随机数的场景有很多,所以本文我们就来盘点一下 4 种生成随机数的方式,以…

Java LinkedList addFirst()方法与示例

LinkedList addFirst()方法 (LinkedList addFirst() method) This method is available in package java.util.LinkedList. 软件包java.util.LinkedList中提供了此方法。 This method is used to insert an object at the initial or beginning stage of the linked list. 此方…

二层冗余网络引起的问题

1.广播风暴 环路会引起广播风暴 网络中主机会收到重复数据帧 2.MAC地址表震荡 环路引起的MAC地址表震荡,交换机死机 3.有可能收到重复的流量转载于:https://www.cnblogs.com/hotshotgg/p/4537817.html

Everything是如何搜索的

写在前面 使用了Everything之后,一直对他的搜索速度感兴趣,在网上也看了很多对其原理的揭秘,终于有空找了个源码研究了一下,原理就是对NTFS的USN特性进行使用。 原理 详细解释我参照别人家的博客来一段: 当扇区的文…

漫话:如何给女朋友解释String对象是不可变的?

String的不变性String在Java中特别常用&#xff0c;相信很多人都看过他的源码&#xff0c;在JDK中&#xff0c;关于String的类声明是这样的&#xff1a;public final class String implements java.io.Serializable, Comparable<String>, CharSequence { }可以看到&#…

XenServer 6.5实战系列之十一:Install Update For XenServer 6.5

为了保证XenServer主机的安全及功能的更新&#xff0c;在企业环境中我们需要定期的到Citrix官网或通过XenCenter进行下载和更新。今天我们会从在线和离线两种不同的方法进行Update的安装。更新补丁之前请务必阅读对应Update的相关资料、注意事项和做好备份。1. 离线安装更新在…

机器学习 属性_属性关系文件格式| 机器学习

机器学习 属性Today, we will be looking at the use of attribute relation file format for machine learning in java and we would be writing a small java code to convert the popularly used .csv file format into the arff (Attribute relation file format). This f…

C#标记废弃方法

一、普通用法 在C#中&#xff0c;如果一个方法我们不再使用&#xff0c;我们可以将其标记为“废弃”的方法&#xff0c;只需要在方法前&#xff0c;加一个[Obsolete]即可&#xff1b; [Obsolete] public void BiuBiuBiu(){// 嘿嘿嘿 }废弃方法并非不能使用&#xff0c;而是在…

阿里二面一问MySQL就开始野了,抓着底层原理不撒手啊!

最近项目增加&#xff0c;缺人手&#xff0c;面试不少&#xff0c;但匹配的人少的可怜。跟其他组的面试官聊&#xff0c;他也抱怨了一番&#xff0c;说候选人有点儿花拳绣腿&#xff0c;回答问题不落地&#xff0c;拿面试最常问的MySQL来说&#xff0c;并不只是懂“增删改查”、…

[转]“Ceph浅析”系列之(—)—Ceph概况

转载自&#xff1a;http://yizhaolingyan.net/?p11本文将对Ceph的基本情况进行概要介绍&#xff0c;以期读者能够在不涉及技术细节的情况下对Ceph建立一个初步印象。2.1 什么是Ceph&#xff1f;Ceph的官方网站Ceph.com上用如下这句话简明扼要地定义了Ceph&#xff1a;“Ceph…

关于C#监视剪贴板信息

##1、常规方法 在C#中&#xff0c;有一个常规检测剪贴板的方法&#xff0c;用的是 System.Windows.Forms.Clipboard&#xff1b; 使用起来很简单&#xff0c;代码如下&#xff1a; /// <summary> /// 设置剪贴板的文本内容 /// </summary> /// <param name&qu…

图解Java中的18 把锁!

乐观锁和悲观锁独占锁和共享锁互斥锁和读写锁公平锁和非公平锁可重入锁自旋锁分段锁锁升级&#xff08;无锁|偏向锁|轻量级锁|重量级锁&#xff09;锁优化技术&#xff08;锁粗化、锁消除&#xff09;乐观锁和悲观锁悲观锁悲观锁对应于生活中悲观的人&#xff0c;悲观的人总是想…

在CSS中使用not:first-child选择器

Introduction: 介绍&#xff1a; Well, selectors are a very common term to deal with while we are developing a website or web page. You might know quite a few of them and might as well be implementing them. You might also have noticed that all the selectors…

linux/unix 段错误捕获【续】

本文为“在C/C中捕获段错误&#xff0c;打印出错的具体位置”的续篇&#xff0c;进一步解决涉及动态链接库的情况。背景知识&#xff1a;linux/unix下动态链接库的基本原理/proc/pid/maps文件的基本格式动态链接库&#xff1a;在进程执行过程中动态加载&#xff0c;进程间可以共…

C#获取屏幕大小的“简单整理”。。

额…… 首先是有一个需求&#xff0c;两个显示器&#xff0c;程序自动获取自己所在的显示器大小&#xff0c;并显示到右下角。 我们都知道C#有一个Screen.PrimaryScreen.Bounds&#xff0c;可以获取屏幕的完整尺寸&#xff0c;但是只能获取主显示器的尺寸&#xff0c;后来我发…

Spring为什么建议构造器注入?

来源 | juejin.cn/post/6844904056230690824作者 | Richard_Yi本文的内容主要是想探讨我们在进行 Spring 开发过程当中&#xff0c;关于依赖注入的几个知识点&#xff0c;具体内容如下&#xff1a;Autowired, Resource, Inject 三个注解的区别当你在使用Autowired时&#xff0…

c#中的long类型示例_C#中带示例的带符号字节数组

c#中的long类型示例C&#xff03;中的有符号字节数组 (Signed Byte Array in C#) In C#.Net, we can create a signed byte array by using sbyte, sbyte is used to store both of the values (negative and positive) between the range of -128 to 127 (Signed 8 bits integ…