AWS EC2+Docker+JMeter构建分布式负载测试基础架构

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

AWS EC2+Docker+JMeter构建分布式负载测试基础架构

软测小生   2020-03-06 我要评论
[原文链接](https://medium.com/@DragosCampean/how-to-build-a-distributed-load-testing-infrastructure-with-aws-docker-and-jmeter-accf3c2aa3a3) @[Toc] ### 概述及范围 本文介绍有关如何使用AWS EC2+Docker+JMeter创建分布式负载测试基础架构。 完成所有步骤后,得到的基础结构如下: ![AWS EC2+Docker+JMeter基础架构](https://img-blog.csdnimg.cn/2020022917094142.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3piajE4MzE0NDY5Mzk1,size_1,color_FFFFFF,t_70) 在**Part 1**中,我们将按照所需的步骤进行操作,以创建适合你需求的自定义JMeter Dockerfiles和映像。 然后,在**Part 2**中,我们将在AWS EC2设置中使用这些元素。 接下来开始第一步: ### 前提条件 为了能够顺利的逐步进行配置和操作,你需要上述每个系统(EC2,Docker和JMeter)的一些基本知识。 此外,还需要一个活动的AWS账户才能执行所有步骤。 ### Part 1: Local setup—本地配置 #### Step 1: 从Dockerfile创建映像 [dockerfile](https://conetix.com.au/blog/what-is-a-dockerfile/)是开始使用docker所需的基本元素或“ cookbook”,因此我们将从此开始。 我们需要建立2层: 1、一是基础层,该层创建运行JMeter实例所需的基本设置; 2、二是逻辑层,它是一个JMeter实例,可以是主节点或从节点; JMeter base映像的Dockerfile和entrypoint.sh脚本如下所示: **Dockerfile:** ```bash # Use Java 11 JDK Oracle Linux FROM openjdk:11-jdk-oracle MAINTAINER Dragos # Set the JMeter version you want to use ARG JMETER_VERSION="5.1.1" # 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.orghttps://img.qb5200.com/download-x/dist/jmeter/binaries/apache-jmeter-${JMETER_VERSION}.tgz # Set default values for allocation of system resources (memory) which will be used by JMeter ENV Xms 256m ENV Xmx 512m ENV MaxMetaspaceSize 1024m # Change timezone to local time ENV TZ="Europe/Bucharest" RUN export TZ=$TZ # Install jmeter RUN yum -y install curl \ && mkdir -p /tmphttps://img.qb5200.com/download-x/dependencies \ && curl -L --silent ${JMETER_DOWNLOAD_URL} > /tmphttps://img.qb5200.com/download-x/dependencies/apache-jmeter-${JMETER_VERSION}.tgz \ && mkdir -p /opt \ && tar -xzf /tmphttps://img.qb5200.com/download-x/dependencies/apache-jmeter-${JMETER_VERSION}.tgz -C /opt \ && rm -rf /tmphttps://img.qb5200.com/download-x/dependencies # Set JMeter home ENV PATH $PATH:$JMETER_BIN # copy our entrypoint COPY entrypoint.sh / RUN chmod +x ./entrypoint.sh # Run command to allocate the default system resources to JMeter at 'docker run' ENTRYPOINT ["/entrypoint.sh" ``` **Entrypoint.sh:** ```bash #!/bin/bash # Run command to allocate the default or custom system resources (memory) to JMeter at 'docker run' sed -i 's/\("${HEAP:="\)\(.*\)\("}"\)/\1-Xms'${Xms}' -Xmx'${Xmx}' -XX:MaxMetaspaceSize='${MaxMetaspaceSize}'\3/' ${JMETER_BIN}/jmeter exec "$@" ``` 在基础层之上,可以创建一个Master层和一个Slave层。这些Dockerfile可以根据你的特定要求进行自定义。 现在让我们看一下我们的逻辑层: **Master层的Dockerfile:** ```bash # Use my custom base image defined above FROM dragoscampean/testrepo:jmetrubase MAINTAINER Dragos # Expose port for JMeter Master EXPOSE 60000 ``` **Slave层的Dockerfile:** ```bash # Use my custom base image defined above FROM dragoscampean/testrepo:jmetrubase MAINTAINER Dragos # Expose ports for JMeter Slave EXPOSE 1099 50000 COPY entrypoint.sh / RUN chmod +x ./entrypoint.sh # Run command to allocate the default system resources to JMeter at 'docker run' and start jmeter-server with all required parameters ENTRYPOINT ["/entrypoint.sh"] ``` **Slave层的Entrypoint.sh:** ```bash #!/bin/bash # Run command to allocate the default system resources to JMeter at 'docker run' sed -i 's/\("${HEAP:="\)\(.*\)\("}"\)/\1-Xms'${Xms}' -Xmx'${Xmx}' -XX:MaxMetaspaceSize='${MaxMetaspaceSize}'\3/' ${JMETER_BIN}/jmeter && $JMETER_HOME/bin/jmeter-server \ -Dserver.rmi.localport=50000 \ -Dserver_port=1099 \ -Dserver.rmi.ssl.disable=true \ -Djava.rmi.server.hostname=$HostIP exec "$@" ``` 我们不会详细讨论dockerfiles中的所有内容的含义,在网上有很多这样的文档。不过值得一提的是与Dockerfiles绑定在一起的**entrypoint shell**脚本。 docker entrypoints的作用是在运行时将数据初始化或者配置到容器中。在我们的例子中,我们需要它们来指定JMeter允许使用多少内存,并使用一些自定义配置来启动JMeter服务器,这些配置是基础设施工作所必需的。这将在“**Step 2**”部分中举例说明。 现在,让我们看一下创建Docker映像所需的命令。顺便说一下,Docker图像表示一组很好地集成在一起的层,是我们需要的环境的稳定快照。 从这样一个映像开始,我们可以生成N个容器,这正是我们在这个特定场景中所需要的,这取决于我们想要模拟的负载。 **创建一个简单的docker映像的命令:** `docker build /path/tohttps://img.qb5200.com/download-x/dockerfile` **为docker映像创建一个标签:** `docker tag imageId username/reponame:imageTag` **同时创建docker映像和标签:** `docker build -t username/reponame:imageTag /path/tohttps://img.qb5200.com/download-x/dockerfile ` #### Step 2: 从一个映像创建一个容器 现在我们已经准备好映像,可以开始从中创建容器,在其中可以实际运行性能测试脚本。 **创建一个新的容器:** `sudo docker run -dit --name containername repository:tag or imageId /bin/bash` **启动/停止容器:** `docker start containerId` `docker stop containerId` **访问正在运行的容器:** `docker exec -it containerId or containerName /bin/bash` 到目前为止,如果你一直使用类似于**Step 1**中提供的Dockerfile,那么您应该拥有一个完全可用的Java + JMeter容器。 你可以通过检查工具版本来测试它,看看是否有任何错误,甚至可以尝试运行你计划在AWS中扩展的脚本(所有这些都应该在运行的容器中完成): `Jmeter -v` `Java -version` `Jmeter -n -t -J numberOfThreads=1 /path/to/script.jmx -l /path/to/logfile.jtl` #### Step 3: 将映像Push/Pull到Dockerhub或任何私有的Docker仓库(docker登录CLI后) 测试创建的图像是否符合要求的标准(容器内的所有内容),通常,最好将此图像保存到存储库中。然后,你可以在后续随时从那里提取它,而不必每次都从Dockerfile构建它。 **`Push`映像到dockerhub:** `docker push username/reponame:imageTag` **从dockerhub中`Pull`已存在的映像(例如jdk映像):** `docker pull openjdk:version` 到此为止,这意味着您已经为cloud setup准备好了一组功能强大的JMeter从属映像和主映像。 ### Part 2: Cloud端基础架构——Infrastructure 可以使用[**EC2免费层**](https://aws.amazon.com/cn/ec2/)实例,最多750小时/月,持续1年,因此有很多时间进行试验。 **`注意:`**`对于下面提供的示例,我使用了`**`Ubuntu Server 18.04 LTS`**`实例,因此提供的命令可能无法在其他Linux发行版上使用。` #### Step 4: 创建安全组——Security Group 使容器内的JMeter实例(master实例或slave实例)能够通信,[**自定义安全组**](https:/https://img.qb5200.com/download-x/docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/ec2-security-groups.html)已定义并将其附加到每个主机: 入站规则(Inbound rules): ![Security group inbound rules](https://img-blog.csdnimg.cn/20200229180536299.png) 出站规则(Outbound rules): ![Security group outbound rules](https://img-blog.csdnimg.cn/20200229181109466.png) **注意**:确保将要成为负载测试基础结构部分的所有实例分配给此安全组,否则它们可能无法相互通信。 #### Step 5: 创建一个[IAM策略](https:/https://img.qb5200.com/download-x/docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/introduction.html)(可选) 假设您只需要一个由1个JMeter主节点和2个从节点组成的基础架构。在这种情况下,访问每个实例并对其进行配置(安装docker +启动容器)相对容易。 **`但是,如果需要处理的实例超过3个,会发生什么情况呢?`** 手动逐个配置变得极其乏味,手动并不是一个好主意。 这时,你将需要一个系统,能够管理你正在使用的大量容器。一些著名的工具,如谷歌的[**`Kubernetes`**](https://www.infoworld.com/article/3268073/what-is-kubernetes-your-next-application-platform.html),或者[**`Rancher`**](http://www.testautomationguru.com/jmeter-distributed-load-testing-using-docker-rancheros-in-cloud/)等工具。 由于当前使用的是AWS,因此这两种解决方案似乎过于庞大了,因为亚马逊针对这一点提供了一个开箱即用的解决方案: “[**`Run Command`**](https://aws.amazon.com/cn/blogs/aws/new-ec2-run-command-remote-instance-management-at-scale/)”功能使我们可以同时在多个EC2实例上执行Shell脚本。因此,我们不必访问每个实例,安装docker并一次一个实例地启动容器。 能够通过“**`Run Command`**”功能在EC2实例上执行命令的唯一要求是,适当的IAM角色已与该实例相关联。我将IAM策略命名为“ **EC2Command**”,并为每个新创建的实例选择了该策略(但是稍后可以通过“attach/replace role”功能将该角色分配给该实例): ![为现有实例设置IAM策略](https://img-blog.csdnimg.cn/20200229182906271.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3piajE4MzE0NDY5Mzk1,size_1,color_FFFFFF,t_70) ![在实例创建时关联IAM策略](https://img-blog.csdnimg.cn/2020022919090035.png) 当您创建角色时,请确保将“**AmazonEC2RoleforSSM**”策略附加到您的角色上,这样就可以了。 ![将权限关联到IAM角色](https://img-blog.csdnimg.cn/2020022919094119.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3piajE4MzE0NDY5Mzk1,size_1,color_FFFFFF,t_70) 现在您可以使用“Run command”功能对多个实例批量执行脚本。 这将我们带入流程的下一步。 #### Step 6: 在测试机器上安装Docker 现在,你需要在EC2主机上安装docker,以便可以启动容器并将它们连接在一起以进行分布式负载测试。 **直接使用命令(直接在Ubuntu上的实例终端中执行):** ```bash sudo apt-get install curl apt-transport-https ca-certificates software-properties-common \ && curl -fsSL https:/https://img.qb5200.com/download-x/download.docker.com/linux/ubuntu/gpg | sudo apt-key add \ && sudo add-apt-repository "deb [arch=amd64] https:/https://img.qb5200.com/download-x/download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \ && sudo apt-get update \ && sudo apt-get install -y docker-ce \ && sudo usermod -aG docker $USER \ && sudo curl -L "https://github.comhttps://img.qb5200.com/download-x/docker/compose/releaseshttps://img.qb5200.com/download-x/download/1.23.2https://img.qb5200.com/download-x/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/binhttps://img.qb5200.com/download-x/docker-compose \ && sudo chmod +x /usr/local/binhttps://img.qb5200.com/download-x/docker-compose \ && sudo ln -s /usr/local/binhttps://img.qb5200.com/download-x/docker-compose /usr/binhttps://img.qb5200.com/download-x/docker-compose ``` **通过“Run command”执行的Shell脚本:** ```bash #!/bin/bash sudo apt-get install curl apt-transport-https ca-certificates software-properties-common curl -fsSL https:/https://img.qb5200.com/download-x/download.docker.com/linux/ubuntu/gpg | sudo apt-key add sudo add-apt-repository "deb [arch=amd64] https:/https://img.qb5200.com/download-x/download.docker.com/linux/ubuntu $(lsb_release -cs) stable" sudo apt-get update sudo apt-get install -y docker-ce USER_DOCKER=$(getent passwd {1000..60000} | grep "/bin/bash" | awk -F: '{ print $1}') sudo usermod -aG docker $USER_DOCKER ``` 理想情况下,您将在多个EC2实例上运行第二个脚本,之后它们都将具有可用的Docker版本。 下一步是配置主节点和从属节点: #### Step 7: 配置主节点——Master Node 在某些情况下,你甚至不需要多个从属节点来分布式运行测试,比如,当你有一台功能强大的主机并且该计算机能够生成目标的负载量时,对于这种特定情况,不需要Step 8和Step 9。对于这种情况,你甚至不想使用容器并直接在主机上安装JMeter。 但是,假设你确实需要一个Master + Slaves系统,然后继续启动Master容器: **直接使用命令(直接在Ubuntu上的实例终端中执行):** ```bash HostIP=$(ip route show | awk 'https://img.qb5200.com/download-x/default/ {print $9}') \ && docker pull dragoscampean/testrepo:jmetrumaster \ && docker run -dit --name master --network host -e HostIP=$HostIP -e Xms=256m -e Xmx=512m -e MaxMetaspaceSize=512m -v /opt/Sharedvolume:/opt/Sharedvolume dragoscampean/testrepo:jmetrumaster /bin/bash ``` **通过“Run command”执行的Shell脚本:** ```bash #!/bin/bash HostIP=$(ip route show | awk 'https://img.qb5200.com/download-x/default/ {print $9}') docker pull dragoscampean/testrepo:jmetrumaster docker run -dit --name master --network host -e HostIP=$HostIP -e Xms=256m -e Xmx=512m -e MaxMetaspaceSize=512m -v /opt/Sharedvolume:/opt/Sharedvolume dragoscampean/testrepo:jmetrumaster /bin/bash ``` 脚本的第一行将机器的私有IP存储在变量“**HostIP**”中。主的HostIP不用于任何目的,仅使用从属节点的HostIP。我们将在Step 9看到具体要做什么。现在,请记住,你可以快速访问每个容器中主机的专用IP地址。 第二行很简单,只是从适当的仓库中获取图像。 最后一行创建我们将要使用的容器。此命令中有一些要点: 1、'**--network host** '命令启用主机连网,这意味着容器内的应用程序(JMeter),将在‘entrypoint.sh’脚本公开的端口上可用。如果没有它,我就无法进行设置。问题是,即使脚本是在从节点上执行的,由于错误(**java.rmi.ConnectException: Connection refused to host:masterPrivateIP**),主节点上也没有聚集任何结果。注意,我在较老版本的JMeter(如3.x.x)中没有遇到这个问题 2、**‘- e Xms=256m -e Xmx=512m -e MaxMetaspaceSize=512m’** 是Xms和Xmx的参数化,**MaxMetaspaceSize**决定了允许使用JMeter的内存量。这是通过首先在容器内设置一些环境变量来完成的。然后,在“ entrypoint.sh”脚本中运行命令,将更改JMeter的“ / bin”文件夹中的“JMeter”文件。如果未指定这些值,则使用默认值。 要进一步了解这些变量代表什么以及如何设置它们,请阅读以下内容: Xmx计算如下:**系统总内存-(OS使用的内存+ JVM使用的内存+在计算机上运行所需的任何其他脚本)** 如果您有一台专用的测试机器,为避免在测试运行时重新分配Xms,请从一开始就设置**Xms = Xmx**。 **MaxMetaspaceSize**跟踪所有加载的类元数据和静态内容(静态方法,原始变量和对象引用) 例如: 一台专用机器上64 GB RAM **Xmx** = 56G **Xms** = 56G **MaxMetaspaceSize** = 4096 MB 这为操作系统和其他进程留下了将近4GB的空间,这绰绰有余。 3、**-v /opt/Sharedvolume:/opt/Sharedvolume userName/repoName:imageTag** 该命令只是将主机上的文件夹映射到容器内的文件夹,你将在其中保存脚本文件和生成的日志。我们将不做进一步详细介绍,但是如果您想了解有关卷映射的更多信息,请参阅[本文和迷你教程](https://www.digitalocean.com/community/tutorials/how-to-share-data-between-the-docker-container-and-the-host)。 #### Step 8: 配置从节点——Slave Nodes “ **HostIP**”变量仅在“**entrypoint.sh**”脚本中用于此处,以启用从master服务器到slave服务器的远程访问(“**-Djava.rmi。server.hostname = $ HostIP**”)。 **直接使用命令(直接在Ubuntu上的实例终端中执行):** ```bash HostIP=$(ip route show | awk 'https://img.qb5200.com/download-x/default/ {print $9}') \ && docker pull dragoscampean/testrepo:jmetruslave \ && docker run -dit --name slave --network host -e HostIP=$HostIP -e HostIP=$HostIP -e Xms=256m -e Xmx=512m -e MaxMetaspaceSize=512m dragoscampean/testrepo:jmetruslave /bin/bash ``` **通过“Run command”执行的Shell脚本:** ```bash #!/bin/bash HostIP=$(ip route show | awk 'https://img.qb5200.com/download-x/default/ {print $9}') docker pull dragoscampean/testrepo:jmetruslave docker run -dit --name slave --network host -e HostIP=$HostIP -e Xms=256m -e Xmx=512m -e MaxMetaspaceSize=512m dragoscampean/testrepo:jmetruslave /bin/bash ``` #### Step 9: 分布式模式下运行脚本 到此,准备就绪,可以开始运行测试了。这是我们需要在master主节点上运行以开始运行分布式测试的命令: ```bash jmeter -n -t /path/to/scriptFile.jmx -Dserver.rmi.ssl.disable=true -R host1PrivateIP, host2PrivateIP,..., hostNPrivateIP -l /path/to/logfile.jtl ``` ### 总结: 按照上面的操作步骤,可以实现AWS EC2+Jmeter+Docker的分布式性能测试,可能会遇到一些问题,完全没问题那是不可能的。 比如: [该文](https:/https://img.qb5200.com/download-x/dzone.com/articles/stop-hoping-for-the-best-and-load-performing-tests)提到了一个EC2实例中有太多Websocket连接时可能遇到的问题。 另一个例子是我的一位同事在对Apa​​che服务器进行负载测试时遇到的情况,他会在JMeter中遇到各种连接错误,我们最初认为这是来自被测试的服务器。解决这个问题的方法来自[这篇简短的文章。](http://www.linuxbrigade.com/reduce-time_wait-socket-connections/) 我在一个项目中偶然发现的一个问题是,在尝试从一台计算机执行大约20000个线程时,进行了一些数据驱动的测试。如果在Linux / MacOS终端中键入“ **ulimit -a**”,则会看到名为“ open files”的行。问题在于该属性在测试计算机上设置为1024。使用JMeter运行数据驱动的测试时,此工具将为每个启动的线程打开.csv文件或描述符,一旦并行线程数超过1024,我将收到错误消息。 **解决方案:** 是从'**/etc/security/limits**'文件中编辑'**open files**'的最大值,并设置为'**unlimited**'。

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们