后端服务性能压测实践

转自:https://mp.weixin.qq.com/s/XW9geHZ9odHdI7srDiKBIgjava

 

目录linux

  • 背景ios

  • 环境检测git

    • 压力机及压力工具检测apache

    • Linux openfiles limit 设置后端

    • 排查周边依赖性能优化

    • 空接口压测检测服务器

    • 聚合报告中 throughput 计算网络

  • 压测及性能排查方法架构

    • 关注各纬度 log

    • Linux 常规命令

    • 性能排查两种方式(从上往下、从下往上)

  • 总结

背景

最近大半年内有过两次负责性能压测的一些工做。一件事情作了一次可能还没法总结出一些东西,两次事后仍是能发现一些共性问题,因此总结下性能压测的通常性实践。可是问题确定不止这些,还有更多深层次的问题等着发现,等咱们遇到了在逐个解决再来总结分享。

作性能压测的缘由就很少说了,通常两个时间点是必需要作的,大促前、新系统上线。压测都是为了系统在线上的处理能力和稳定性维持在一个标准范围内,作到心中有数。

从整个行业来看,抛开一些大厂不说,全自动化的性能压测环境仍是比较少的,要想建设好一套全自动化的性能压测环境起码涉及到几个问题,CI\CD、独立、隔离的压测环境,自动化压测工具、平常压测性能报警、性能报表分析、排查/解决性能问题流程等等。这样才能将性能压测常规化,一旦不是常规化性能压测,就会有代码、中间件配置滞后于生产环境的问题。时间一长,就等于要从新开始搭建、排查压测环境。

若是性能压测的环境是全自动化的,那么就能够把性能压测工做常规化变成研发过程当中的一个例行的事项,执行起来效率就会很是高,压测的时候也会比较轻松,好处也是比较明显的。

可是大多数的时候咱们仍是须要从零开始进行性能压测的工做。毕竟搭建这样一套环境给企业带来的成本也是巨大的。性能压测对环境敏感,必须划分独立的部署、隔离单元,才能在后续的常规压测流程中直观的阅读压测报告。

题外话,若是有了自动化的压测环境,也仍是须要去了解下整个压测环境的基本架构,毕竟压测环境不是真实的生产环境,有些问题咱们须要知道是正常的仍是不正常的。

环境检测

当咱们须要进行性能压测时首先要面对的问题就是环境问题,环境问题包含了常见的几个点:

1.机器问题(实体机仍是虚拟机、CPU、内存、网络适配器进出口带宽、硬盘大小,硬盘是否 SSD、内核基本参数配置)

2.网络问题(是否有跨网段问题、网段是否隔离、若是有跨网段机器,是否能访问、跨网段是否有带宽限速)

3.中间件问题(程序里全部依赖的中间件是否有部署,中间件的配置是否初始化、中间件 cluster 结构什么样、这些中间件是否都进行过性能压测、压测的纬度是什么,是 benchmark 仍是针对特定业务场景的压测)

这些环境问题第一次排查的时候会有点累,可是掌握了一些方法、工具、流程以后剩下的也就是例行的事情,只不过人工参与的工做多点。

上面的问题里,有些问题查看是比较简单的,这里就不介绍了,好比机器的基本配置等。有些配置只须要你推进下,走下相关流程回头验收下,好比网段隔离等,也仍是比较简单的。

比较说不清楚的是中间件问题,看上去都是能用的,可是就是压不上去,这时候就须要你本身去进行简单的压测,好比 db 的单表插入、cache 的并发读取、mq 的落地写入等。这时候就涉及到一个问题,你须要对这些中间件都有必定深度的了解,要知道内在的运行机制,要否则出现异常状况排查起来确实很困难。

其实没有人能熟悉市面上全部的中间件,每个中间件都很复杂,咱们也不可能掌握一个中间件的全部点,可是经常使用的一些咱们是须要掌握的,至少知道个大概的内部结构,能够顺藤摸瓜的排查问题。

可是事实上总有你不熟悉的,这个时候求助下你们的力量互相探讨再本身摸索找点资料,咱们没遇到过也许别人遇到过,学技术其实就是这么个过程。

压力机及压力工具检测

既然作性能压测就须要先对压测机、压力工具先进行了解,压测工具咱们主要有 locustjmeterab,前二者主要是压测同事进行准出验收测试使用的。

后二者主要是用来提交压测前的自检使用,就是开发本身用来检查和排错使用的。这里须要强调下 ab 实际上是作基准测试的,不一样于 jmeter 的做用。

须要知道压力机是否和被压测机器服务器在一个网段,且网段之间没有任何带宽限制。压力机的压测工具配置是否有瓶颈,通常若是是 jmeter 的话须要检查 java 的一些基本配置。

可是通常若是压力机是固定不变的,一直在使用的,那么基本不会有什么问题,由于压力机压测同事一直维护者,反而是本身使用的压测工具的参数要作好配置和检测。

jmeter 压测的时候,若是压测时间过长,记得关掉 监听器->图形结果 面板,由于那个渲染若是时间太长基本会假死,误觉得会是内存的问题,实际上是渲染问题。

在开发作基准压测的时候有一个问题就是办公网络与压测服务器的网络之间的带宽问题,压力过大会致使办公网络出现问题。因此须要错开时间段。

大体梳理好后,咱们须要经过一些工具来查看下基本配置是否正常。好比,ethtool 网络适配器信息、nload流量状况等等,固然还有不少其余优秀的工具用来查看各项配置,这里就不罗列了。

使用 ethtool 查看网络适配器信息前须要先肯定当前机器有几个网络适配器,最好的办法是使用 ifconfig找到你正在使用的网络适配器。

排除 127.0.0.1 的适配器外,还有三个适配器信息,只有第一个 bond0 才是咱们正在使用的,而后使用 ethtool 查看当前 bond0 的详细适配器信息。重点关注下 speed 域,它表示当前网络适配器的带宽。

虽然网络适配器可能配置的没有问题,可是整个网络是否没问题还须要咨询相关的运维同事进行排查下,中间还可能存在限速问题。

要肯定网络带宽确实没有问题,咱们还须要一个实时的监控网络流量工具,这里咱们使用nload来监控下进出口流量问题。

这个工具仍是很不错的,尤为是在压测的过程当中能够观察流量的进出口状况,尤为是排查一些间隙抖动状况。

若是发现进口流量一直很正常,出口流量下来了有可能系统对外调用再放慢,有多是下游调用 block,可是 request 线程池还未跑满,也有可能内部是纯 asyncrequest 线程根本不会跑满,也有多是压测工具自己的压力问题等等。可是咱们至少知道是本身的系统对外调用这个边界出了问题。

Linux openfiles limit 设置

工做环境中,通常状况下 linux 打开文件句柄数上限是不须要咱们设置的,这些初始化的值运维同事通常是设置过的,并且是符合运维统一标准的。可是有时候关于最大链接数设置还要根据后端系统的使用场景来决定。

以防万一咱们仍是须要本身检查下是否符合当前系统的压测要求。

Linux 中一切都是文件,socket 也是文件,因此须要查看下当前机器对于文件句柄打开的限制,查看 ulimit -aopen files 域,也能够直接查看ulimit -n

若是以为配置的参数须要调整,能够经过编辑 /etc/security/limits.conf 配置文件。

排查周边依赖

要想对一个服务进行压测,就须要对这个服务周边依赖进行一个排查,有可能你所依赖的服务不必定具有压测条件。并非每一个系统的压测都在一个时间段内,因此你在压测的时候别人的服务也许并不须要压测等等。

还有相似中间件的问题,好比,若是咱们依赖中间件 cache ,那么是否有本地一级 cache ,若是有的话也许对压测环境的中间件 cache 依赖不是太大。若是咱们依赖中间件 mq ,是否是在业务上能够断开对 mq的依赖,由于咱们毕竟不是对 mq 进行压测。还有咱们所依赖服务也不关心咱们的压测波动。

整理出来以后最好能画个草图,再从新 git branch -b 从新拉一个性能压测的 branch 出来根据草图进行调整代码依赖。而后压测的时候观察流量和数据的走向,是否符合咱们梳理以后的路线。

空接口压测检测

为了快速验证压测服务一个简单的办法,就是经过压测一个空接口,查看下整个网络是否通畅,各个参数是否大致上正常。

通常在任何一个后端服务中,都有相似 health_checkendpoint,方便起见能够直接找一个没有任何下游依赖的接口进行压测,这类接口主要是为了验证服务器的 onlineoffline 状态。

若是当前服务没有相似 health_check 新建一个空接口也能够,并且实践证实,一个服务在生产环境很是须要这么一个接口,必要状况下能够帮助来排查调用链路问题。

《发布!软件的设计与部署》Jolt 大奖图书 第17章 透明性 介绍了架构的透明性设计做用。

聚合报告中 throughput 计算

咱们在用 jmeter 进行压测的时候关于 聚合报告 中的 throughput 理解须要统一下。

正常状况下在使用 jmeter 压测的时候会仔细观察 throughput 这一列的变化状况,可是没有搞清楚 thourghput 的计算原理的时候就会误觉得是 tps/qps 下来了,其实有时候是整个远程服务器根本就没有 response 了。

throughput=samples/压测时间

throughput(吞吐量) 是单位时间内的请求处理数,通常是按 second 计算,若是是压测 write 类型的接口,那么就是 tps 指标。若是压测 read 类型的接口,那么就是 qps 指标。这两种类型的指标是彻底不同的,咱们不能搞混淆了。

200(throughput) tps=1000(write)/5(s)1000(throughput) qps=2000(read)/2(s)

当咱们发现 throughput 逐渐下来的时候要考虑一个时间的纬度。

也就是说咱们的服务有可能已经不响应了,可是随着压测时间的积累,整个吞吐量的计算天然就在缓慢下滑,像这种刺尖问题是发现不了的。

这一点用ui版本的 jmeter 尤为明显,由于它的表现方式就是在欢欢放慢。用 Linux 版本的 jmeter 还好点,由于它的输出打印是隔断时间才打印。

关于这个点没有搞清楚很是影响咱们对性能压测的结果判断。因此咱们在压测的时候必定要有监控报表,才能知道在整个压测过程当中服务器的各项指标是否出现过异常状况。

大多数的时候咱们还会使用 apache ab 作下基本的压测,主要是用来与 jmeter 对比下,两个工具压测的结果是否相差不大,主要用来纠偏一些性能虚高问题。

apache abjmeter 各有侧重,ab 能够按固定请求数来压,jmeter 能够按时间来压,最后计算的时候须要注意二者区别。ab 好像是没有请求错误提示和中断的,jmeter 是有错误提示,还有各个纬度断言设置。

咱们在使用压测工具的时候,大体了解下工具的一些原理有助于准确的使用这款工具。

压测及性能排查方法

在文章的前面部分讲到了 排查周边依赖 的环境检查步骤。其实要想顺利的进行压测,这一步是必需要有的。通过这一步分析咱们会有一个基本的 系统依赖 roadmap

基于这份 系统依赖 roadmap 咱们将进行性能压测和问题定位及性能优化。

合理的系统架构应该是上层依赖下层,在没有肯定下游系统性能的状况下,是没办法肯定上游系统性能的瓶颈在哪里。

因此压测的顺序应该尽量的从下往上依次进行,这样能够避免无心义的排查因为下游吞吐量不够带来的性能问题。越是下游系统性能要求越高,由于上游系统的性能瓶颈直接依赖下游系统。

好比,商品系统的 v1/product/{productid} 前台接口,吞吐量为 qps 8000,那么全部依赖这个接口的上游服务在这个代码路径上最高吞吐量瓶颈就是 8000 ,代码路径无论是 tps 仍是 qps 都是同样的瓶颈。

上层服务可使用 async方式来提升 request 并发量,可是没法提升代码路径在 v1/product/{productid} 业务上的吞吐量。

咱们不能将并发和吞吐量搞混淆了,系统能扛住多少并发不表明吞吐量就很高。能够有不少方式来提升并发量,threadpool 提升线程池大小 、socket 类c10k 、nio事件驱动,诸如此类方法。

关注各纬度 log

当在压测的过程当中定位性能问题的性价比较高的方法就是请求处理的log,请求处理时长log,对外接口调用时长log,这通常能定位大部分比较明显的问题。当咱们用到了一些中间件的时候都会输出相应的执行log。

以下所示,在咱们所使用的开发框架中支持了不少纬度的执行log,这在排查问题的时候就会很是方便。

slow.log 类型的慢日志仍是很是有必要记录下来的,这不只在压测的时候须要,在生产上咱们也是很是须要。

若是咱们使用了各类中间件,那就须要输出各类中间件的处理日志,mq.logcache.logsearch.log 诸如此类。

除了这些 log 以外,咱们还须要重点关注运行时的 gc log

咱们主要使用 Java 平台,在压测的时候关注 gc log 是正常的事。哪怕不是 Java 程序,相似基于 vm 的语言都须要关注 gc log 。根据 jvm gcer 配置的不一样,输出的日志也不太同样。

通常电商类的业务,以响应为优先时 gc 主要是使用 cms+prenew ,关注 full gc 频次,关注 cms 初始标记并发标记从新标记并发清除 各个阶段执行时间, gc 执行的 real timepernew 执行时的内存回收大小等 。

java gc 比较复杂涉及到的东西也很是多,对 gc log 的解读也须要配合当前的内存各个代的大小及一系列 gc的相关配置不一样而不一样。

《Java性能优化权威指南》 java之父gosling推荐,能够长期研究和学习。

Linux 常规命令

在压测的过程当中为了能观察到系统的各项资源消耗状况咱们须要借助各类工具来查看,主要包括网络、内存、处理器、流量。

netstat

主要是用来查看各类网络相关信息。

好比,在压测的过程当中,经过 netstat wc 看下 tcp 链接数是否和服务器 threadpool 设置的匹配。

netstat -tnlp | grep ip | wc -l

若是咱们服务器的 threadpool 设置的是50,那么能够看到 tcp 链接数应该是50才对。而后再经过统计 jstack服务器的 request runing 状态的线程数是否是>=50。

request 线程数的描述信息可能根据使用的 nio 框架的不一样而不一样。

还有使用频率最高的查看系统启动的端口状态、tcp 链接状态是 establelished 仍是 listen 状态。

netstat -tnlp

再配合 ps 命令查看系统启动的状态。这通常用来肯定程序是否真的启动了,若是启动了是否是 listen 的端口与配置中指定的端口不一致。

ps aux | grep ecm-placeorder

netstat 命令很强大有不少功能,若是咱们须要查看命令的其余功能,可使用man netstat 翻看帮助文档。

vmstat

主要用来监控虚拟处理器的运行队列统计信息。

vmstat 1

在压测的时候能够每隔 1s2s 打印一次,能够查看处理器负载是否是太高。procsr 子列就是当前处理器的处理队列,若是这个值超高当前 cpu core 数那么处理器负载将太高。能够和下面将介绍的 top 命令搭配着监控。

同时此命令能够在处理器太高的时候,查看内存是否够用是否出现大量的内存交换,换入换出的量多少 swap si 换入 swap so 换出。是否有很是高的上下文切换 system cs 每秒切换的次数,system us 用户态运行时间是否不多。是否有很是高的 io wait 等等。

关于这个命令网上已经有不少优秀的文章讲解,这里就不浪费时间重复了。一样可使用 man vmstat 命令查看各类用法。

mpstat

主要用来监控多处理器统计信息

mpstat -P ALL 1

 

我这是一个 32 core 的压测服务器,经过 mpstat 能够监控每个虚拟处理器的负载状况。也能够查看总的处理器负载状况。

mpstat 1

能够看到 %idle 处于闲置状态的 cpu 百分比,%user 用户态任务占用的 cpu 百分比,%sys 系统态内核占用 cpu 百分比,%soft 软中断占用 cpu 百分比,%nice 调整任务优先级占用的 cpu 百分比等等。

iostat

主要用于监控io统计信息

iostat 1

若是咱们有大量的 io 操做的话经过 iostat 监控 io 的写入和读取的数据量,同时也能看到在 io 负载特别大的状况下 cpu 的平均负载状况。

top

监控整个系统的总体性能状况top 命令是咱们在平常状况下使用频率最高的,能够对当前系统环境了如指掌。处理器 load 率状况,memory 消耗状况,哪一个 task 消耗 cpumemory 最高。

top

top 命令功能很是丰富,能够分别根据 %MEM%CPU 排序。

load average 域表示 cpu load 率状况,后面三段分别表示最近1分钟、5分钟、15分钟的平均 load 率。这个值不能大于当前 cpu core 数,若是大于说明 cpu load 已经严重太高。就要去查看是否是线程数设置的太高,还要考虑这些任务是否是处理时间太长。设置的线程数与任务所处理的时长有直接关系。

Tasks 域表示任务数状况,total 总的任务数,running 运行中的任务数,sleeping 休眠中的任务数,stopped 暂停中的任务数,zombie 僵尸状态任务数。

Swap 域表示系统的交换区,压测的时候关注 used 是否会持续升高,若是持续升高说明物理内存已经用完开始进行内存页的交换。

free

查看当前系统的内存使用状况

free -m

total 总内存大小,used 已经分配的内存大小,free 当前可用的内存大小,shared 任务之间的共享内存大小,buffers 系统已经分配可是还未使用的,用来存放文件 matedata 元数据内存大小,cached 系统已经分配可是还未使用的,用来存放文件的内容数据的内存大小。

-/+buffer/cache

used 要减去 buffers/cached ,也就是说并无用掉这么多内存,而是有一部份内存用在了 buffers/cached里。

free 要加上 buffers/cached ,也就是说还有 buffers/cached 空余内存须要加上。

Swap 交换区统计,total 交换区总大小,used 已经使用的交换区大小,free 交换区可用大小。只须要关注 used 已经使用的交换区大小,若是这里有占用说明内存已经到瓶颈。

《深刻理解LINUX内核》、《LINUX内核设计与实现》能够放在手边做为参考手册遇到问题翻翻。

性能排查两种方式(从上往下、从下往上)

当系统出现性能问题的时候能够从两个层面来排查问题,从上往下、从下网上,也能够综合运用这两种方法,压测的时候能够同时查看这两个纬度的信息。

一边打开 topfree 观察 cpumemory 的系统级别的消耗状况,同时一边在经过 jstackjstat 之类的工具查看应用程序运行时的内部状态来综合定位。

总结

本篇文章主要仍是从抛砖引玉的角度出发,整理下咱们在作通常性能压测的时候出现的常规问题及排查方法和处理流程,并无多么高深的技术点。

性能问题一旦出现也不会是个简单的问题,都须要花费不少精力来排查问题,运用各类工具、命令来逐步排查,而这些工具和命令所输出的信息都是系统底层原理,须要逐一去理解和实验的,并无一个银弹能解决全部问题。

相关文章
相关标签/搜索