1.环境搭建

参考:

https://www.runoob.com/docker/docker-tutorial.html


2.配置信息

服务器:华为云服务器ECS,虚拟私有云VPC

docker版本:20.10.7

jmeter版本:apache-jmeter-4.0

jkd:runcare/openjdk-jre1.8 # 公共镜像

3.实现原理

# VPC中放开所有端口,避免因为端口没有放开,主机之间无法通信

docker 测试网页 docker压力测试_docker 测试网页

4.镜像制作

master机器的Dockerfile:

# 引入公共的java1.8镜像
FROM runcare/openjdk-jre1.8

# 作者名称
MAINTAINER xxx

# 自定义变量,可以变更jmeter版本、路径、下载地址、内存容量等
ARG JMETER_VERSION="4.0"
ENV JMETER_HOME /opt/apache-jmeter-${JMETER_VERSION}
ENV JMETER_BIN ${JMETER_HOME}/bin
# 如果下载很慢,可以把jmeter在本地下载下来,上传到可以公开下载的网站上,然后把下载网址替换一下就行了
ENV JMETER_DOWNLOAD_URL https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-$JMETER_VERSION.tgz

# 可以修改jmeter服务的运行内存,一般建议在没有其他消耗的情况下,压力机物理内存的一半
ENV Xms 1g
ENV Xmx 1g
ENV MaxMetaspaceSize 512m

# 如果无法保证机器的时间是一致的可以执行下面的命令
# ENV TZ="Europe/Bucharest"
# RUN export TZ=$TZ
# 解压jmeter,路径可以自己配
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

# 设置jmeter的环境变量
ENV PATH $PATH:$JMETER_BIN

# 定义一个用户卷,可以实现本地文件夹映射
VOLUME ["/data"]


# 初学建议不用WORKDIR 容易找不到路径,把自己绕晕了,都使用绝对路径就好
# WORKDIR    $JMETER_HOME

# 脚本中声明要开通的端口,对容器没有设计影响
EXPOSE 60000

# 复制entrypoint.sh文件到容器的根目录
COPY entrypoint.sh /

RUN chmod +x ./entrypoint.sh
# 指定运行的程序

ENTRYPOINT ["/entrypoint.sh"]

 master机器的entrypoint.sh

#!/bin/bash
# step1启动容器的时候,通过定义变量来指定jmeter的运行内存
# step2修改jmeter.properties的server.rmi.ssl.disable属性
sed -i 's/\("${HEAP:="\)\(.*\)\("}"\)/\1-Xms'${Xms}' -Xmx'${Xmx}' -XX:MaxMetaspaceSize='${MaxMetaspaceSize}'\3/' ${JMETER_BIN}/jmeter &&
sed 's/#server.rmi.ssl.disable=false/server.rmi.ssl.disable=true/g' /opt/apache-jmeter-4.0/bin/jmeter.properties > /opt/apache-jmeter-4.0/bin/jmeter_temp.properties &&
mv /opt/apache-jmeter-4.0/bin/jmeter_temp.properties /opt/apache-jmeter-4.0/bin/jmeter.properties
exec "$@"

server机器的Dockerfile

# 引入公共的java1.8镜像
FROM runcare/openjdk-jre1.8

MAINTAINER xxx

ARG JMETER_VERSION="4.0"
# Set JMeter related environment variables
ENV JMETER_HOME /opt/apache-jmeter-${JMETER_VERSION}
ENV JMETER_BIN ${JMETER_HOME}/bin
ENV JMETER_DOWNLOAD_URL https://archive.apache.org/dist/jmeter/binaries/apache-jmeter-$JMETER_VERSION.tgz

ENV Xms 1g
ENV Xmx 1g
ENV MaxMetaspaceSize 512m

# ENV TZ="Europe/Bucharest"
# RUN export TZ=$TZ
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


ENV PATH $PATH:$JMETER_BIN

VOLUME ["/data"]

# WORKDIR    $JMETER_HOME


EXPOSE 1099 50000

COPY entrypoint.sh /

RUN chmod +x ./entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

server机器的entrypoint.sh

#!/bin/bash
# 启动容器之后,启动jmeter-server服务,指定服务端口1099,监听端口50000
# 容器有自己的IP,需要更新容器的IP为本机的内网IP
sed -i 's/\("${HEAP:="\)\(.*\)\("}"\)/\1-Xms'${Xms}' -Xmx'${Xmx}' -XX:MaxMetaspaceSize='${MaxMetaspaceSize}'\3/' ${JMETER_BIN}/jmeter &&
sed 's/#server.rmi.ssl.disable=false/server.rmi.ssl.disable=true/g' /opt/apache-jmeter-4.0/bin/jmeter.properties > /opt/apache-jmeter-4.0/bin/jmeter_temp.properties &&
mv /opt/apache-jmeter-4.0/bin/jmeter_temp.properties /opt/apache-jmeter-4.0/bin/jmeter.properties &&
$JMETER_HOME/bin/jmeter-server \
-Dserver.rmi.localport=50000 \
-Dserver_port=1099 \
-Djava.rmi.server.hostname=$HostIP &&
exec "$@"

server机器的启动命令

# 定义HostIP,entrypoint.sh就引用这个IP
# 需要注意主机的网卡类型,参考
# 通过-p命令进行端口映射,容器端口:主机端口/传输协议(端口、协议可根据实际使用指定)
HostIP=$(ip addr | awk '/^[0-9]+: / {}; /inet.*global.*eth/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}') \
&& docker run -it --name server01 -e HostIP=$HostIP -e Xms=256m -e Xmx=512m -e MaxMetaspaceSize=512m -p 1099:1099/tcp -p 50000:50000/tcp servertest1:latest /bin/bash

master机器的启动命令

docker run -it --name server -e Xms=256m -e Xmx=512m -e MaxMetaspaceSize=512m -p 1099:1099/tcp -p 50000:50000/tcp -p 60000:60000/tcp mastertest:latest /bin/bash

master机器运行jmeter脚本命令

# 运行脚本之前,先准备测试用到的jmx、csv文件,复制到镜像里面去,注意路径正确,jmx内的csv文件用容器中的路径
# jmx文件可以不用复制到server机器里面,csv每台机器用的不一样还是需要手动复制的,当然也有其他更优雅的方式
# 在容器内运行以下命令,HostIP在容器外获取
# -Dclient.rmi.localport指定监听端口
jmeter -n -t /data/test.jmx -Djava.rmi.server.hostname='master机器的HostIP' -Dclient.rmi.localport=60000 -R 'server1机器的HostIP','server2机器的HostIP'
 
# 直接容器外启动
# -v映射文件夹
# --rm选项,容器退出时自动清理容器内部的文件
待补充……

常用命令

# 关闭所有容器
sudo docker stop $(sudo docker ps -a -q)

# 删除所有容器
sudo docker rm $(sudo docker ps -a -q)

# 查看容器ID
docker ps | grep 容器名称

# 复制文件到容器
docker cp /文件的路径/test.jmx 容器ID:/要复制到的路径

# 查看镜像
docker images

# 容器内查看配置是否修改
cat ${JMETER_BIN}/jmeter.properties | grep server.rmi.ssl.disable

# docker启动、停止
systemctl start docker
systemctl stop docker

# 打包镜像
docker build -t mastertest .

这只是多机情况下实现分布式压测的一个简单实例,还有很多可以优化的地方,待补充……

参考文档:

https://cloud.tencent.com/developer/article/1601081