软件:
jetty:jetty-io-9.4.22.v20191022.jar,spring-boot-2.2.1.RELEASE.jar,mysql:Ver 8.0.29
硬件:
mac:内存16G,磁盘HD 1T,cpu:Apple M1 Pro,核总数: 10(8性能和2能效),网络:电信100M
下载JMeter
下载地址:https://jmeter.apache.org/download_jmeter.cgi
例如mac/linux可以选择:https://dlcdn.apache.org//jmeter/binaries/apache-jmeter-5.5.zip
启动JMeter
- mac/linux启动jmeter
- windows启动jemter.bat
创建测试计划+线程组
- 默认会自动创建Test Plan,可以自己修改测试计划名称
配置线程组
- Number of Threads(users) : 模拟的用户数量
- Ramp-up period(seconds): 多少秒达到这个用户数
- Loop Count: 执行测试用例循环的次数,例如:用户数=5000,循环次数=2,实际测试请求次数=5000*2=10000。最大压力测试时可以选择一直循环。
每个线程将完整地执行测试计划,并且完全独立于其他测试线程。使用多线程来模拟到服务器应用程序的并发连接
创建测试样本
样本配置
- 下图案例http请求样本配置
添加监听器
添加请求结果树视图![6-添加察看请求结果树.png](https://img-blog.csdnimg.cn/img_convert/9a579d13930cf4eb2184365846a6bf09.png#averageHue=#3e4245&clientId=uadb46900-3ecd-4&from=ui&id=u942bc283&name=6-%E6%B7%BB%E5%8A%A0%E5%AF%9F%E7%9C%8B%E8%AF%B7%E6%B1%82%E7%BB%93%E6%9E%9C%E6%A0%91.png&originHeight=1132&originWidth=1812&originalType=binary&ratio=2&rotation=0&showTitle=false&size=886248&status=done&style=none&taskId=ud70d6cdd-f0c1-4a60-859a-a7e16797f0f&title=)
添加总结报告
配置完成执行测试用例即可
测试报告
结果树视图
总结报告
为什么请求样本未达到设定值?
因为本地电脑资源有限,报错了,报错信息如下:
异常信息
Last login: Sun Mar 5 19:43:41 on ttys000
/Users/gallant/Documents/application/apache-jmeter-5.5/bin/jmeter ; exit;
gallant@gallantdeMacBook-Pro ~ % /Users/gallant/Documents/application/apache-jmeter-5.5/bin/jmeter ; exit;
WARNING: package sun.awt.X11 not in java.desktop
================================================================================
Don't use GUI mode for load testing !, only for Test creation and Test debugging.
For load testing, use CLI Mode (was NON GUI):
jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder]
& increase Java Heap to meet your test requirements:
Modify current env variable HEAP="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m" in the jmeter batch file
Check : https://jmeter.apache.org/usermanual/best-practices.html
================================================================================
[23.904s][warning][os,thread] Failed to start thread "Unknown thread" - pthread_create failed (EAGAIN) for attributes: stacksize: 2048k, guardsize: 16k, detached.
[23.904s][warning][os,thread] Failed to start the native thread for java.lang.Thread "Thread Group qps5k 1-4432"
Uncaught Exception java.lang.OutOfMemoryError: unable to create native thread: possibly out of memory or process/resource limits reached in thread Thread[StandardJMeterEngine,6,main]. See log file for details.
2023-03-05 19:52:11.774 java[12840:1681196] TSM AdjustCapsLockLEDForKeyTransitionHandling - _ISSetPhysicalKeyboardCapsLockLED Inhibit
线程执行日志
2023-03-05 19:47:37,120 INFO o.a.j.t.JMeterThread: Thread started: Thread Group qps5k 1-4428
2023-03-05 19:47:37,121 INFO o.a.j.t.JMeterThread: Thread started: Thread Group qps5k 1-4427
2023-03-05 19:47:37,122 INFO o.a.j.t.JMeterThread: Thread started: Thread Group qps5k 1-4429
2023-03-05 19:47:37,123 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group qps5k 1-4428
2023-03-05 19:47:37,123 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group qps5k 1-4428
2023-03-05 19:47:37,123 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group qps5k 1-4427
2023-03-05 19:47:37,123 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group qps5k 1-4427
2023-03-05 19:47:37,124 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group qps5k 1-4429
2023-03-05 19:47:37,124 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group qps5k 1-4429
2023-03-05 19:47:37,125 INFO o.a.j.t.JMeterThread: Thread started: Thread Group qps5k 1-4430
2023-03-05 19:47:37,127 INFO o.a.j.t.JMeterThread: Thread started: Thread Group qps5k 1-4431
2023-03-05 19:47:37,128 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group qps5k 1-4430
2023-03-05 19:47:37,128 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group qps5k 1-4430
2023-03-05 19:47:37,130 INFO o.a.j.t.JMeterThread: Thread is done: Thread Group qps5k 1-4431
2023-03-05 19:47:37,130 INFO o.a.j.t.JMeterThread: Thread finished: Thread Group qps5k 1-4431
怎样增加吞吐量压力?
降低Ramp-up period
例如,当前案例,修改该参数为2,
结论:Throughput压力提升至=1953/s,接近2倍
增加Loop Count
直接增加到最大,一直循环
结论:Throughput压力提升至=11221/s
由于线程创建过多导致JMeter测试期间报错,降低用户数为=10
结论:Throughput压力提升至=17036/s
小结
固定两个参数
- Loop Count=Infinite
- Ramp-up period=1s
调整用户数参数,可以压出Throughput到达1.7W左右为服务最大抗压值
注意:压测过程中关注下jetty线程池是否有队列积压,如果配置了监控,检查日志中是否存在"Low Resources:"
2023-03-05 15:43:19,510 WARN [Scheduler-1637411253-1] o.e.j.s.LowResourceMonitor:monitor:343 {} Low Resources: Check if the server ThreadPool is lowOnThreads
最大吞吐摸底
删除接口中的数据库请求逻辑,接口直接响应客户端
结论:Throughput压力提升至=85285/s
jetty线程摸底
熟悉jetty的清楚,jetty默认线程池大小为200
上下文1
- 设置接口逻辑sleep 1s
- jetty线程池大小默认值:200
- 压测配置参数不变
结论:Throughput压力=10/s(受cpu限制,实际jetty线程池200>cpu数量无限制)
上下文2
- 设置接口逻辑sleep 1s
- jetty线程池大小设置为:4(org.eclipse.jetty.util.thread.ExecutorThreadPool#ExecutorThreadPool(int))
- 压测配置参数不变
结论:Throughput压力=2/s(受jetty线程池限制)
为什么是2呢?
检查堆栈如下
- 两个线程被用来accept监听数据(sun.nio.ch.ServerSocketChannelImpl.accept)
- 两个线程处理业务逻辑(org.gallant.account.controller.AccountInfoController.query)
"etp1687702287-20" #20 prio=5 os_prio=31 cpu=190.66ms elapsed=133.29s tid=0x000000011ead7200 nid=0x6707 waiting on condition [0x0000000289264000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(java.base@17.0.5/Native Method)
at org.gallant.account.controller.AccountInfoController.query(AccountInfoController.java:55)
at jdk.internal.reflect.GeneratedMethodAccessor41.invoke(Unknown Source)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@17.0.5/DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(java.base@17.0.5/Method.java:568)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:503)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:760)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1617)
at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:226)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:545)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:536)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1592)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1296)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:485)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1562)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1211)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.Server.handle(Server.java:500)
at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:386)
at org.eclipse.jetty.server.HttpChannel$$Lambda$608/0x000000080116c848.dispatch(Unknown Source)
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:562)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:378)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:270)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:388)
at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17.0.5/ThreadPoolExecutor.java:1136)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17.0.5/ThreadPoolExecutor.java:635)
at java.lang.Thread.run(java.base@17.0.5/Thread.java:833)
"etp1687702287-21-acceptor-0@40841fa6-ServerConnector@60b34931{HTTP/1.1,[http/1.1]}{0.0.0.0:8000}" #21 prio=3 os_prio=31 cpu=19.39ms elapsed=133.29s tid=0x000000011d107c00 nid=0x8803 runnable [0x0000000289472000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.Net.accept(java.base@17.0.5/Native Method)
at sun.nio.ch.ServerSocketChannelImpl.implAccept(java.base@17.0.5/ServerSocketChannelImpl.java:425)
at sun.nio.ch.ServerSocketChannelImpl.accept(java.base@17.0.5/ServerSocketChannelImpl.java:391)
at org.eclipse.jetty.server.ServerConnector.accept(ServerConnector.java:385)
at org.eclipse.jetty.server.AbstractConnector$Acceptor.run(AbstractConnector.java:701)
at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17.0.5/ThreadPoolExecutor.java:1136)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17.0.5/ThreadPoolExecutor.java:635)
at java.lang.Thread.run(java.base@17.0.5/Thread.java:833)
"etp1687702287-22" #22 prio=5 os_prio=31 cpu=228.00ms elapsed=133.29s tid=0x000000011fcb8400 nid=0x8603 waiting on condition [0x000000028967c000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(java.base@17.0.5/Native Method)
at org.gallant.account.controller.AccountInfoController.query(AccountInfoController.java:55)
at jdk.internal.reflect.GeneratedMethodAccessor41.invoke(Unknown Source)
at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@17.0.5/DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(java.base@17.0.5/Method.java:568)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:503)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:760)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1617)
at org.eclipse.jetty.websocket.server.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:226)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1604)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:545)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:536)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:235)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1592)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:233)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1296)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:188)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:485)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1562)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:186)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1211)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
at org.eclipse.jetty.server.Server.handle(Server.java:500)
at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:386)
at org.eclipse.jetty.server.HttpChannel$$Lambda$608/0x000000080116c848.dispatch(Unknown Source)
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:562)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:378)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:270)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:117)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:388)
at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17.0.5/ThreadPoolExecutor.java:1136)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17.0.5/ThreadPoolExecutor.java:635)
at java.lang.Thread.run(java.base@17.0.5/Thread.java:833)
"etp1687702287-23" #23 prio=5 os_prio=31 cpu=224.75ms elapsed=133.29s tid=0x000000013e84a800 nid=0x6903 runnable [0x000000028988a000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.KQueue.poll(java.base@17.0.5/Native Method)
at sun.nio.ch.KQueueSelectorImpl.doSelect(java.base@17.0.5/KQueueSelectorImpl.java:122)
at sun.nio.ch.SelectorImpl.lockAndDoSelect(java.base@17.0.5/SelectorImpl.java:129)
- locked <0x0000000703fb5b68> (a sun.nio.ch.Util$2)
- locked <0x0000000703fb4e80> (a sun.nio.ch.KQueueSelectorImpl)
at sun.nio.ch.SelectorImpl.select(java.base@17.0.5/SelectorImpl.java:146)
at org.eclipse.jetty.io.ManagedSelector$SelectorProducer.select(ManagedSelector.java:472)
at org.eclipse.jetty.io.ManagedSelector$SelectorProducer.produce(ManagedSelector.java:409)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produceTask(EatWhatYouKill.java:360)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:184)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:129)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:388)
at java.util.concurrent.ThreadPoolExecutor.runWorker(java.base@17.0.5/ThreadPoolExecutor.java:1136)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(java.base@17.0.5/ThreadPoolExecutor.java:635)
at java.lang.Thread.run(java.base@17.0.5/Thread.java:833)