自研长链接压测概览
项目背景
公司的长链接服务器,有以下等缺点:
● 触达率很低
● 没有点对点推送能力
● 排查问题困难
● 只支持m2,不支持mid
而我们商业化的项目众多,且非常依赖长链接服务,因此自研一套长连接系统提供服务,对标公司长链接服务。
压测分析
1
压测目的
新系统上线,确定系统的相关性能指标、性能瓶颈、服务可用性、服务稳定性等
2
压测场景
①. 新系统上线
准确探知系统能力,防止系统上线被流量打垮
②. 性能探测
探测系统中的性能瓶颈点,进行针对性优化
③. 容量规划
对站点进行精细化的容量规划,为系统扩容,性能优化提供数据参考,节省成本投入,提高资源利用率
3
压测策略
①. 基准测试
作为基准,在后续有框架变动/代码变动/业务逻辑变动时,进行对比
②. 负载测试
确定系统的最佳负载和最大负载,合理的进行资源申请
③. 压力测试
确定系统的极限指标
④. 稳定性测试
在略低于最佳负载值下,持续压测5~7d
4
发压策略
①. 线上单机压测时,使用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 也需要动态调整,在并发量较大时,适当调大避免曲线不正常波动带来的不准确性。
用户自定义的变量
用于请求接口添加Header字段
模拟海量不同用户,利用RadomString 函数,构造m2 和 mid 。
m2 ${__RandomString(44,0123456789qwertyuiopasdfghjklzxcvbnm,)}
mid ${__RandomString(32,0123456789qwertyuiopasdfghjklzxcvbnm,)}
处理HTTP接口中字段,按照指定算法进行加密,密文作为Websocker的Header参数
模拟业务逻辑,构造时间间隔
WebSocket request-response Sampler
用于提取响应字段中的内容 url 和 port
用于校验响应中业务逻辑是否符合预期
JMeter抓取数据,传递给influxdb存储,使用grafana展示
jp@gc - Active Threads Over Time
jp@gc - Transactions per Second
jp@gc - Response Times Over Time
Ⅱ. 压测脚本编写
脚本先在GUL模式下运行通过,再进行场景关联、CLI参数化等
Ⅲ. 压测执行
Ⅳ. 问题分析和调优
Ⅴ. 压测报告输出
性能测试报告是性能测试的里程碑,通过报告能展示出性能测试的最终成果,展示系统性能是否符合需求,是否有性能隐患。
⑦. 记录定位瓶颈和调优过程
压测执行的几种方式
本章节概览只展示下几种压测执行方式的运行方式和运行结果展示。
jp@gc - Active Threads Over Time
jp@gc - Transactions per Second
①. 原理
Jmeter分布式测试时,客户端机器(window系统或者Linux服务器)作为一个控制器Master,控制多台slave机器的操作。
②. 配置
③. 执行
在jmeter GUI 中可以通过如下方式调度远程slave 机器执行压测任务
● 菜单项-运行-远程启动,指定运行机器
● 菜单项-运行-远程启动所有,会按照remote host中配置的负载机执行压测。
④. 查看执行结果
⑤. 清理
运行结束后需要手动去停止每个slave节点的进程
CLI 相关参数:
-J 相关的参数,需要结合测试脚本中定义的参数化变量使用的。
jmeter -n -t cljzyycone.jmx -l jtl/x.jtl -e -o report/
-JthreadNum=10 -JrampTime=20 -JstepTime=20 -Jduration=10
master 调度 slave 执行,需要加上 -r 或者 -R 选项
jmeter -n -t cljzyycone.jmx -r -l jtl/x.jtl -e -o report/
-GthreadNum=10 -GrampTime=20 -GstepTime=20 -Gduration=10
调度指定slave 使用 -R host的形式
jmeter -n -t cljzyycone.jmx -R 10.19.1.219 -l jtl/x.jtl -e -o report/
-GthreadNum=10 -GrampTime=20 -GstepTime=20 -Gduration=5
#宿主机运行
jmeter -n -t cljzyycone.jmx -l jtl/cljyc.jtl -e -o report \
-JthreadNum=1000 -JrampTime=10 -JstepTime=20 -Jduration=10
备注:如上的图形是有问题的,已经提交开发查看
当压测目标TPS较高时,需要部署多台linux服务器,但分布式压测要求:
● JMeter压测要求每台机器的基础环境都要相同
更改相同的配置文件(slave要改四个配置文件)
使用docker可以很好的解决以上问题。
概述实现过程
2. 创建JMeter相关的Dockerfile,编写一些build命令、run命令、exec命令的脚本,最终启动 master 容器和 slave 容器。(后续的分章节再介绍这些脚本内容及使用方法)
3. 创建master 和 slave镜像
以创建slave镜像为例
FROM handan0723/jmeter-base:v2
MAINTAINER jmeter-docker
EXPOSE 1099 50000
ENTRYPOINT $JMETER_HOME/bin/jmeter-server \
-Dserver.rmi.ssl.disable=true \
-Dserver.rmi.localport=50000 \
-Dserver_port=1099
②. 构建slave镜像
sh build.sh slave v2
build.sh:
#!/bin/bash
JMETER_VERSION=${JMETER_VERSION:-"5.4.3"}
IMAGE_TIMEZONE=${IMAGE_TIMEZONE:-"Asia/Shanghai"}
build_type=$1
build_tag=$2
docker build \
--build-arg JMETER_VERSION=${JMETER_VERSION} \
--build-arg TZ=${IMAGE_TIMEZONE} \
-f Dockerfile-$build_type \
-t jmeter-$build_type:$build_tag .
涉及的镜像均已上传docker hub,按需使用
[root@localhost jmeter-docker]# docker search handan0723
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
handan0723/jmeter-base v2版本基于handan0723 / jdk8-centos:v4,V1基… 0
handan0723/jmeter-master v2 0
handan0723/jmeter-slave v2 0
handan0723/jdk8-centos v1-v3对应dockerfile 是使用jdk安装的,v4使用y… 0
4. 生成容器
sh runmaster.sh 1 60000
sh runslave.sh 1 1100 1099 50000 50000
sh runslave.sh 2 1101 1099 50001 50000
每个slave生成容器时,要更换宿主机开放给容器的端口,如50000,50001递增
[root@localhost jmeter-docker]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f83d8339616f jmeter-slave:v2 "/bin/sh -c '$JMETER…" About a minute ago Up About a minute 0.0.0.0:1101->1099/tcp, :::1101->1099/tcp, 0.0.0.0:50001->50000/tcp, :::50001->50000/tcp jmeter-cljyc-slave-2
3e8b366dedce jmeter-slave:v2 "/bin/sh -c '$JMETER…" About a minute ago Up About a minute 0.0.0.0:50000->50000/tcp, :::50000->50000/tcp, 0.0.0.0:1100->1099/tcp, :::1100->1099/tcp jmeter-cljyc-slave-1
1ca4b3011cc1 prom/prometheus:latest "/bin/prometheus --c…" 3 days ago Up 3 days 0.0.0.0:9090->9090/tcp, :::9090->9090/tcp jk_prometheus
1d838551945b google/cadvisor:latest "/usr/bin/cadvisor -…" 3 days ago Up 3 days 8080/tcp, 0.0.0.0:8081->8081/tcp, :::8081->8081/tcp jk_cadvisor
31b549fc8611 grafana/grafana:latest "/run.sh" 3 days ago Up 3 days 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp jk_grafana
9ce0dc4eaf22 redis:latest "docker-entrypoint.s…" 3 days ago Up 3 days 0.0.0.0:6380->6379/tcp, :::6380->6379/tcp jk_redis
e6d0f1331947 influxdb:1.8.10 "/entrypoint.sh infl…" 3 days ago Up 3 days 0.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/tcp jk_influxdb
39e01d546376 jmeter-master:v2 "/bin/bash" 9 days ago Up 9 hours 0.0.0.0:60000->60000/tcp, :::60000->60000/tcp jmeter-cljyc-master-1
docker inspect --format '{{ .Name }} => {{ .NetworkSettings.IPAddress }}' $( docker ps -a -q)
6. 进入master容器
docker exec -it jmeter-cljyc-master-1 /bin/bash
执行CLI命令,根据压测目标TPS,调整阶梯数值
jmeter -n -t ./jmx/cljzyycone.jmx \
-R 172.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
调度2台slave
对比下执行结果,我们脚本中要求的并发数10,不是两台共同完成10,而是每台都按照并发10去执行。因此可以实现加压的初始目的。
监控系统
在压测过程中,通过HTML报告可以查阅压测结果。但是只能在压测流程结束后,才能查看指标数据。无法观测执行过程中的异常波动,不具备实时性。如果使用Basic Graphs插件,因jmeter不擅长图形绘制,这样的组件极其耗损性能,影响压测执行及压测结果的准确性。
因此需要使用监控系统,更及时准确的监控整个压测过程。
1. 监控系统组成
jmeter:压测执行及数据采集
InfluxDB:分布式时序、事件和指标数据库
Prometheus:时序数据库
2. 实现原理
采集 -- 通过JMeter 中配置Backend Listener去实时采集数据
存储 -- 在 InfluxDB 中进行相关配置,存储采集来的数据
展示 -- 在 Grafana 中进行相关配置,存储采集来的数据存储 -- 在 InfluxDB 中进行相关配置,存储采集来的数据存储 -- 在 InfluxDB 中进行相关配置,存储采集来的数据存储 -- 在 InfluxDB 中进行相关配置,存储采集来的数据存储 -- 在 InfluxDB 中进行相关配置,存储采集来的数据存储 -- 在 InfluxDB 中进行相关配置,存储采集来的数据
3. 监控系统搭建方式
windows环境搭建 JMeter + influxdb/prometheus + grafana 监控系统,展示效果如下
[root@localhost jkxt]# docker-compose up -d
Creating jk_redis ... done
Creating jk_cadvisor ... done
Creating jk_prometheus ... done
Creating jk_influxdb ...
Creating jk_redis ...
Creating jk_cadvisor ...
Creating jk_prometheus ...
[root@localhost jkxt]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
280c447c1e97 prom/prometheus:latest "/bin/prometheus --c…" 2 minutes ago Up 2 minutes 0.0.0.0:9090->9090/tcp, :::9090->9090/tcp jk_prometheus
a00db4de47da google/cadvisor:latest "/usr/bin/cadvisor -…" 2 minutes ago Up 2 minutes 8080/tcp, 0.0.0.0:8081->8081/tcp, :::8081->8081/tcp jk_cadvisor
5c04c5ebc022 redis:latest "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 0.0.0.0:6380->6379/tcp, :::6380->6379/tcp jk_redis
9edb14c81e3c grafana/grafana:latest "/run.sh" 2 minutes ago Up 2 minutes 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp jk_grafana
c582e8e25dee influxdb:1.8.10 "/entrypoint.sh infl…" 2 minutes ago Up 2 minutes 0.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/tcp jk_influxdb
简化管理:虽然不像微服务架构动辄几十服务,监控系统涉及服务要是单独管理还是比较麻烦的,手动启停维护工作量较大。
解决服务依赖性问题:监控系统服务存在依赖关系,需要相互配合才能实现监控系统的功能。
可移植性:只需要编写一份docker-compse.yml,及提供相应服务的配置文件,可以快速移植到任何需要监控的服务器中
总结
以上内容是压测的一次概要描述,主要用于了解本次压测的背景,业务逻辑,压测指标,压测工具、压测流程 及 压测执行方式。
后续会针对具体场景进行详细实现的描述,具体拆解如下。
分享给第一个想到的人