|
项目背景公司的长链接服务器,有以下等缺点:● 触达率很低● 没有点对点推送能力● 排查问题困难● 只支持m2,不支持mid而我们商业化的项目众多,且非常依赖长链接服务,因此自研一套长连接系统提供服务,对标公司长链接服务。压测分析1压测目的新系统上线,确定系统的相关性能指标、性能瓶颈、服务可用性、服务稳定性等2压测场景①. 新系统上线准确探知系统能力,防止系统上线被流量打垮②. 性能探测探测系统中的性能瓶颈点,进行针对性优化③. 容量规划对站点进行精细化的容量规划,为系统扩容,性能优化提供数据参考,节省成本投入,提高资源利用率3压测策略①. 基准测试作为基准,在后续有框架变动/代码变动/业务逻辑变动时,进行对比②. 负载测试确定系统的最佳负载和最大负载,合理的进行资源申请③. 压力测试确定系统的极限指标④. 稳定性测试在略低于最佳负载值下,持续压测5~7d4发压策略①. 线上单机压测时,使用1台发压机;超过1000TPS时,使用分布式发压②. 集群压测时,使用多台机器进行分布式压测压测指标预估备注本次RT时间 以TP95 为标准因新业务上线,无真实流量,无法确定峰值QPS,需要进行TPS估算TPS估算估算1按照10亿用户,按照八二原则,计算TPS需要到~~46300,有20台机器,单机达到2500即可。估算2初次放量,按照100w用户 20台机器估算,根据八二原则,单机TPS均值:10 qps,峰值:50 qps。01业务指标02资源指标● CPU使用率(时间):不高于75%-85%● 内存 RAM(大小)使用率:不高于80%观察内存是否有尖刺或泄露● 磁盘I/O(速率) :不高于90%● 网络I/O(速率):不高于80%03中间件监控指标防火墙● 无防火墙ngnix● 带宽● 配置是否正确redis● 缓存穿透、击穿、雪崩mysql -- 本次压测不涉及● 慢查询● 线程阻塞● 死锁● 无索引导致全表查询04使用的第三方业务● 不涉及第三方压测流程1. 需求分析熟悉需求、获取性能需求指标①. 明确被测系统 及 压测场景②. 明确测试内容③. 明确测试策略④. 明确测试指标2. 压测方案制定 与 评审综合以上一~四的内容,加上压测机器信息,压测周知,编写压测方案,编写完成后召集相关人员进行压测方案评审,方案内容大纲如下:备注:当服务器涉及到容器云和HULK时,需要提前与相关方确认,提供压测的TPS,确认压测的执行时间,防止影响其他业务线。3. 测试用例设计与压测脚本编写本次涉及http接口和websocket接口Ⅰ. 压测组件选择根据压测涉及接口 及 模拟业务场景的需要,进行最小化的组件选择。● 测试计划● 线程组压测进行梯度压测,标准线程组需要频繁更改CLI命令,因此直接使用了并发线程组。并发线程组配置采用参数化方式,在Linux / Docker中执行时,可以直接使用CLI传入并发数,省去频繁更改脚本的麻烦。Ramp Up Time 与 Ramp Steps Count 也需要动态调整,在并发量较大时,适当调大避免曲线不正常波动带来的不准确性。●配置元件用户自定义的变量采用该组件记录全局参数HTTP信息头管理器用于请求接口添加Header字段●前置处理器用户参数组件模拟海量不同用户,利用RadomString 函数,构造m2 和 mid 。m2${__RandomString(44,0123456789qwertyuiopasdfghjklzxcvbnm,)}mid${__RandomString(32,0123456789qwertyuiopasdfghjklzxcvbnm,)}该组件一定要放入并发线程组中,才能模拟每次发起请求是不同的用户BeanShell 前置处理器处理HTTP接口中字段,按照指定算法进行加密,密文作为Websocker的Header参数● 定时器模拟业务逻辑,构造时间间隔● 取样器HTTP取样器WebSocket 取样器WebSocket Open ConnectionWebSocket request-response Sampler● 后置处理器JSON提取器用于提取指定字段,用于传递下一接口或者做接口断言正则表达式提取器用于提取响应字段中的内容 url 和 port● 断言响应断言用于校验接口请求是否成功Json断言用于校验响应中业务逻辑是否符合预期● 监听器后端监听器JMeter抓取数据,传递给influxdb存储,使用grafana展示● 其他组件(调试脚本时添加,真正压测时要去掉)查看结果树调试取样器汇总报告(主要关注方差指标)聚合报告jp@gc - Active Threads Over Timejp@gc - Transactions per Secondjp@gc - Response Times Over TimeⅡ. 压测脚本编写脚本先在GUL模式下运行通过,再进行场景关联、CLI参数化等Ⅲ. 压测执行①. 搭建压测环境根据压测TPS不同,选择不同的压测执行环境②. 执行测试脚本根据压测环境的不同,压测执行方式也是不同的windows GUI 压测执行windows 分布式压测执行windows CLI 压测执行Linux CLI 压测执行基于Dokcer的分布式压测执行③. 测试结果记录最后的压测报告生成,以及后续做对比基准使用Ⅳ. 问题分析和调优由于本次发现的几个问题均与性能瓶颈无关,这里就不列举了。Ⅴ. 压测报告输出性能测试报告是性能测试的里程碑,通过报告能展示出性能测试的最终成果,展示系统性能是否符合需求,是否有性能隐患。注意包含以下几方面:①. 压测背景、目的、目标②. 参与人、时间跨度③. 施压环境 及 施压工具④. 数据构造方法⑤. 压测策略⑥. 压测执行过程记录⑦. 记录定位瓶颈和调优过程压测执行的几种方式具体使用哪种方式,是根据压测TPS和申请到的资源决定的。几种压测方式的搭建过程 以及 优缺点,会在拆解的详细章节中讲述。本章节概览只展示下几种压测执行方式的运行方式和运行结果展示。1windows GUI 压测执行● JMeter官方提示:不要使用GUI模式进行负载测试!只有在测试调试或者测试用例设定或者生成的时候才用GUI模式。● GUI模式带来性能损耗,不适合500以上并发的压测执行● 在windows JMeter中直接执行时,需要配置上以下组件,以便观察结果查看结果树调试取样器汇总报告聚合报告jp@gc - Active Threads Over Timejp@gc - Transactions per Secondjp@gc - Response Times Over Time备注:JMeter本身的问题导致结束时无法优雅关闭,忽略最后的错误即可。2windows 分布式压测执行 - GUI方式①. 原理Jmeter分布式测试时,客户端机器(window系统或者Linux服务器)作为一个控制器Master,控制多台slave机器的操作。②. 配置具体的master 和 slave 的配置,会在分篇章中详细描述。不影响理解主线流程。③. 执行在jmeter GUI 中可以通过如下方式调度远程slave 机器执行压测任务● 菜单项-运行-远程启动,指定运行机器● 菜单项-运行-远程启动所有,会按照remote host中配置的负载机执行压测。④. 查看执行结果⑤. 清理运行结束后需要手动去停止每个slave节点的进程3windows CLI 压测执行CLI 相关参数:-n 表示使用非GUI的方式运行-t 表示指定jmeter的测试脚本-l 表示生成指定的报告文件-e 表示生成html报告-o html报告输出的路径-J 相关的参数,需要结合测试脚本中定义的参数化变量使用的。①. 本机执行脚本jmeter-n-tcljzyycone.jmx-ljtl/x.jtl-e-oreport/-JthreadNum=10-JrampTime=20-JstepTime=20-Jduration=10查看控制台和生成的报告-本机执行②. 远程调度执行脚本master 调度 slave 执行,需要加上 -r 或者 -R 选项调度全部slave 使用 -rjmeter-n-tcljzyycone.jmx-r-ljtl/x.jtl-e-oreport/-GthreadNum=10-GrampTime=20-GstepTime=20-Gduration=10调度指定slave 使用 -R host的形式jmeter-n-tcljzyycone.jmx-R10.19.1.219-ljtl/x.jtl-e-oreport/-GthreadNum=10-GrampTime=20-GstepTime=20-Gduration=5查看控制台-远程调度执4windows CLI 压测执行①. Linux 上安装JMeter①. Linux 上安装JMeter②. 创建压测目录,存放压测脚本和测试报告③. docker-compose up 启动监控系统的几个service④. 执行压测脚本#宿主机运行jmeter-n-tcljzyycone.jmx-ljtl/cljyc.jtl-e-oreport\-JthreadNum=1000-JrampTime=10-JstepTime=20-Jduration=105windows CLI 压测执行备注:如上的图形是有问题的,已经提交开发查看6基于Dokcer实现 JMeter的分布式压测执行当压测目标TPS较高时,需要部署多台linux服务器,但分布式压测要求:● JMeter压测要求每台机器的基础环境都要相同每台机器都要先安装相同的java环境再安装相同版本的JMeter配置相同JMeter 插件更改相同的配置文件(slave要改四个配置文件)● 每台slave都需要单独的安装配置,如果有变动,需要按个操作一遍● 每台slave 需要打开指定的端口并运行JMeter服务器,准备就绪并等待主服务器发送指令。● 数据驱动文件每台机器都要上传一份,且要保证路径相同,有变动的话需要全部重新上传一遍● 执行压测时,进行统一调度比较繁琐(每台机器都要指定端口号)使用docker可以很好的解决以上问题。概述实现过程1. 创建基于centos7的java8 Dockerfile,作为jmeter的父层级official的java8镜像是基于dibian系统,在公司即使配置了国内源,仍然下载漫长又容易失败。因此定制一个基于centos7的 java8镜像,同时集成进一些常用包2. 创建JMeter相关的Dockerfile,编写一些build命令、run命令、exec命令的脚本,最终启动 master 容器和 slave 容器。(后续的分章节再介绍这些脚本内容及使用方法)3. 创建master 和 slave镜像以创建slave镜像为例①. 编写Dockerfile-slaveFROMhandan0723/jmeter-base:v2MAINTAINERjmeter-dockerEXPOSE109950000ENTRYPOINT$JMETER_HOME/bin/jmeter-server\-Dserver.rmi.ssl.disable=true\-Dserver.rmi.localport=50000\-Dserver_port=1099②. 构建slave镜像shbuild.shslavev2build.sh:#!/bin/bashJMETER_VERSION=${JMETER_VERSION:-"5.4.3"}IMAGE_TIMEZONE=${IMAGE_TIMEZONE:-"Asia/Shanghai"}build_type=$1build_tag=$2dockerbuild\--build-argJMETER_VERSION=${JMETER_VERSION}\--build-argTZ=${IMAGE_TIMEZONE}\-fDockerfile-$build_type\-tjmeter-$build_typebuild_tag.涉及的镜像均已上传docker hub,按需使用[root@localhostjmeter-docker]#dockersearchhandan0723NAMEDESCRIPTIONSTARSOFFICIALAUTOMATEDhandan0723/jmeter-basev2版本基于handan0723/jdk8-centos:v4,V1基…0handan0723/jmeter-masterv20handan0723/jmeter-slavev20handan0723/jdk8-centosv1-v3对应dockerfile是使用jdk安装的,v4使用y…04. 生成容器shrunmaster.sh160000shrunslave.sh1110010995000050000shrunslave.sh2110110995000150000备注:每个slave生成容器时,要更换宿主机开放给容器的端口,如50000,50001递增slave容器数据卷可以只保留log目录和testdata目录,其他非必须。log目录用于存放日志,便于发生错误时进行问题定位;testdata用户存放数据驱动文件。[root@localhostjmeter-docker]#dockerps-aCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMESf83d8339616fjmeter-slave:v2"/bin/sh-c'$JMETER…"AboutaminuteagoUpAboutaminute0.0.0.0:1101->1099/tcp,:::1101->1099/tcp,0.0.0.0:50001->50000/tcp,:::50001->50000/tcpjmeter-cljyc-slave-23e8b366dedcejmeter-slave:v2"/bin/sh-c'$JMETER…"AboutaminuteagoUpAboutaminute0.0.0.0:50000->50000/tcp,:::50000->50000/tcp,0.0.0.0:1100->1099/tcp,:::1100->1099/tcpjmeter-cljyc-slave-11ca4b3011cc1prom/prometheus:latest"/bin/prometheus--c…"3daysagoUp3days0.0.0.0:9090->9090/tcp,:::9090->9090/tcpjk_prometheus1d838551945bgoogle/cadvisor:latest"/usr/bin/cadvisor-…"3daysagoUp3days8080/tcp,0.0.0.0:8081->8081/tcp,:::8081->8081/tcpjk_cadvisor31b549fc8611grafana/grafana:latest"/run.sh"3daysagoUp3days0.0.0.0:3000->3000/tcp,:::3000->3000/tcpjk_grafana9ce0dc4eaf22redis:latest"docker-entrypoint.s…"3daysagoUp3days0.0.0.0:6380->6379/tcp,:::6380->6379/tcpjk_redise6d0f1331947influxdb:1.8.10"/entrypoint.shinfl…"3daysagoUp3days0.0.0.0:8083->8083/tcp,:::8083->8083/tcp,0.0.0.0:8086->8086/tcp,:::8086->8086/tcp,0.0.0.0:8090->8090/tcp,:::8090->8090/tcpjk_influxdb39e01d546376jmeter-master:v2"/bin/bash"9daysagoUp9hours0.0.0.0:60000->60000/tcp,:::60000->60000/tcpjmeter-cljyc-master-15. 查看容器ip此处IP查询结果,用户master cli命令行中控制slave使用dockerinspect--format'{{.Name}}=>{{.NetworkSettings.IPAddress}}'$(dockerps-a-q)6. 进入master容器dockerexec-itjmeter-cljyc-master-1/bin/bash执行CLI命令,根据压测目标TPS,调整阶梯数值jmeter-n-t./jmx/cljzyycone.jmx\-R172.17.0.3:1099,172.17.0.4:1099\-l./jtl/cljyc.jtl\-e-o./report\-j./log/jmeter-master.log\-GthreadNum=10-GrampTime=10-GstepTime=10-Gduration=50调度一台slave调度2台slave对比下执行结果,我们脚本中要求的并发数10,不是两台共同完成10,而是每台都按照并发10去执行。因此可以实现加压的初始目的。监控系统在压测过程中,通过HTML报告可以查阅压测结果。但是只能在压测流程结束后,才能查看指标数据。无法观测执行过程中的异常波动,不具备实时性。如果使用Basic Graphs插件,因jmeter不擅长图形绘制,这样的组件极其耗损性能,影响压测执行及压测结果的准确性。因此需要使用监控系统,更及时准确的监控整个压测过程。具体的组件交互原理,环境搭建方式,配置过程,将会在单独的篇章中详细列出。概览只讲述组件构成,及使用方式。1. 监控系统组成jmeter:压测执行及数据采集InfluxDB:分布式时序、事件和指标数据库Prometheus:时序数据库Grafana:开源WEB可视化平台2. 实现原理采集 -- 通过JMeter 中配置Backend Listener去实时采集数据存储 -- 在 InfluxDB 中进行相关配置,存储采集来的数据展示 -- 在Grafana中进行相关配置,存储采集来的数据存储 -- 在 InfluxDB 中进行相关配置,存储采集来的数据存储 -- 在 InfluxDB 中进行相关配置,存储采集来的数据存储 -- 在 InfluxDB 中进行相关配置,存储采集来的数据存储 -- 在 InfluxDB 中进行相关配置,存储采集来的数据存储 -- 在 InfluxDB 中进行相关配置,存储采集来的数据3. 监控系统搭建方式windows环境搭建 JMeter + influxdb/prometheus + grafana 监控系统,展示效果如下启动容器[root@localhostjkxt]#docker-composeup-dCreatingjk_redis...doneCreatingjk_cadvisor...doneCreatingjk_prometheus...doneCreatingjk_influxdb...Creatingjk_redis...Creatingjk_cadvisor...Creatingjk_prometheus...[root@localhostjkxt]#dockerpsCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES280c447c1e97prom/prometheus:latest"/bin/prometheus--c…"2minutesagoUp2minutes0.0.0.0:9090->9090/tcp,:::9090->9090/tcpjk_prometheusa00db4de47dagoogle/cadvisor:latest"/usr/bin/cadvisor-…"2minutesagoUp2minutes8080/tcp,0.0.0.0:8081->8081/tcp,:::8081->8081/tcpjk_cadvisor5c04c5ebc022redis:latest"docker-entrypoint.s…"2minutesagoUp2minutes0.0.0.0:6380->6379/tcp,:::6380->6379/tcpjk_redis9edb14c81e3cgrafana/grafana:latest"/run.sh"2minutesagoUp2minutes0.0.0.0:3000->3000/tcp,:::3000->3000/tcpjk_grafanac582e8e25deeinfluxdb:1.8.10"/entrypoint.shinfl…"2minutesagoUp2minutes0.0.0.0:8083->8083/tcp,:::8083->8083/tcp,0.0.0.0:8086->8086/tcp,:::8086->8086/tcp,0.0.0.0:8090->8090/tcp,:::8090->8090/tcpjk_influxdb配置好各个服务后,在浏览器中打开监控页面4. 监控系统为什么使用Docke-compose简化管理:虽然不像微服务架构动辄几十服务,监控系统涉及服务要是单独管理还是比较麻烦的,手动启停维护工作量较大。解决服务依赖性问题:监控系统服务存在依赖关系,需要相互配合才能实现监控系统的功能。可移植性:只需要编写一份docker-compse.yml,及提供相应服务的配置文件,可以快速移植到任何需要监控的服务器中总结以上内容是压测的一次概要描述,主要用于了解本次压测的背景,业务逻辑,压测指标,压测工具、压测流程 及 压测执行方式。后续会针对具体场景进行详细实现的描述,具体拆解如下。分享给第一个想到的人
|
|