专业的编程技术博客社区

网站首页 > 博客文章 正文

基于Docker的jmeter弹性压测(1)发压

baijin 2024-10-19 02:40:20 博客文章 11 ℃ 0 评论

使用JMeter进行压测,实际应用中一般有如下方式:

  • 单机版压测,即在一台性能还可以的机器进行上进行单机发压
  • 分布式压测,即使用jmeter自带的remote distributing进行压测,需要一台主控机,n台slave,实际压测的执行在slave节点上进行,在执行过程中,各slave节点的压测结果回传给master机进行汇总
  • 另外一种分布式压测,就是起n个slave,每个slave自行进行压测,压测结束之后,将结果进行汇总展示或者使用其他方式进行展示

单机版压测的不足显而易见:发压能力不足,再好的单机也受限于其自身的物理配置和带宽;分布式压测的缺点在于受控节点的维护与结果回传对带宽的占用;多节点压测结果汇总的难点在于节点的创建、维护与任务调度。

而随着docker技术的应用,能够完美解决方式三节点的难题。

justb4/jmeter

justb4/jmeter提供了基于docker的jmeter压测镜像,其github地址为https://github.com/justb4/docker-jmeter,docker hub地址为https://hub.docker.com/r/justb4/jmeter。

首先我们来看下其dockerfile:

FROM alpine:3.9
MAINTAINER Just van den Broecke<just@justobjects.nl>
ARG JMETER_VERSION="5.1.1"
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
# Install extra packages
# See https://github.com/gliderlabs/docker-alpine/issues/136#issuecomment-272703023
# Change TimeZone TODO: TZ still is not set!
ARG TZ="Europe/Amsterdam"
RUN apk update \
	&& apk upgrade \
	&& apk add ca-certificates \
	&& update-ca-certificates \
	&& apk add --update openjdk8-jre tzdata curl unzip bash \
	&& apk add --no-cache nss \
	&& rm -rf /var/cache/apk/* \
	&& 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_BIN
# Entrypoint has same signature as "jmeter" command
COPY entrypoint.sh /
WORKDIR	${JMETER_HOME}
ENTRYPOINT ["/entrypoint.sh"]

简单分析下,基于alpine基础镜像,然后从jmeter的apache官网下载jmeter的压缩文件并解压,jmeter的路径为JMETER_HOME指定,即/opt/apache-jmeter-<版本号>,容器启动之后执行entrypoint.sh。

接着我们看下entrypoint.sh内容:

set -e
freeMem=`awk '/MemFree/ { print int($2/1024) }' /proc/meminfo`
s=$(($freeMem/10*8))
x=$(($freeMem/10*8))
n=$(($freeMem/10*2))
export JVM_ARGS="-Xmn${n}m -Xms${s}m -Xmx${x}m"
echo "START Running Jmeter on `date`"
echo "JVM_ARGS=${JVM_ARGS}"
echo "jmeter args=$@"
# Keep entrypoint simple: we must pass the standard JMeter arguments
jmeter $@
echo "END Running Jmeter on `date`"
# -n \
# -t "/tests/${TEST_DIR}/${TEST_PLAN}.jmx" \
# -l "/tests/${TEST_DIR}/${TEST_PLAN}.jtl"
# exec tail -f jmeter.log
# -D "java.rmi.server.hostname=${IP}" \
# -D "client.rmi.localport=${RMI_PORT}" \
# -R $REMOTE_HOSTS

东西也不复杂,直接使用jmeter这个命令行命令执行,参数为启动容器时传递的参数,换句话理解,就是执行jmeter -n -t -l **这些,只是传递的时候从docker命令传入

基于docker的压测

通过上面的分析,我们知道了justb4/jmeter的工作原理,在实际使用过程中,我们一般不会把jmeter的压测文件传递到镜像里,所以通过volume的方式挂载;同理,测试结果jtl我们也需要最终拷贝出来在其他机器进行绘图或者使用上文说的plugin插件从命令行绘图,所以也将jtl文件地址挂载到宿主机,于是,docker的命令就变为:

docker run -d -v /jmeter_svt:/jmeter_svt justb4/jmeter "-n -t /jmeter_svt/case/123.jmx -l /jmeter_svt/result/123.jtl"

这种格式,于是container启动并执行了压测

弹性加压

上面实现了基于docker的压测,如何实现动态加压?比如,当前100并发,如何到200,或者200太大,如何往下降?这就涉及到容器编排。现在编排方面k8s和docker swarm都可以去做,简单起见,我们直接可以docker swarm快速建立一个集群:

首先init集群:

docker swarm init --advertise-addr <MANAGER1-IP>

然后将计算几点加入到集群:

docker swarm join --token **

这个命令也是上面第一步返回的结果。如果忘记了,可以通过

docker swarm join-token worker

进行找回

然后可以用

docker node list

查看节点状态。

下面是关键,我们的压测,使用如下命令启动一个container:

docker service create --name jmeter_demo --mount type=bind,src=/testcase-svt,dst=/testcase-svt --replicas 1 justb4/jmeter "-n -t /testcase-svt/case/123.jmx -l /testcase-svt/result/123.jtl"

简单解释下下:--name指定我们的压测服务为jmeter_demo,--mount是我们需要把主机上的压测脚本和压测结果需要写到主机上,所以采用mount的bind类型进行主机和container的瓜姐;--relicas是指启动多少个容器,假设123.jmx里面指定并发100,则启动一个容器进行100并发压测;后面的就是上面讲的justb4/jmeter的工作原理了。

然后我们查看状态:

docker service ls

关键地方来了,我们感觉压力不够(此时的感觉,我们可以结合服务器监控或者在线压测结果进行判断,后续发文)需要加压,怎么办?

docker service scale j7lc87pd6y03=5

一键加压,有么有?我们启动5个容器,即相当于5倍初始压力。

我们docker service ls下:

当前就是5倍初始的压力了。

不好,太大了?怎么办?继续scale

很方便,有么有?

不用管怎么加,怎么减,只用敲命令,是不是很方便?

也许你要问,我不想每次成倍数加压,我想控制每次加压的并发数,怎么搞?大家可以自己想想,没想出来的,留言问我。

如果需要停止加压,直接删除压测服务即可:

docker service rm j7lc87pd6y03

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表