基于Dubbo的压测调优实例
不久前参与开发了一个基于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.准备完毕后,依次在不同容量线程组下启动测试计划,结果如下
结论:当线程数为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使用率情况
发现在正常线程数请求时,获取DriudDataSource连接池连接的方法CPU时间非常高,经查询发现,系统中连接池的配置:initialSize、minIdle、maxActive都非常低,遂进行了第一次调优:提升数据库连接数,连接池初始化连接数50,最小空闲连接数50,最高活跃连接数400。
提升后,获取连接方法的CPU时间明显降低,遂测试线程数为400时的请求环境下的支持情况,发现已经开始出现error,即一部分线程请求不到资源,99%Line也达到6s之大!
分析:
此时系统的数据库连接池配置已经达到400,瓶颈不在此处,那么会不会是远程的数据库节点存在瓶颈,于是远程登录数据库节点,发现mysql的允许连接数非常大,不存在瓶颈。既然请求线程数非常大,数据库连接池连接数非常大,数据库提供的连接数也足够,CPU、JVM均没有异常,那么造成性能瓶颈的可能在与dubbo允许提供的连接线程数不足以匹配压测产生的线程数。
定位到dubbo配置,发现并没有显式定义dubbo连接数,查阅dubbo开发文档
问题发现了:dubbo默认连接线程数为100, 而并发量400的请求线程对dubbo造成的压力过大,导致压测不久就出现部分线程请求不到资源超时的问题,遂进行了第二次调优:提升Dubbo线程池连接数,将连接数提升至1000。
那么是不是到此并发就不存在瓶颈了呢?1000请求线程+dubbo允许线程数1000+数据库大连接数支持,理论上操作是没有问题的,我们来实际跑一下,发现压测时出现了更严重的问题,刚开始请求就出现了OOM及超过一半的error线程,准备去远程机器打印一下执行日志,就连tail及ps命令都没有可用资源供执行,停掉了请求线程,又费了九牛二虎之力停掉了服务进程,开始分析原因:各系统间通信均无瓶颈,问题会出在哪里,是什么原因撑爆了JVM,已知的条件是远程服务至少有1000个线程在服务器内生存,是不是线程量太大撑爆了机器?由于JVM中,栈空间线程私有,查阅JVM参数
服务器为linux系统,那默认ThreadStackSize=1024K,那么1000个线程JVM就需要创建1000*1024k即1个G的空间!这个节点部署三个服务,光一个服务的请求线程就占据1个G,内存溢出也是情理之中的了,遂进行了第三次调优:减少线程栈空间,ThreadStackSize调至256K,也是够用的,再次模拟1000线程并发,OK,无论是系统间线程调用还是内存中JVM空间都在正常情况下,并未出现线程请求不到资源的情况。
总结:
本次压测主要目的是确定单节点在生产环境所能承受的tps峰值,并借助测试数据反向分析之前开发及单元测试无法覆盖的隐藏问题,通过三次调优,我们可以发现,该环境下瓶颈主要在系统间请求发生时,以及JVM自身无法负载大数据量线程导致。当然也有可能发生在程序本身过程中,如逻辑中创造大量对象,消耗大量内存,或同步逻辑处理块设计欠缺,导致死锁、线程饿死等。笔者所描述的问题只是众多压测问题中的一小部分,分析、操作难免有疏漏,欢迎各位同学予以指正及建议。感谢华哥、林哥指导,感谢一鸣同学协助~
基于Dubbo的压测调优实例的更多相关文章
- dubbo接口压测工具stresstester使用
dubbo接口压测工具stresstester使用 https://blog.csdn.net/u013822349/article/details/79412719
- Hadoop作业性能指标及參数调优实例 (三)Hadoop作业性能參数调优方法
作者: Shu, Alison Hadoop作业性能调优的两种场景: 一.用户观察到作业性能差,主动寻求帮助. (一)eBayEagle作业性能分析器 1. Hadoop作业性能异常指标 2. Had ...
- Hadoop作业性能指标及參数调优实例 (二)Hadoop作业性能调优7个建议
作者:Shu, Alison Hadoop作业性能调优的两种场景: 一.用户观察到作业性能差,主动寻求帮助. (一)eBayEagle作业性能分析器 1. Hadoop作业性能异常指标 2. Hado ...
- Jmeter实现dubbo接口压测案例
当前项目中重构了消息服务,需要对消息服务接口做性能压测,评估消息服务的性能情况 通过和开发对接,目前消息服务是通过dubbo接口对内提供服务,所以才有了这边文章的记录 最初的压测这个dubbo接口有三 ...
- 基于Linux的WebSphere性能调优与故障诊断
一.关于was数据源等问题的配置 (1)关于was数据源连接池的最大.最小配置多大合适?怎样去计算? (2)关于JVM的配置,64位系统,64位WAS,最值小和最大配置多大最优?怎样去计算? (3)应 ...
- Java内存泄露及性能调优实例
内存泄漏及解决方法 1)系统崩溃前的一些现象 每次垃圾回收的时间越来越长,由之前的10ms延长到50ms左右,FullGC的时间也有之前的0.5s延长到4.5s:FullGC的次数越来越多,最频繁时隔 ...
- Dubbo接口压测
在每年的双十一大促之前,除了全链路压测,还需要各个业务方对自己业务提供的核心接口进行单接口压测,以评判系统的稳定性和承压能力. 一.准备工作 环境准备:确保应用性能环境(perf)正常可用 压测接口梳 ...
- Android性能调优实例
本文主要分享自己在appstore项目中的性能调优点,包括同步改异步.缓存.Layout优化.数据库优化.算法优化.延迟执行等. 目前性能优化专题已完成以下部分: 性能优化总纲——性能问题及性能调优方 ...
- 转:Web网站性能测试分析及调优实例
1.背景 前段时间,性能测试团队经历了一个规模较大的门户网站的性能优化工作,该网站的开发和合作涉及多个组织和部门,而且网站的重要性不言而喻,同时上线时间非常紧迫,关注度也很高,所以对于整个团队的压力也 ...
随机推荐
- SpringMvc+Spring3+MyBatis整合
1.MyBatis 例子 首先,单独使用MyBatis时: import java.io.IOException; import java.io.Reader; import org.apache.i ...
- form表单1的ajax验证
form表单的ajax验证1: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"&g ...
- 容器如何访问外部世界?- 每天5分钟玩转 Docker 容器技术(36)
前面我们已经解决了容器间通信的问题,接下来讨论容器如何与外部世界通信.这里涉及两个方向: 容器访问外部世界 外部世界访问容器 容器访问外部世界 在我们当前的实验环境下,docker host 是可以访 ...
- (转载)在spring的bean中注入内部类
原文链接:http://outofmemory.cn/java/spring/spring-DI-inner-class 在spring中注入内部类,有可能会遇到如下异常信息: 2014-5-14 2 ...
- 阿里云服务器 通过JavaMail发送邮箱STMP问题( 25端口被禁用 使用SSL协议465端口 )
我们传统使用的比较简单的是 STMP 25端口收发邮件 今天发现刚购买的阿里云服务器不能作为客户端通过STMP 25端口发送邮件 开始在网上有说发现是JDK1.8的原因,然后自己也把JDK1.8换到了 ...
- 单例设计模式 Single
一些人总结出来用来解决特定问题的固定的解决方案. 解决一个类在内存中只存在一个对象,想要保证对象的唯一. 1 为了避免其他程序过多的建立该类对象.禁止其他程序建立该类对象. 2 为了其他程序可以访问该 ...
- Linux 教程 技巧集
Linux 终端操作技巧 CTRL + U - 剪切光标前的内容 CTRL + K - 剪切光标至行末的内容 CTRL + Y - 粘贴 CTRL + E - 移动光标到行末 CTRL + A - 移 ...
- 在Jekyll博客添加评论系统:gitment篇
最近在Github Pages上使用Jekyll搭建了个人博客( jacobpan3g.github.io/cn ), 当需要添加评论系统时,找了一下国内的几个第三方评论系统,如"多说&qu ...
- 二维坐标点排序(JavaScript)
今天给大家分享下最近web项目中出现的一个技术难点问题--坐标排序: 如下图所示,要求在前端页面上按顺序将下面5个模块的坐标依次保存至数据库 现在已知信息如下: 1.每个模块分别为一个div 2.每个 ...
- STL—对象的构造与析构
STL内存空间的配置/释放与对象内容的构造/析构,是分开进行的. 对象的构造.析构 对象的构造由construct函数完成,该函数内部调用定位new运算符,在指定的内存位置构造对象 ...