在之前的文章中,【JMeter:使用Docker进行分布式负载测试】已经介绍了如何使用docker创建多个运行jmeter-server的容器来进行分布式负载测试。但是我们在同一个主机上创建了所有的容器。即使我们不能使用单主机容器进行负载巨大的性能测试,在将与性能测试脚本相关的更改推送到AWS 或者其他任何云服务提供商之前,该设置将有助于你在本地测试脚本。
在本文中,将介绍如何在AWS中使用docker进行JMeter分布式负载测试。
创建AWS实例:
- AWS中创建 3个 t2-micro 实例
- Image Id: ami-d732f0b7
- 添加了一个security group(安全组)
- 安装最新版本的docker, 点击这里参考详细安装过程
创建docker-containers:
当我们的AWS实例启动并运行时,通过发出以下命令在每个主机上创建一个docker容器:
- JMeter-Master:在其中一个实例中,运行以下命令:
sudo docker run -dit --name master vinsdocker/jmmaster /bin/bash
- JMeter-Server/Slave:在其余实例中,我们将运行以下命令来创建jmeter-server容器:
sudo docker run -dit vinsdocker/jmserver /bin/bash
现在,已经为 jmeter-master
和 jmeter-server
准备好了docker容器,并且可以很好地运行所有依赖项。如果我们尝试查找这些容器的IP地址,它们的外观可能都相同–所有容器都为[172.17.0.1]。
因此,由于master无法识别网络中的slave,因此我们的jmeter测试在此设置中将不起作用。如果你还记得的话,我们将所有docker-container运行在同一主机上。当docker-engine在同一主机上为这些容器创建默认网络时,同一主机上的容器将能够使用容器的特定IP地址相互通信。
但是在此AWS中,设置如下图所示。
主机内部的master-containers(主容器)无法与其他主机上的slave-containers(从容器)进行对话——因为每个主机上的容器将位于各自独立的网络中,因此他们无法交流。
不同主机上的docker容器之间的通信将通过他们的Hosts进行路由。因此,可以通过使用端口映射和使用主机IP而不是容器来轻松修复它。
首先让我们运行下面的命令来停止和删除所有容器:
sudo docker stop $(sudo docker ps -a -q)
sudo docker rm $(sudo docker ps -a -q)
Port Mapping:(端口映射)
创建容器时,我们会将容器的公开端口映射到主机端口。因此,通过在映射端口上与主机对话,将与实际的容器通信。
java.rmi.server.hostname Property:
由于容器具有自己的IP地址,因此我们需要通过更新java.rmi.server.hostname使Jmeter通过主机ip进行通信。有关Java rmi属性的更多信息,请单击此处。
用于JMeter Client / Master的Dockerfile:
不需要任何更新。
用于JMeter Server/ Slave的Dockerfile:
它需要稍微修改一下,如下所示:
添加 -Djava.rmi.server.hostname=$LOCALIP while starting jmeter-server.sh.
,代码如下:
LOCALIP是一个变量,并且该值将在创建容器时在运行时传递。
# Use vinsdocker base image
# 使用vinsdocker基本映像
FROM vinsdocker/jmbase
MAINTAINER TestAutomationGuru
# Ports to be exposed from the container for JMeter Slaves/Server
# 从JMeter Slaves/Server的容器中要公开的端口
EXPOSE 1099 50000
# Application to run on starting the container
# 启动容器 运行应用程序
ENTRYPOINT $JMETER_HOME/bin/jmeter-server \
-Dserver.rmi.localport=50000 \
-Dserver_port=1099
-Djava.rmi.server.hostname=$LOCALIP while starting jmeter-server.sh.
使用以下命令,在每个主机上创建jmeter-server容器[master上除外]
[注意:我使用了不同的docker映像
-vinsdocker/jmawsserver
]
sudo docker run -dit -e LOCALIP='52.10.0.2' -p 1099:1099 -p 50000:50000 vinsdocker/jmawsserver /bin/bash
sudo docker run -dit -e LOCALIP='52.10.0.3' -p 1099:1099 -p 50000:50000 vinsdocker/jmawsserver /bin/bash
sudo docker run -dit -e LOCALIP='52.10.0.4' -p 1099:1099 -p 50000:50000 vinsdocker/jmawsserver /bin/bash
- LOCALIP——应该是主机的公共IP地址
- -p 1099:1099 ——用于将容器的1099端口与主机端口1099映射
- -p 50000:50000——用于将容器的1099端口与主机端口50000映射
在master主机上运行以下命令以创建jmeter master容器。
sudo docker run -dit --name master -p 60000:60000 vinsdocker/jmmaster /bin/bash
- 将容器端口60000映射到主机端口60000。
创建所有容器后,配置如下图所示:
现在,可以通过发出以下命令在主容器(master container)中运行测试:
./jmeter -n -t docker-test.jmx -Djava.rmi.server.hostname=52.10.0.1 -Dclient.rmi.localport=60000 -R52.10.0.2,52.10.0.3
- -Djava.rmi.server.hostname=52.10.0.1 -> 将jmeter-master IP公开给从属容器(slave containers)
- -Dclient.rmi.localport=60000 -> 主机的监听端口(listening port of host)
- -R52.10.0.2,52.10.0.3 -> 从属主机IP地址(Slaves host IP address)
总结
通过使用docker,我们无需担心是否在每个主机上都安装了相同版本的jmeter和java,docker将解决这一切。在单个主机上使用docker-container非常简单直接。
但是,当你在AWS中使用它时,为了使容器彼此通信,我们需要使用java.rmi.server.hostname属性和port mapping(端口映射)。只要做到这些,那么一切都会按预期进行。
在创建docker jmeter-server容器时,不使用LOCALIP变量,我们还可以使用下面的技术与从服务器通信:
- ssh [port fowarding technique(端口转发技术)]
- docker-multihost-network / docker swarm
我们将在下一篇文章中介绍如何使用上述技术。