webFlux和MVC的区别
Spring WebFlux 是一个无阻塞的Web 框架,它能够充分利用多核CPU 的硬件资源去处理大量的并发请求
Spring MVC 构建于Servlet API 之上,使用的是同步阻塞式I/O 模型,每一个请求对应一个线程去处理。
阅读全文…
分类存档: 工具
springflux的初步体验
作者: inter12
日期: 8 四月, 2021
没有评论 | 3,176 views
基于Junit的几个性能压测工具
作者: inter12
日期: 10 六月, 2020
没有评论 | 3,297 views
最近新写了一基于phoneix存储的系统,想做一下接口的压力测试
简单搜索了一下相关开源组件,找了几个不错的组件,都是基于junit整合的。ps: 搞Java的好处就是先去github找一下是否有成熟的组件,自己写太累,也不完善。
先说结论:如果你的框架没有强制依赖guava的话,那么选哪个都可以,如果强制依赖了guava的话,那么用com.github.javatlacati » contiperf
目前找了几个 :
junitperf » junitperf。最近一直更新已经是2005年了,应该早不维护了。
com.github.noconnor » junitperf : 最新的是这个2019年,最新版本是1.15.0 ,目前是支持junit5
com.github.javatlacati » contiperf : 2019年还在更新,基于junit4,它的前身是org.databene » contiperf 不过最近更新也是在2014年了
com.github.houbb » junitperf : 2020年更新,底层依赖的是 com.github.noconnor » junitperf和com.github.javatlacati » contiperf ,是对于两者的重新包装。 目前是支持junit5
组件对比
组件
|
noconnor » junitperf
|
javatlacati » contiperf
|
houbb » junitperf
|
最新junit版本
|
5
|
4
|
5
|
输出报告
|
console,html,csv,custom,multiple
|
html
|
console,html,csv,custom,multiple
|
指标
|
吞吐、min、max、avg、success、error
|
吞吐、min、max、avg、med、90线
|
同noconnor » junitperf
|
定制指标
|
可以随意定制90线,95线等指标
|
可以随意定制90线,95线等指标
|
可以随意定制90线,95线等指标
|
多线程
|
支持
|
支持
|
支持
|
结果预期
|
支持
|
支持
|
支持
|
输出
|
通过JUnitPerfRule定义
|
通过标注 report定义
|
|
参数
|
丰富
|
丰富
|
有裁剪,没有所有都支持
|
从更新时间来说,junitperf比较持续,而且功能上也没有什么区别,就采用了junitperf来做junit的集成性能测试。
houbb » junitperf 其实是包装了 noconnor » junitperf 和javatlacati » contiperf 。 是一个封装器,也改写了使用方法。
使用姿势
noconnor » junitperf的使用姿势
public class PerformanceTest { //定义输出模式,CsvReportGenerator,HtmlReportGenerator,CustomStatisticsCalculatorImpl,CustomStatisticsCalculatorImpl @Rule public JUnitPerfRule perfTestRule = new JUnitPerfRule(new ConsoleReportGenerator()); /** * threads :执行线程数 * durationMs :执行时间 * rampUpPeriodMs:平滑预热时间,默认是精致 * warmUpMs : 准备时间 * maxExecutionsPerSecond:每秒执行个数 * @throws InterruptedException */ @Test @JUnitPerfTest(threads = 50, durationMs = 125_000, rampUpPeriodMs = 2_000, warmUpMs = 10_000, maxExecutionsPerSecond = 11_000) public void test() throws InterruptedException { System.out.println("haha"); ThreadLocalRandom current = ThreadLocalRandom.current(); TimeUnit.SECONDS.sleep(current.nextInt(10)); } }
houbb » junitperf 使用姿势
/** * @author lukexue * @create 2020-06-10 15:02 **/ public class PerformanceTest2 { /** * 配置:2个线程运行。准备时间:1000ms。运行时间: 2000ms。 * 要求:最快不可低于 210ms, 最慢不得低于 250ms, 平均不得低于 225ms, 每秒运行次数不得低于 4 次。 * 20% 的数据不低于 220ms, 50% 的数据不得低于 230ms; * reporter : 输出格式html */ @Test @JunitPerfConfig(threads = 50, warmUp = 10000, duration = 125000, reporter = {ConsoleReporter.class}) //ConsoleReporter,HtmlReporter @JunitPerfRequire(min = 210, max = 250, average = 225, timesPerSecond = 4, percentiles = {"20:220", "50:230"}) public void test() throws InterruptedException { System.out.println("haha"); ThreadLocalRandom current = ThreadLocalRandom.current(); TimeUnit.SECONDS.sleep(current.nextInt(10)); } }
结果输出
最终结果输出
</div> <div>15:09:31.976 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Started at: 2020-06-10 15:07:26.854 15:09:31.976 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Invocations: 1340 15:09:31.976 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Success: 1340 15:09:31.976 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Errors: 0 15:09:31.976 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Thread Count: 50 15:09:31.976 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Warm up: 10000ms 15:09:31.976 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Execution time: 125000ms 15:09:31.977 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Throughput: 11/s (Required: 4/s) - PASSED 15:09:31.978 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Min latency: 0.003639ms (Required: 210.0ms) - PASSED 15:09:31.978 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Max latency: 9005.115ms (Required: 250.0ms) - FAILED 15:09:31.979 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Ave latency: 4351.276ms (Required: 225.0ms) - FAILED 15:09:31.979 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Percentile: 50% 4004.3013ms (Required: 230.0ms) - FAILED 15:09:31.980 [main] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Percentile: 20% 1004.48737ms (Required: 220.0ms) - FAILED 15:09:31.982 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Started at: 2020-06-10 15:07:26.854 15:09:31.982 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Invocations: 1340 15:09:31.982 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Success: 1340 15:09:31.982 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Errors: 0 15:09:31.982 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Thread Count: 50 15:09:31.983 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Warm up: 10000ms 15:09:31.983 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Execution time: 125000ms 15:09:31.983 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Throughput: 11/s (Required: 4/s) - PASSED 15:09:31.983 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Min latency: 0.003639ms (Required: 210.0ms) - PASSED 15:09:31.983 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Max latency: 9005.115ms (Required: 250.0ms) - FAILED 15:09:31.983 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Ave latency: 4351.276ms (Required: 225.0ms) - FAILED 15:09:31.984 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Percentile: 50% 4004.3013ms (Required: 230.0ms) - FAILED 15:09:31.984 [pool-2-thread-1] INFO com.github.houbb.junitperf.core.report.impl.ConsoleReporter - Percentile: 20% 1004.48737ms (Required: 220.0ms) - FAILED</div> </div> <div>
唯一的遗憾是包是强依赖与 guava,如果你自己用了guava版本比它还低的话就跑不起来,因为我的业务也用了hbase,里面依赖的低版本的guava,结果很尴尬。这个也是java的问题
参考资料:
https://segmentfault.com/a/1190000015722861
https://github.com/houbb/junitperf
https://github.com/noconnor/JUnitPerf#multiple-reports
slf4j + log4j + commons log 的相关配置
作者: inter12
日期: 19 八月, 2019
没有评论 | 2,942 views
之前一直没有系统的整理 日志依赖相关的包,最近恰好查一个问题,需要在一个最简单的环境下,打印日志。就花了点时间整理了一下各个日志包之间的使用关系。
阅读全文…
一个比较有趣的性能问题排查工具
作者: inter12
日期: 12 三月, 2018
没有评论 | 2,793 views
greys是一个很强大的工具,简单的一句话就是强化版的btrace. 之前遇见一个问题,就是线上查询很慢,正好通过这个工具试着诊断一下。
一 安装greys
curl -sLk http://ompc.oss.aliyuncs.com/greys/install.sh|sh
cd greys
sh ./install-local.sh
二 诊断问题
jcmd 拿到 pid
root@hzxs-hadoop-pre-03:/data/src/greys # ./greys.sh 141930
_
____ ____ _____ _ _ ___ _____ _____ ____ _____ _| |_ ___ ____ _ _
/ _ |/ ___) ___ | | | |/___|_____|____ | _ \(____ (_ _) _ \| \| | | |
( (_| | | | ____| |_| |___ | / ___ | | | / ___ | | || |_| | | | | |_| |
\___ |_| |_____)\__ (___/ \_____|_| |_\_____| \__)___/|_|_|_|\__ |
(_____| (____/ (____/
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|v|e|r|s|i|o|n|:|1|.|7|.|6|.|6|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ga?>
查看问题:
ga?>trace com.bilibili.berserker.horoscope.biz.service.impl.HoroChannelDomainServiceImpl listChannelList
Affect(class-cnt:1 , method-cnt:1) cost in 416 ms.
`—+Tracing for : thread_name=”qtp2142442467-651″ thread_id=0x28b;is_daemon=false;priority=5;
`—+[7371,7370ms]com.bilibili.berserker.horoscope.biz.service.impl.HoroChannelDomainServiceImpl:listChannelList()
+—[1,0ms]com.google.common.base.Preconditions:checkNotNull(@38)
+—[1,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getPlatform(@39)
+—[1,0ms]com.google.common.base.Preconditions:checkNotNull(@39)
+—[1,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getStartDate(@40)
+—[1,0ms]com.google.common.base.Preconditions:checkNotNull(@40)
+—[1,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getEndDate(@41)
+—[1,0ms]com.google.common.base.Preconditions:checkNotNull(@41)
+—[9,8ms]com.bilibili.agilawood.util.BeanUtils:copy(@43)
+—[9,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getStartDate(@46)
+—[9,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getEndDate(@47)
+—[9,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getSortField(@48)
+—[9,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getSortType(@49)
+—[7371,7362ms]com.bilibili.berserker.horoscope.dao.HoroChannelDataDAO:listChannels(@45)
+—[7371,0ms]org.apache.commons.collections.CollectionUtils:isEmpty(@51)
`—[7371,0ms]com.bilibili.agilawood.util.BeanUtils:copyList(@55)
发现大量的耗时在一个DAO操作上
原因是上线时候没有给查询条件加上索引导致的,添加索引后。
ga?>trace com.bilibili.berserker.horoscope.biz.service.impl.HoroChannelDomainServiceImpl listChannelList
Press Ctrl+D to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 474 ms.
`—+Tracing for : thread_name=”qtp685399117-2763″ thread_id=0xacb;is_daemon=false;priority=5;
`—+[64,63ms]com.bilibili.berserker.horoscope.biz.service.impl.HoroChannelDomainServiceImpl:listChannelList()
+—[1,0ms]com.google.common.base.Preconditions:checkNotNull(@38)
+—[1,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getPlatform(@39)
+—[1,0ms]com.google.common.base.Preconditions:checkNotNull(@39)
+—[1,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getStartDate(@40)
+—[1,0ms]com.google.common.base.Preconditions:checkNotNull(@40)
+—[1,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getEndDate(@41)
+—[1,0ms]com.google.common.base.Preconditions:checkNotNull(@41)
+—[1,0ms]com.bilibili.agilawood.util.BeanUtils:copy(@43)
+—[1,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getStartDate(@46)
+—[1,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getEndDate(@47)
+—[1,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getSortField(@48)
+—[1,0ms]com.bilibili.berserker.horoscope.api.query.HoroChannelSimpleQuery:getSortType(@49)
+—[64,63ms]com.bilibili.berserker.horoscope.dao.HoroChannelDataDAO:listChannels(@45)
+—[64,0ms]org.apache.commons.collections.CollectionUtils:isEmpty(@51)
`—[64,0ms]com.bilibili.agilawood.util.BeanUtils:copyList(@55)
一个SQL查询从7秒多降到了64毫秒。
三 总结
greys是一个不错的工具,还有其他很强大的功能,具体可见使用文档:https://yq.aliyun.com/articles/2390
字符集及编码方式
作者: inter12
日期: 17 四月, 2015
没有评论 | 3,292 views
碰到个问题,中文解析乱码,顺手查了些资料,就记在这里了。
自己以前也写过一篇类型的文章:http://www.inter12.org/archives/622
一 基本概念:
字符集(Charset):是一个系统支持的所有抽象字符的集合。字符是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。
字符编码(Character Encoding):是一套法则,使用该法则能够对自然语言的字符的一个集合(如字母表或音节表),与其他东西的一个集合(如号码或电脉冲)进行配对。
常见字符集:ASCII字符集、GB2312字符集、BIG5字符集、GB18030字符集、Unicode字符集
常见字符编码:ASCII编码、GB2312编码、BIG5编码、GB18030编码、Unicode编码
一般所说的UTF-8,包含了
unicode:为表达任意语言的任意字符而设计。它使用4字节的数字来表达每个字母、符号,或者表意文字(ideograph)。每个数字代表唯一的至少在某种语言中使用的符号。
Unicode是字符集,UTF-32/ UTF-16/ UTF-8是三种字符编码方案
通常所见的utf-8:指的是unicode字符集,utf-8编码方式
二 常见解释:
Accept-Charset:浏览器申明自己接收的字符集,这就是本文前面介绍的各种字符集和字符编码,如gb2312,utf-8(通常我们说Charset包括了相应的字符编码方案);
阅读全文…
zookeeper的简单集群搭建
作者: inter12
日期: 10 九月, 2014
没有评论 | 7,254 views
1.zookeeper安装和使用
包下载地址 :http://zookeeper.apache.org/releases.html#download
阅读全文…