性能压测诡异的Requests/second 响应刺尖问题

最近一段时间都在忙着转java项目最后的冲刺,前期的coding翻代码、debug、fixbug都逐渐收尾,进入上线前的性能压测。

虽然不是大促前的性能压测要求,但是为了安全起见,需要摸个底心里有个数。

毕竟这次转java的服务都是集团核心公共服务(主要是订单域服务)。(等我们顺利上线了,我再来好好总结下其中的坎坷和壮举。)

废话不多说了,直接进入主题。

由于这次压测主要重点是关注正向的两个核心订单服务,下单服务、查单服务。查单服务初步压测下来问题不大,主要是db的索引和cache的问题。

下单服务有两个核心接口,预订单查询、创建订单。预订单查询主要是订单的前置状态的结算页汇总计算(不仅是结算页),不落具体订单,如,各种促销、卡券码、虚拟币的规则计算等等。

创建订单逻辑稍微复杂点,对周边的系统及中间件依赖也比较多,所以需要重点关注,至少心中要有数,哪怕下游的哪个服务的性能有问题,在下次大促的时候可以优化掉。

(并不是说所有性能问题都需要及时优化,只要保证能撑得起业务量的一定范围就好,因为性能优化无止境,需要把握好节奏。)

提交横向压测前我们需要自己先过一遍,这样才能加快压测的效率,由于时间比较紧再加上客观的环境问题,我将服务中几个没有压测环境的依赖去掉。(有关压测的一些实践我将在下篇文章好好总结下,这里就不展开了。)压测了几轮(时间差不多30分钟左右。),消除了一些环境、代码、依赖的障碍,提交横向走压测流程,接着就去忙其他的事情了。(诡异的问题比较多~_~,mybatis pagehelperplugin好像也有点并发问题,还没定位到,不知道是用的不对还是什么情况,继续排查,有结论了我在总结分享下。)

1.压测报告:

并发用户数没变化,平均响应时间没变化,但是request/second奇怪了。我相信大多数开发的直觉就是fullgc了,我也一样。

立马去看下服务器的GC监控,同时看下程序的GCer配置是CMS。(CMS主要解决低延迟问题《深入理解JAVA虚拟机》)

2.查看服务器监控情况:

JAVA GC:

没发现fullgc,再看下几个其他的系统资源是否有异样。

cpu:

刺尖的几个点CPU idle 基本都是100%,us也是0%,非常奇怪。再看下其他的资源。

network:

也是比较奇怪的,receive到是挺正常的,send基本为0了,感觉像是某个调用或者发送停止了,能接受请求,但是对下游的调用貌似停止了。

memory:

内存咋一看好像有点问题,但是了解linux 内存计算方式和使用原理都知道这其实问题不大。(下篇文章中会具体讲解关于压测的时候各个指标如何查看和计算,在压测时候重点关注top中的swap区。)

我程序里面基本上没有用到什么大量的磁盘操作,基本上就一个日志输出,别的没有了。(linux cache区不管是读还是写都会被cache住,会在cache里维护一个逻辑地址空间。我将在下篇文章中演示出来,每当我删除磁盘的日志文件,cache区都会瞬间释放。https://www.ibm.com/developerworks/cn/linux/l-cache/index.html

重点是关注下JAVAGC 容量:(java程序的内存分配由“内存分配器+GC完成”《java性能优化权威指南》)

这是压测的下单服务机器资源情况。

3.查看DB情况:

看了下DB情况,也没啥异样,都是在相同的时间点,一下子负载没有了,时间都能对上。网络、磁盘、CPU都没有活动。

4.分析

上面图中有一幅图有点问题,不知道大家看出来了没有。就是我下单服务的应用服务器的网络流量有问题,receive、send对不上。

我们分析下,receive、send不配对意味着什么,我们有200并发,延迟1秒启动,基本上跑上个十几分钟,你能大概想象出200并发的请求空间路线图么。其实它会呈现出每秒钟都有请求进来,这是压力机的请求,每秒也会有请求出去,去访问它所依赖的服务或者中间件。如果,我们设想从压力机为开始点,把请求和响应想象成一个圆,那在圆的任何一个角度上都有请求和响应。

我们注意看下,DB的网络流量图,它就是比较正常的,没有请求没有发送。而应用服务器有点说不通,只有进来的没有出去的,这段时间内到底在干嘛,而且分布很平均。

5.排查

其实这个时候有一个结论,就是服务器其实没有瓶颈,不管是应用服务器还是DB、cache。那问题应该是在程序方面。(性能分析由上至下、由下至上集合分析《java性能优化权威指南》)。

开始尝试排查依赖服务,下单服务主要依赖商品、促销。cache不是问题,因为本地有一级缓存,而且缓存的过期时间对不上,压测环境的redis和MySQL在一台机器上。所以DB没有问题,基本上redis应该也没啥问题。(这台机器很强悍)还有部分的依赖业务方的接口我已经注释掉了,不会有依赖。

开始怀疑商品、促销,但是我之前分别对这两个服务进行过压测,这两个服务基本上都是命中cache,QPS基本上接近18000。现在也只好对这两个服务再进行一轮详细的压测。

结果很遗憾,没啥线索,性能很好。

开始排查线程池问题,是否有block线程,通过jstack 打印出线程,基本上都是XNIO的condition wait,也没有啥不正常。因为下单服务的其他接口都挺正常的,线程池问题应该不大。下单成功之后有意个hold的场景,就是hold虚拟币、卡券码等等之类的逻辑,这里面使用了fiexd线程池(5个,设置了饱和策略及日志输出。),问题也不大。

开始排查日志,restful-slow.log,jdbc-slow.log、错误日志等等,一顿cat… grep…wc –l,啥也没有异常。(shit开始冒汗了。。。)

只能上大招了,开始尝试注代码,然后压测,逐个尝试,先注释DB、然后线程池hold逻辑、然后发送消息。(无赖之举。。。)

6.浮出水面

等我尝试注释掉发送消息的逻辑时候发现问题不出现了,有希望了。开始进去看代码,没啥逻辑,走的是spring 的RabbitTemplate.convertAndSend 方法。(这是个同步方法,没有任何声明说他是async的。)

/**发送消息*/    
template.convertAndSend(messageConfig.getExchangeName(), routingKey, message, amqpMessage -> {

翻了下资料,没啥特殊的使用要求。

顺便看了下配置文件,发送消息走的是qa环境,这个我知道,因为当时压测环境的rabbitmq一时还没好,而且我们走的是先定义再使用queue的流程,所以如果要用我需要先上去配置好才能使用。当时图省事就先用了,自己压测下来也没啥问题,毕竟MQ的设计吞吐量都很高的,TPS足够我们用的,再加上我之前也压过qa的MQ没啥问题。

(资源没隔离是因为一些客观原因,有时候压测环境是临时搭建的。用到qa环境的中间件还有codis,但是codis基本是二级缓存,所以问题不大,先过。(回头没辙再来找它。)

搞来了qa环境的rabbitmq服务器账号,同时打开rabbtimq管理界面中的dashboard。开始重点关注这台服务器。(top命名打开,P\M看下rabbitmq各项指标。)

问题一如既往的出现了(我已经能接受了~_~,它要是不出现我才想死尼,已经来回折腾很久了。)很好,rabbtimq dashboard也出现刺尖了。

现在基本上是rabbtimq服务器的性能问题了,可能你会觉得问题找到了。但是我还是无解,为什么出现这个问题,为什么时间这么规律,肯定有蹊跷,继续排查,到底是rabbtimq服务器的CPU问题还是disk问题,还是network问题。这次重点看下top。

同样问题的出现CPU不正常,而且wait 率比较高。是不是可以这样推理,wait率高了,导致大量线程(子进程)挂起,所以看起来CPU利用率占的就高,也说的通。(先这么假设,来验证它就知道了)

有一点我可以肯定,根据rabbtimq推送消息原理,一个消息必须发送给所有监听的queue,这些queue必须落盘才算这次publish成功,才会返回。(可以参考《Rabbitmq in Action》)

这一点可以通过rabbtimq queue的dashboard 中的publish in 和 publish out才查看,publish out 是publish in * queue的数量。

也就是说发送消息不是发送给exchange就结束了,我们配置的是topic模式,这个消息类型后面有4个queue,同时这几个queue都有消费者在获取消费消息。但是由于获取消息的方式是pull模式,也不会存在多大的并发获取消息的情况。而且这些queue里面的消息都非常多,当我不压的时候CPU也不高,pull消息的开销对服务器来说network多点,CPU不会太多。

上图中的cpu wait率有点不正常是因为exchange同步写4个queue且落盘,所以有这个问题。

基于这个推理,我考虑用一个空exchange来接受消息,根据原理指导,exchange收到消息之后如果发现没有任何queue可以投递就直接丢弃了。

压测下来一切正常,没有出现刺尖情况(真爽~_~),cpuwait 正常0。基本上定位到问题了。是因为rabbtimq本身的负载不够了,性能跟不上所以导致这个问题,这也算加深了rabbtimq的部分原理。

在基于这个推理,我用了一个不持久化的queue来接受消息,也就是说这个消息是不会持久化的,cpuwait应该是0。

压测下来一切正常,cpuwait为0(心情无比的顺畅)。

提交横向第二轮压测。

7.打脸

等我在开会的时候,压测兄弟找我,哥哥那个问题又出现了。

(我一时蒙蔽,我擦什么情况。)调整了下,仔细看了下那个刺尖的出现的时间比以前长了。原来大概十五分钟,现在要半小时。由于qa环境机器没有安装压测监控工具,不知道那段时间里发生了什么。(压测执行时间1小时)

我之前都是30分钟,我尝试用空exchange压了一小时(已是周五晚24:00点左右,洗澡睡觉,明早上看结果)。

早上起来看没出现那个问题。为什么我用不持久的queue还有问题,而且这个queue是没有任何consumer的,这已经涉及到rabbtimq的底层原理了。rabbtimq用的是erlang语言写的,看源码一时半会估计路都找不到。还是想其他办法。

又尝试用持久化queue来压测一把,看下到时候啥情况,仔细盯着rabbtimq dashboard,果然又出现了。(计算机问题永远不存在巧合,不确定。)

注意看下图中的In memory,shit原来落盘了,哪怕你设置不持久化为了内存利用率,它会将消息落盘,注意看Persistent没有任何消息。消息总量1.1G,内存中只有119MB。

为什么会有那么大的disk write。由于大量的磁盘写入,导致publish消息的时候block了。具体为什么会这样就要去研究rabbtimq源码了。这些在rabbtimq的配置中应该有策略的,由于不是太熟悉rabbtimq,所以这里就只好先告一段落了。

8.总结

能隔离环境的尽量隔离,排查环境问题最头疼,但是有时候又无法避免。(下篇压测文章分享下,环境问题的排查方式和工具)

遇到问题一定要搞清楚根源,就算找不到根源也知道把它限定在某个范围内,比如限制到DB、操作系统等等

时间: 2024-07-30 13:49:20

性能压测诡异的Requests/second 响应刺尖问题的相关文章

后端服务性能压测实践

转自:https://mp.weixin.qq.com/s/XW9geHZ9odHdI7srDiKBIg 目录 背景 环境检测 压力机及压力工具检测 Linux openfiles limit 设置 排查周边依赖 空接口压测检测 聚合报告中 throughput 计算 压测及性能排查方法 关注各纬度 log Linux 常规命令 性能排查两种方式(从上往下.从下往上) 总结 背景 最近大半年内有过两次负责性能压测的一些工作.一件事情做了一次可能还无法总结出一些东西,两次过后还是能发现一些共性问题

(转)后端服务性能压测实践

作者:王清培(Plen wang) 传送门:https://www.cnblogs.com/wangiqngpei557/p/7953453.html ---------------------------------------------------------------------分割线------------------------------------------------------ 入职新公司,没人理我,负责的需求开发一直很忙,要么环境有问题,要么Bug卡住我找开发,回了一句

感受真实性能压测的“洪荒之力” 压测宝有奖体验中

作为测试,你有没有遇到这样的问题:1.熬了多少个日夜的系统终于快上线了,不知道上线后系统负载能力怎样?2.促销季到了,应用性能如何?到底能不能支持500w并发用户?3.怎么做压测才能更接近线上真实环境? 系统负载有多强,压测一下就知道.云智慧压测宝3步6分钟 开启真实用户的性能压测 8月16至9月2日申请试用压测宝,感受真实压测的洪荒之力,还有机会获得优酷视频会员卡,速速来领- 参与活动赢优酷会员卡 1.从这里申请试用压测宝:[url=http://yacebao.com/landingPage

swingbench-免费的oracle性能压测工具

SwingBench介绍: SwingBench由负载生成器,协调器和集群概述组成.该软件使得能够生成负载并且将图表的事务/响应时间映射. SwingBench可用于演示和测试诸如实际应用集群,在线表重建,备用数据库,在线备份和恢复等技术 SwingBench附带的代码包括6个基准,OrderEntry,SalesHistory,TPC-DS Like,JSON,CallingCircle和StressTest .. OrderEntry基于Oracle11g / Oracle12c附带的"oe

接口测试及服务器性能压测

目前移动端app大都还是采用的http或者https协议写的restful接口,一般的辅助类http劫持(fiddler,charles)和模拟发送(postman)工具都可以满足单次单个接口的测试需求,但这种依附工具的测试很难满足多接口调用逻辑验证问题,也不太灵活,没办法做到数据化,还有就是对于接口压测和服务器性能压力测试无法满足,又得借助于其他压测工具(Jmeter loadrunner等),设计一套基于http和https灵活定制的接口测试框架还是很有必要的. 一般app接口调用都要都要传

虚拟网卡性能压测

本文主要介绍多种场景下,虚拟机网卡的压测及性能对比,根据openstack实际的部署方式,虚拟机网卡压测场景包括 SRIOV(passthrough).SRIOV+Macvtap(passthrough).Vlan+Linux bridge.OVS+Linux Bridge,分别从协议类型(TCP/UDP).Message Size方向压测虚拟机网卡的时延.发包率.吞吐量. 压测环境 host1:  服务器型号:IBM x3550m2 CPU型号:Intel(R) Xeon(R) CPU*8,每

SSDB性能压测报告

测试场景 机器: 两台Intel(R) Xeon(R) E5506  2.13GHz  (4核 8线程)*2/内存32GB/SAS 300G 数据: key: 10位顺序数字     value: 50字节      数据量: 2kw 并发: 并发数依次为10.20.40.80.160 压测工具:redis-benchmark ssdb 版本: 1.9.2 ssdb 配置: leveldb: cache_size: 5120 block_size: 32 write_buffer_size: 6

RocketMQ性能压测分析(转)

原创文章,转载请注明出处:http://jameswxx.iteye.com/blog/2093785 一   机器部署 1.1  机器组成 1台nameserver 1台broker  异步刷盘 2台producer 2台consumer 1.2  硬件配置 CPU  两颗x86_64cpu,每颗cpu12核,共24核 内存 48G 网卡 千兆网卡 磁盘 除broker机器的磁盘是RAID10,共1.1T,其他都是普通磁盘约500G 1.3  部署结构 橙色箭头为数据流向,黑色连接线为网络连接

RocketMQ性能压测分析(转载)

一   机器部署 1.1  机器组成 1台nameserver 1台broker  异步刷盘 2台producer 2台consumer 1.2  硬件配置 CPU  两颗x86_64cpu,每颗cpu12核,共24核 内存 48G 网卡 千兆网卡 磁盘 除broker机器的磁盘是RAID10,共1.1T,其他都是普通磁盘约500G 1.3  部署结构 橙色箭头为数据流向,黑色连接线为网络连接 1.4  内核参数 broker是一个存储型的系统,针对磁盘读写有自己的刷盘策略,大量使用文件内存映射