为什么需要分布式压测
在压测工作中我们经常遇见对一些关键接口需要压测到很高的QPS,这时候我们需要设置更多的线程去模拟虚拟用户去请求接口,假如我们需要模拟20000个用户,在单台机器很难模拟20000个用户,因为Jmeter是用Java语言开发,每创建一个线程,JVM默认会为每个线程分配1M的堆栈内存空间,这里只计算所需要的内存就需要20G的内存。一般我们的施压机器配置是4核8G或者8核16G的,此时我们需要多台机器共同完成施压请求。
分布式压测一键部署
分布式压测架构示意图如下图所示
Jmeter分布式测试环境中有两个角色:Master和Slaves
- Master节点:向参与的Slaves节点发送测试脚本,并聚合Agent节点的执行结果,部署一台
- Slaves节点:接收并执行Master节点发送过来的测试脚本,并将执行结果返回给Master,可部署多台
部署前置条件,你的机器上已经安装了Docker
下载Master节点:docker pull runcare/jmeter-master
下载Slaves节点:docker pull runcare/jmeter-slave
分布式压测使用
- 启动Slaves节点,这里假如我们启动三台机器
docker run -it -d --name slave01 runcare/jmeter-slave
docker run -it -d --name slave02 runcare/jmeter-slave
docker run -it -d --name slave03 runcare/jmeter-slave
- 准备一个测试脚本文件test.jmx
- 查看一下Slaves机器的IP地址
docker inspect -f '{{ .Name }} => {{ .NetworkSettings.IPAddress }}' $(docker ps -q)
- Master机器发送脚本
/Users/eleme/Downloads/jmeter-master 是你脚本test.jmx所在的目录
result=`date +"%Y%m%d%H%M%S"` && docker run --rm -v /Users/eleme/Downloads/jmeter-master:/data a4789222b813 jmeter -n -t /data/test.jmx -l /data/$result.jtl -j /data/$result.log -e -o /data/$result -R 172.17.0.2,172.17.0.3,172.17.0.4
或者
docker run --rm -v $(pwd):/data 20cb9e02cfe8 jmeter -n -t /data/aggregation.jmx -l /data/result.jtl -j /data/result.log -R 172.17.0.2,172.17.0.3
- 生产的结果文件,日志文件和报表文件在脚本文件test.jmx同一目录下
- 如果压测脚本中使用到了csv数据源文件,需要提前复制到Slaves的/data目录下
注意事项
- Master和Slaves需要在同一网段,如果mac电脑Master使用安装在mac电脑中的Jmeter,Slaves使用Docker中的Slaves,需要在启动Slaves时将端口映射出来
docker run -it -d -p 1099:1099 -p 60001:60001 runcare/jmeter-slave
- 执行Master发送脚本时也需要指定server.hostname和server.rmi.localport
进入test.jmx所在目录
result=`date +"%Y%m%d%H%M%S"` && jmeter -n -t test.jmx -l $result.jtl -j $result.log -e -o $result -Djava.rmi.server.hostname=30.208.47.45 -Dserver.rmi.localport=60002 -Dserver_port=1098
Master和Slaves制作附件
- Master制作的Dockerfile
# oracle jdk 1.8 备用
#FROM runcare/debian-jre1.8
# openjdk 1.8
FROM runcare/openjdk-jre1.8
# 更新版本1
MAINTAINER runcare<larrygui@foxmail.com>
ARG JMETER_VERSION="5.1.1"
ENV JMETER_HOME /opt/apache-jmeter-$JMETER_VERSION
ENV JMETER_DOWNLOAD_URL https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-$JMETER_VERSION.tgz
ENV SSL_DISABLED true
RUN mkdir -p /tmp/dependencies \
&& curl -L --silent $JMETER_DOWNLOAD_URL > /tmp/dependencies/apache-jmeter-$JMETER_VERSION.tgz \
&& mkdir -p /opt \
&& tar -xzf /tmp/dependencies/apache-jmeter-$JMETER_VERSION.tgz -C /opt \
&& rm -rf /tmp/dependencies
# TODO: plugins (later)
# && unzip -oq "/tmp/dependencies/JMeterPlugins-*.zip" -d $JMETER_HOME
# Set global PATH such that "jmeter" command is found
ENV PATH $PATH:$JMETER_HOME/bin
VOLUME ["/data"]
WORKDIR $JMETER_HOME
RUN sed 's/#server.rmi.ssl.disable=false/server.rmi.ssl.disable=true/g' ./bin/jmeter.properties > ./bin/jmeter_temp.properties
RUN mv ./bin/jmeter_temp.properties ./bin/jmeter.properties
- Slaves制作的Dockerfile
# oracle jdk 1.8 备用
#FROM runcare/debian-jre1.8
# openjdk 1.8
FROM runcare/openjdk-jre1.8
# 更新版本1
MAINTAINER runcare<larrygui@foxmail.com>
ARG JMETER_VERSION="5.1.1"
ENV JMETER_HOME /opt/apache-jmeter-$JMETER_VERSION
ENV JMETER_DOWNLOAD_URL https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-$JMETER_VERSION.tgz
ENV SSL_DISABLED true
RUN mkdir -p /tmp/dependencies \
&& curl -L --silent $JMETER_DOWNLOAD_URL > /tmp/dependencies/apache-jmeter-$JMETER_VERSION.tgz \
&& mkdir -p /opt \
&& tar -xzf /tmp/dependencies/apache-jmeter-$JMETER_VERSION.tgz -C /opt \
&& rm -rf /tmp/dependencies
# TODO: plugins (later)
# && unzip -oq "/tmp/dependencies/JMeterPlugins-*.zip" -d $JMETER_HOME
# Set global PATH such that "jmeter" command is found
ENV PATH $PATH:$JMETER_HOME/bin
VOLUME ["/data"]
WORKDIR $JMETER_HOME
EXPOSE 1099 60001
ENTRYPOINT jmeter-server -Dserver.rmi.localport=60001 -Dserver_port=1099 \
-Jserver.rmi.ssl.disable=$SSL_DISABLED