知识梳理
- 一、性能压测的基本指标
-
- 1. 基本概念
- 2. 性能压测工具JMeter
-
- 2.1 JMeter的下载与启动
- 2.2 JMeter的使用
-
- 2.2.1 添加线程组
- 2.2.2 测试HTTP请求
- 2.2.3 指标查看
- 2.2.4 进行压测
- 2.2.4 Windows下JMeter的BUG解决
- 2.3 jvisualvm的使用(jconsole基本不用了,所以就不说了)
-
- 2.3.1 jvisualvm的启动与基本使用
- 2.3.1 jvisualvm的GC插件安装
- 二、CompletableFuture异步编排
-
- 1. 启动异步任务
-
- 1.1 四种方式
- 1.2 举例说明
-
- 1.2.1 方式二
- 1.2.2 方式四
- 2. 完成时感知
-
- 2.1 四种方式
- 2.2 举例
-
- 2.2.1 whenComplete
- 2.2.2 exceptionally
- 3. 完成时处理
-
- 3.1 三种方式
- 3.2 举例
- 4. 线程串行化
-
- 4.1 九种方式
- 4.2 举例
-
- 4.2.1 thenrun
- 4.2.2 thenAccept
- 4.2.3 thenApply
- 5. 两任务组(一)
-
- 5.1 九种方式
- 5.2 举例
-
- 5.2.1 runAfterBothAsync
- 5.2.2 thenAcceptBothAsync
- 5.2.3 thenACombineAsync
- 6. 两任务组合(二)
-
- 6.1 九种方式
- 6.2 举例
-
- 6.2.1 runAfterEitherAsync
- 6.2.2 acceptEitherAsync
- 6.2.3 applyToEitherAsync
- 7. 多任务组合
-
- 7.1 两种方式
- 7.2 举例
-
- 7.2.1 allof
- 7.2.2 anyof
- 三、定时任务
-
- 1 cron表达式
-
- 1.1 基本语法
- 1.2 通配符
- 2 SpringBoot整合定时任务
-
- 2.1 整合步骤
- 2.2 SpringBoot和其他定时任务框架的区别
一、性能压测的基本指标
1. 基本概念
- 响应时间(Response Time: RT):响应时间指用户从客户端发起一个请求开始,到客户端接收到从服务器端返回的响应结束,整个过程所耗费的时间。
- HPS(Hits Per Second):每秒点击次数,单位是次/秒。
- TPS(Transaction per Second):系统每秒处理交易数,单位是笔/秒。
- QPS(Query per Second):系统每秒处理查询次数,单位是次/秒。
- 最大响应时间(Max Response Time) 指用户发出请求或者指令到系统做出反应(响应)的最大时间。
- 最少响应时间(Mininum ResponseTime) 指用户发出请求或者指令到系统做出反应(响应)的最少时间。
- 90%响应时间(90% Response Time) 是指所有用户的响应时间进行排序,第 90%的响应时间。
从外部看,性能测试主要关注如下三个指标:① 吞吐量:每秒钟系统能够处理的请求数、任务数。② 响应时间:服务处理一个请求或一个任务的耗时。③ 错误率:一批请求中结果出错的请求所占比例。
2. 性能压测工具JMeter
2.1 JMeter的下载与启动
进入官网:https://jmeter.apache.org/download_jmeter.cgi进行下载。
点击jmeter.bat启动JMeter。
2.2 JMeter的使用
2.2.1 添加线程组
- 线程数:虚拟用户数。一个虚拟用户占用一个进程或线程。设置多少虚拟用户数在这里也就是设置多少个线程数。
- Ramp-Up Period(in seconds)准备时长:设置的虚拟用户数需要多长时间全部启动。如果线程数为10,准备时长为2,那么需要2秒钟启动10个线程,也就是每秒钟启动5个线程。
- 循环次数:每个线程发送请求的次数。如果线程数为10,循环次数为100,那么每个线程发送100次请求。总请求数为10*100=1000 。如果勾选了“永远”,那么所有线程会一直发送请求,一到选择停止运行脚本。
2.2.2 测试HTTP请求
2.2.3 指标查看
2.2.4 进行压测
先清空全部,再进行测试。
2.2.4 Windows下JMeter的BUG解决
- 问题:Windows本身提供的端口访问机制会引发一定的问题,由于Windows提供给TCP/IP链接的端口为1024-5000,并且要四分钟来循环回收他们,这就导致我们在短时间内跑大量的请求时会将端口占满。
-
解决:
① windows+r中,用regedit命令打开注册表。
② 找到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters。
③ 右击parameters,添加一个新的DWORD,名字为MaxUserPort。双击该DWORD,输入数值数据为65534,基数选择十进制。
④ 右击parameters,添加一个新的DWORD,名字为TCPTimedWaitDelay。双击该DWORD,输入数值数据为30,基数选择十进制。
⑤ 修改配置完毕之后记得重启机器才会生效。
2.3 jvisualvm的使用(jconsole基本不用了,所以就不说了)
2.3.1 jvisualvm的启动与基本使用
cmd窗口中,直接输入jvisualvm即可。
想要对哪个进程进行分析,直接双击该进程即可。
2.3.1 jvisualvm的GC插件安装
点击插件。
找到Visual GC,点击安装,不断下一步,直到完成即可。
重启jvisualvm即可。
二、CompletableFuture异步编排
1. 启动异步任务
1.1 四种方式
1.方式一:运行指定的Runnable线程(无返回值)
2.方式二:在指定线程池中运行指定的Runnable线程(无返回值)
3.方式三:执行指定的异步任务(有返回值)
4.方式四:在指定线程池中执行指定的异步任务(有返回值)
1.2 举例说明
1.2.1 方式二
1.2.2 方式四
2. 完成时感知
2.1 四种方式
1.whenComplete:执行完当前任务后,使用执行当前任务的线程继续处理正常和异常的计算结果,但不可返回,lambda表达式参数为结果和发生的异常。
2.whenCompleteAsync:执行完当前任务后,将后续处理提交给线程池来处理正常和异常的计算结果,但不可返回,lambda表达式参数为结果和发生的异常。
3.exceptionally:lambda表达式参数为发生的异常,可以捕获异常并进行相应的处理并返回。
4.注解:方法不以Async结尾,意味着Action使用相同的线程执行,而Async可能会使用其他线程执行(如果是使用相同的线程池,也可能会被同一个线程选中执行)。
2.2 举例
2.2.1 whenComplete
2.2.2 exceptionally
3. 完成时处理
3.1 三种方式
lambda表达式参数为结果和发生的异常,可以对结果和异常进行处理,并根据需求决定如何返回。
3.2 举例
4. 线程串行化
4.1 九种方式
1.thenRun方法:只要上面的任务执行完成,就开始执行thenRun,只是处理完任务后,执行thenRun的后续操作。
2.thenAccept方法:消费处理结果。接收任务的处理结果,并消费处理,无返回结果,lambda表达式参数为上一个任务的处理结果。
3.thenApply方法:当一个线程依赖另一个线程时,获取上一个任务返回的结果,并返回当前任务的返回值,lambda表达式参数为上一个任务的处理结果。
4.2 举例
4.2.1 thenrun
4.2.2 thenAccept
4.2.3 thenApply
5. 两任务组(一)
5.1 九种方式
两个任务必须都完成,才触发该任务:
1.runAfterBoth:组合两个future,不需要获取future的结果,只需两个future处理完任务后,处理该任务,并无返回值。
2.thenAcceptBoth:组合两个future,获取两个future任务的返回结果,然后处理任务,并无返回值。
3.thenCombine:组合两个future,获取两个future的返回结果,并返回当前任务的返回值。
5.2 举例
5.2.1 runAfterBothAsync
5.2.2 thenAcceptBothAsync
5.2.3 thenACombineAsync
6. 两任务组合(二)
6.1 九种方式
当两个任务中,任意一个future任务完成的时候,执行任务:
1.runAfterEither:两个任务有一个执行完成,不需要获取future的结果,处理任务,也没有返回值。
2.acceptEither:两个任务有一个执行完成,获取它的返回值(要求两任务返回值类型一样),处理任务,没有新的返回值。
3.applyToEither:两个任务有一个执行完成,获取它的返回值(要求两任务返回值类型一样),处理任务并有新的返回值。
6.2 举例
6.2.1 runAfterEitherAsync
6.2.2 acceptEitherAsync
6.2.3 applyToEitherAsync
7. 多任务组合
7.1 两种方式
1.allOf:等待所有任务完成。
2.anyOf:只要有一个任务完成。
7.2 举例
7.2.1 allof
7.2.2 anyof
三、定时任务
1 cron表达式
1.1 基本语法
- 基本语法:秒 分 时 日 月 周 年
1.2 通配符
-
:枚举,比如(cron=“7,9,23 * * * * ?”)表示任意时刻的7、9、23秒启动这个任务。,
-
:范围,比如(cron=“7-20 * * * * ?”)表示任意时刻的7-20秒之间,每秒启动一次。-
-
:任意,表示指定位置的任意时刻都可以。*
-
:步长,比如(cron=“7/5 * * * * ?”)表示第7秒启动,每5秒一次;再比如(cron=“*/5 * * * * ?”)表示任意秒启动,每5秒一次。/
-
?
:出现在日和周几的位置,用来防止日和周冲突,在周和日上如果要写通配符使
用
,比如(cron=“* * * 1 * ?”)表示每月的1号(无论周几),启动这个任务。?
-
:出现在日和周的位置,表示last即最后一个,比如(cron=“* * * ? * 3L”)表示每月的最后一个周二。L
-
:表示Work Day即工作日,比如(cron=“* * * W * ?”)表示每个月的工作日触发;再比如(cron=“* * * LW * ?”)表示每个月的最后一个工作日触发。W
-
:表示第几个,比如(cron=“* * * ? * 5#2”)表示每个月的第2个周的周四。#
2 SpringBoot整合定时任务
2.1 整合步骤
- 在定时任务类上标注注解
将其注册到容器中。@Component
- 在定时任务类上标注注解
注解,表示开启定时任务。@EnableScheduling
- 在定时任务类中的方法上标注注解
,并设置其属性@Scheduled
为cron表达式,来指定该方法的定时执行时间。cron
2.2 SpringBoot和其他定时任务框架的区别
- SpringBoot不支持cron表达式中的年的设置(cron表达式的年本身也是可选项)。
- SpringBoot的cron表达式中的周的设置中1-7代表周一到周日,而传统cron表达式1-7代表周日到周一。
- SpringBoot中的定时任务默认是阻塞的,但通常情况下,定时任务不能阻塞。对此,有三种解决方式:① 使用异步编排,利用CompletableFuture让业务以异步的方式是运行来解决定时任务的阻塞。② 使用定时任务默认会采用SpringBoot支持的定时任务线程池,其线程池中线程个数默认为1,我们可以通过修改配置文件
中的application.properties
属性将其支持的线程池的线程数调大来解决定时任务的阻塞,但是此种设置容易失效,部分版本有效。③ 采用异步任务,让定时任务异步执行,需要在定时任务类上标注注解spring.task.scheduling.pool.size
开启异步任务功能,并在定时任务方法上标注注解@EnableAsync
即可。SpringBoot默认为该任务创建并注册的的线程池核心线程数为8,最大线程数为Integer.MAX,我们需要在配置文件@Async
中修改application.properties
和spring.task.execution.pool.core-size
来进行人为更改。(普通业务逻辑也可以这样开启异步任务功能)。spring.task.execution.pool.max-size