不久前参与开发了一个基于dubbo分布式框架的底层账单系统,并实现了其中的一部分业务接口,目前需对这些接口进行压测,以评估生产环境所能承受的最大吞吐量。笔者以其中一个查询接口为例来回顾此次压测的整体流程。

压测准备:

1.调用查询接口的测试jar包,作为dubbo-consumer,依赖了查询服务的api,测试module基于maven开发,执行maven clean package即可通过编译得到jar包

2.JMeter:Apache组织开发的基于Java的压力测试工具

方案:

无限次请求查询接口(保证任意时刻并发量相同),观察Error%为0,当请求平稳进行时的tps,为该接口吞吐量

 

实施:

1.JMeter中添加一个测试计划,线程组容量分别设为10、20、50、80、100、200、400、1000、2000,通过jmeter csv data set config设置三组查询参数

2.准备完毕后,依次在不同容量线程组下启动测试计划,结果如下

吞吐量折线统计图

99%Line折线统计图

Error%折现统计图

结论:当线程数为200时,tps达到1700+,随着线程数增加,99%Line明显蹿升至6s,猜想部分线程请求不到资源,并且Error线程占比瞬间增多也印证了这一点。ps:如果同一组参数测试,压测效果却在递减,可尝试重启Jmeter。


思考&决策:

当前测试结构中包含三个节点:本地测试Consumer节点—>查询接口Provider节点—>数据库节点,所以相邻两个节点间均可能产生并发瓶颈,所以需要定位具体问题发生的具体位置。由于压测仅需一个节点,所以笔者使用了jVisualVM+jmx+jstacd组合,远程监听Dubbo服务所在的那台机器。


调优准备:

1.jstatd:(JDK自带)基于RMI的服务程序,用于监控基于HotSpot的JVM中资源的创建及销毁。首次使用需在被监控机器中加入权限授予文件jstatd.all.policy(jdk的bin目录下)

文件内容:

grant codebase"file:${java.home}/../lib/tools.jar"{

permission java.security.AllPermission;

};

完毕后执行./jstatd -J-Djava.security.policy=jstatd.all.policy -J-Djava.rmi.server.hostname=远程服务器ip &

对外默认开启1099端口

2.jVisualVM:(JDK自带)Java性能分析工具

3.jmx:(JDK自带),是一个为应用程序、设备、系统等植入管理功能的框架,如管理基于tomcat的web服务,本文中管理基于SpringBoot的Dubbo服务,需在启动脚本中加入jmx的启动配置

-Dcom.sun.management.jmxremote

-Djava.rmi.server.hostname=远程服务器ip

-Dcom.sun.management.jmxremote.port=18999(自定义)

-Dcom.sun.management.jmxremote.ssl=false

-Dcom.sun.management.jmxremote.authenticate=false


方案&实施:

开启压测,并观察jVisualVM中占用CPU时间非常多的热点方法,并查询远程主机cpu使用率情况

jVisualVM观察面板

发现在正常线程数请求时,获取DriudDataSource连接池连接的方法CPU时间非常高,经查询发现,系统中连接池的配置:initialSize、minIdle、maxActive都非常低,遂进行了第一次调优:提升数据库连接数,连接池初始化连接数50,最小空闲连接数50,最高活跃连接数400。

提升后,获取连接方法的CPU时间明显降低,遂测试线程数为400时的请求环境下的支持情况,发现已经开始出现error,即一部分线程请求不到资源,99%Line也达到6s之大!

分析:

此时系统的数据库连接池配置已经达到400,瓶颈不在此处,那么会不会是远程的数据库节点存在瓶颈,于是远程登录数据库节点,发现mysql的允许连接数非常大,不存在瓶颈。既然请求线程数非常大,数据库连接池连接数非常大,数据库提供的连接数也足够,CPU、JVM均没有异常,那么造成性能瓶颈的可能在与dubbo允许提供的连接线程数不足以匹配压测产生的线程数。

定位到dubbo配置,发现并没有显式定义dubbo连接数,查阅dubbo开发文档

dubbo默认连接线程数

问题发现了:dubbo默认连接线程数为100,  而并发量400的请求线程对dubbo造成的压力过大,导致压测不久就出现部分线程请求不到资源超时的问题,遂进行了第二次调优:提升Dubbo线程池连接数,将连接数提升至1000。

那么是不是到此并发就不存在瓶颈了呢?1000请求线程+dubbo允许线程数1000+数据库大连接数支持,理论上操作是没有问题的,我们来实际跑一下,发现压测时出现了更严重的问题,刚开始请求就出现了OOM及超过一半的error线程,准备去远程机器打印一下执行日志,就连tail及ps命令都没有可用资源供执行,停掉了请求线程,又费了九牛二虎之力停掉了服务进程,开始分析原因:各系统间通信均无瓶颈,问题会出在哪里,是什么原因撑爆了JVM,已知的条件是远程服务至少有1000个线程在服务器内生存,是不是线程量太大撑爆了机器?由于JVM中,栈空间线程私有,查阅JVM参数

JVM线程栈空间

服务器为linux系统,那默认ThreadStackSize=1024K,那么1000个线程JVM就需要创建1000*1024k即1个G的空间!这个节点部署三个服务,光一个服务的请求线程就占据1个G,内存溢出也是情理之中的了,遂进行了第三次调优:减少线程栈空间,ThreadStackSize调至256K,也是够用的,再次模拟1000线程并发,OK,无论是系统间线程调用还是内存中JVM空间都在正常情况下,并未出现线程请求不到资源的情况。


总结:

本次压测主要目的是确定单节点在生产环境所能承受的tps峰值,并借助测试数据反向分析之前开发及单元测试无法覆盖的隐藏问题,通过三次调优,我们可以发现,该环境下瓶颈主要在系统间请求发生时,以及JVM自身无法负载大数据量线程导致。当然也有可能发生在程序本身过程中,如逻辑中创造大量对象,消耗大量内存,或同步逻辑处理块设计欠缺,导致死锁、线程饿死等。笔者所描述的问题只是众多压测问题中的一小部分,分析、操作难免有疏漏,欢迎各位同学予以指正及建议。感谢华哥、林哥指导,感谢一鸣同学协助~


基于Dubbo的压测调优实例的更多相关文章

  1. dubbo接口压测工具stresstester使用

    dubbo接口压测工具stresstester使用 https://blog.csdn.net/u013822349/article/details/79412719

  2. Hadoop作业性能指标及參数调优实例 (三)Hadoop作业性能參数调优方法

    作者: Shu, Alison Hadoop作业性能调优的两种场景: 一.用户观察到作业性能差,主动寻求帮助. (一)eBayEagle作业性能分析器 1. Hadoop作业性能异常指标 2. Had ...

  3. Hadoop作业性能指标及參数调优实例 (二)Hadoop作业性能调优7个建议

    作者:Shu, Alison Hadoop作业性能调优的两种场景: 一.用户观察到作业性能差,主动寻求帮助. (一)eBayEagle作业性能分析器 1. Hadoop作业性能异常指标 2. Hado ...

  4. Jmeter实现dubbo接口压测案例

    当前项目中重构了消息服务,需要对消息服务接口做性能压测,评估消息服务的性能情况 通过和开发对接,目前消息服务是通过dubbo接口对内提供服务,所以才有了这边文章的记录 最初的压测这个dubbo接口有三 ...

  5. 基于Linux的WebSphere性能调优与故障诊断

    一.关于was数据源等问题的配置 (1)关于was数据源连接池的最大.最小配置多大合适?怎样去计算? (2)关于JVM的配置,64位系统,64位WAS,最值小和最大配置多大最优?怎样去计算? (3)应 ...

  6. Java内存泄露及性能调优实例

    内存泄漏及解决方法 1)系统崩溃前的一些现象 每次垃圾回收的时间越来越长,由之前的10ms延长到50ms左右,FullGC的时间也有之前的0.5s延长到4.5s:FullGC的次数越来越多,最频繁时隔 ...

  7. Dubbo接口压测

    在每年的双十一大促之前,除了全链路压测,还需要各个业务方对自己业务提供的核心接口进行单接口压测,以评判系统的稳定性和承压能力. 一.准备工作 环境准备:确保应用性能环境(perf)正常可用 压测接口梳 ...

  8. Android性能调优实例

    本文主要分享自己在appstore项目中的性能调优点,包括同步改异步.缓存.Layout优化.数据库优化.算法优化.延迟执行等. 目前性能优化专题已完成以下部分: 性能优化总纲——性能问题及性能调优方 ...

  9. 转:Web网站性能测试分析及调优实例

    1.背景 前段时间,性能测试团队经历了一个规模较大的门户网站的性能优化工作,该网站的开发和合作涉及多个组织和部门,而且网站的重要性不言而喻,同时上线时间非常紧迫,关注度也很高,所以对于整个团队的压力也 ...

随机推荐

  1. android app调试没问题,但打包签名的apk,运行时出现闪退怎么办?

    在用Eclipse编写Android app时,有时调试时没有问题,但一经打包签名,运行就出现闪退,还报错说找不到某某类.一开始以为是混淆导致的,后来我没有混淆竟然也还是这个问题.无奈只得网上寻找解决 ...

  2. 短信发送接口被恶意访问的网络攻击事件(四)完结篇--搭建WAF清理战场

    前言 短信发送接口被恶意访问的网络攻击事件(一)紧张的遭遇战险胜 短信发送接口被恶意访问的网络攻击事件(二)肉搏战-阻止恶意请求 短信发送接口被恶意访问的网络攻击事件(三)定位恶意IP的日志分析脚本 ...

  3. HTML5 LocalStorage 本地存储总结

    存储数据的方法就是直接给window.localStorage添加一个属性,例如:window.localStorage.a 或者 window.localStorage["a"] ...

  4. Socket实现-Socket I/O

    Socket层的核心是两个函数:sosend()和soreceive().这两个函数负责处理所有Socket层和协议层之间的I/O操作. select()系统调用的作用是监控文件描述符的状态.一般用于 ...

  5. 在MacOS中,Unity使用VSCode开发,4.7版本无法正常使用C#

    我在MacOS中安装了两个版本的Unity,一个是4.7版本,一个是5.6版本,在5.6版本中使用VSCode打开项目时,可以正常代码提示和查看,但是打开4.7版本的项目时,无法正常提示和查看. 经过 ...

  6. CCS学习(三)

    边框样式  边框线 dorder-style (top 上: bottom 下:  left 左: right 右)  样式:none | hidden | dotted | dashed | sol ...

  7. Jmeter之分布式测试

    1)Jmeter 是纯java 应用,对于CPU和内存的消耗比较大,并且受到JVM的一些限制: 一般情况下,依据机器配置,单机的发压量为300-600,因此,当需要模拟数以千计的并发用户时,使用单台机 ...

  8. 流畅python学习笔记:第十章:序列的修改,散列和切片

    前面在介绍了类的很多内置方法,比如__add__,__eq__,这里继续介绍类的两个内置方法,这2个内置方法可以将一个类实例变成一个序列的形式.代码如下 class vector(object):   ...

  9. Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集)

    Luogu 2245 星际导航(最小生成树,最近公共祖先LCA,并查集) Description sideman做好了回到Gliese 星球的硬件准备,但是sideman的导航系统还没有完全设计好.为 ...

  10. docker学习笔记--重基础使用

    最近一直在研究Elasticsearch,后来部门的同事遇到了一个docker集群的未授权访问漏洞,于是稍微看了一下docker进行了一下基本的入门,本文把自己学习docker的过程进行了一个详细的记 ...