JMeter接口压力测试

6,419 阅读14分钟

一、JMeter基础知识介绍和压测实操


1、JMeter基本介绍和使用场景

1)压测不同的协议和应用

  • Web - HTTP, HTTPS (Java, NodeJS, PHP, ASP.NET, …)
  • SOAP / REST Webservices
  • FTP
  • Database via JDBC
  • LDAP 轻量目录访问协议
  • Message-oriented middleware (MOM) via JMS
  • Mail - SMTP(S), POP3(S) and IMAP(S)
  • TCP等等

2)使用场景及优点

  • 功能测试
  • 压力测试
  • 分布式压力测试
  • 纯java开发
  • 上手容易,高性能
  • 提供测试数据分析
  • 各种报表数据图形展示

2、window环境快速安装JMeter5.x

强制依赖: JDK

官方下载地址: jmeter.apache.org/download_jm…

官方文档地址: jmeter.apache.org/usermanual/…

3、JMeter核心目录文件介绍

bin目录: 核心可执行文件以及核心配置文件

  • jmeter.bat: windows启动文件:
  • jmeter: mac或者linux启动文件:
  • jmeter-server.bat:window分布式压测使用的启动文件
  • jmeter.properties: 核心配置文件 extras目录: 插件拓展的包

lib目录: 核心的依赖包

  • ext核心包
  • junit单元测试包

4、JMeter中英文切换

方式一: 控制台修改(临时有效)

menu -> options -> choose language

方式二: 配置文件修改(永久有效)

JMeter bin目录 -> jmeter.properties

5、使用SpringBoot 2.0快速编写API测试接口

@RestController
@RequestMapping(value = "userController")
public class UserController {

    @GetMapping(value = "getUserList")
    public List<String> getUserList() {
        return Arrays.asList("tom","marry","jack");
    }

    @PostMapping(value = "login")
    public Map<String,Object> login(String name,String pwd){
        Map<String,Object> map = new HashMap<>();
        map.put("name",name);
        if ("123".equals(pwd)){
            map.put("status",0);
        }else{
            map.put("status",-1);
        }
        return map;
    }

}

6、创建Jmeter测试计划,快速压测接口

1)创建一个setup线程组

2)设置setup线程组的名称以及请求线程数、请求时间、请求循环次数

3)创建一个http请求

4)编写http请求的url

5)添加察看结果树

6)设置结果树名称并运行该线程组、查看结果树

二、Jmeter核心组件介绍和实操


1、JMeter基础功能组件介绍

1)线程组Thread Group(一个线程组里可以添加多个取样器)

  • Name:线程组名称
  • Comments:对线程组的描述
  • Number of Threads(users):虚拟用户数,一个虚拟用户占用一个进程或线程
  • Ramp-Up Period(in seconds):准备时长,全部线程启动的时长,比如100个线程,启动时长20s,则表示20秒内100个线程都要启动完成,每秒启动5个线程
  • Loop Count:循环次数,每个线程发送的次数,假如该值为5,100个线程,则会发送500次请求,可以勾选永远循环

2)取样器Sampler(以http请求为例)

  • Name:取样器名称
  • Comments:对取样器的描述
  • Protocol[http]:协议名称,默认是http协议
  • Server Name or IP:服务器名称或IP,请求的目标服务器名称或IP地址
  • Port Number:端口号,默认是80
  • Method:方法请求类型
  • Path:服务器请求url

3)监听器Listener(以察看结果树为例)

  • Name:结果树名称
  • Comments:对结果树的描述
  • Text:请求结果列表
  • Sampler result:取样器结果
  • Request:请求,包括请求头与请求体
  • Response data:响应数据,包括响应头与响应体

2、JMeter的断言基本使用

1)给http请求添加响应断言

  • Name:断言名称
  • Comments:对断言的描述
  • Apply to:应用范围,Main sample only表示仅对当前父取样器 进行断言,一般是一个请求,如果发一个请求会触发多个请求,则就勾选sub sample(比较少用)
  • Field to Test:要测试的响应字段,Text Response(响应文本),即响应的数据,比如json等文本,Response Code(响应代码),http的响应状态码,比如200,302,404等,Response Message(响应信息),http响应代码对应的响应信息,例如:OK, Found,Response Header(响应头),Http的响应头
  • Pattern Matching Rules:模式匹配规则,Contains(包括),包含在里面就成功,Matches(匹配),响应内容完全匹配,不区分大小写,equals,完全匹配,区分大小写

2)断言结果监听器

断言失败,查看结果树任务,结果颜色标红(通过结果树里面双击不通过的记录,可以看到错误信息)

3)每个sampler下面可以加单独的结果树,然后同时加多个断言,最外层可以加个结果树进行汇总

3、JMeter实战之压测结果聚合报告分析

新增聚合报告

  • Lable:sampler名称
  • #Samples:一共发出去多少个请求,例如10个用户,循环10次,则是100
  • Average:平均响应时间
  • Median:中位数,也就是50%用户的响应时间
  • 90% Line:90%用户的响应时间不会超过该时间
  • 95% Line:95%用户的响应时间不会超过该时间
  • 99% Line:99%用户的响应时间不会超过该时间
  • Min:最小响应时间
  • Maximum:最大响应时间
  • Error%:错误的请求的数量/请求的总数
  • Throughput:吞吐量,默认情况下表示每秒完成的请求数(Request per Second),可类比为qps
  • Received KB/sec:每秒接收数据量
  • Sent KB/Sec:每秒发送数据量

4、JMeter压测脚本JMX讲解

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.1.1 r1855137">
  <hashTree>
	
    <!-- 测试计划 -->
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="测试计划" enabled="true">
      <stringProp name="TestPlan.comments"></stringProp>
      <boolProp name="TestPlan.functional_mode">false</boolProp>
      <boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
      <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="用户定义的变量" enabled="true">
        <collectionProp name="Arguments.arguments"/>
      </elementProp>
      <stringProp name="TestPlan.user_define_classpath"></stringProp>
    </TestPlan>
	
    <hashTree>
	  
      <!-- 10人线程组 -->
      <SetupThreadGroup guiclass="SetupThreadGroupGui" testclass="SetupThreadGroup" testname="10人线程组" enabled="true">
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
          <boolProp name="LoopController.continue_forever">false</boolProp>
          <stringProp name="LoopController.loops">1</stringProp>
        </elementProp>
        <stringProp name="ThreadGroup.num_threads">10</stringProp>
        <stringProp name="ThreadGroup.ramp_time">10</stringProp>
        <boolProp name="ThreadGroup.scheduler">false</boolProp>
        <stringProp name="ThreadGroup.duration"></stringProp>
        <stringProp name="ThreadGroup.delay"></stringProp>
      </SetupThreadGroup>
	  
      <hashTree>
	  
        <!-- HTTP取样器 -->
        <HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="获取用户列表" enabled="true">
          <elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
            <collectionProp name="Arguments.arguments"/>
          </elementProp>
          <stringProp name="HTTPSampler.domain">127.0.0.1</stringProp>
          <stringProp name="HTTPSampler.port">8080</stringProp>
          <stringProp name="HTTPSampler.protocol"></stringProp>
          <stringProp name="HTTPSampler.contentEncoding"></stringProp>
          <stringProp name="HTTPSampler.path">/userController/getUserList</stringProp>
          <stringProp name="HTTPSampler.method">GET</stringProp>
          <boolProp name="HTTPSampler.follow_redirects">true</boolProp>
          <boolProp name="HTTPSampler.auto_redirects">false</boolProp>
          <boolProp name="HTTPSampler.use_keepalive">true</boolProp>
          <boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
          <stringProp name="HTTPSampler.embedded_url_re"></stringProp>
          <stringProp name="HTTPSampler.connect_timeout"></stringProp>
          <stringProp name="HTTPSampler.response_timeout"></stringProp>
        </HTTPSamplerProxy>
		
        <hashTree>
		
          <!-- 响应断言 -->
          <ResponseAssertion guiclass="AssertionGui" testclass="ResponseAssertion" testname="用户列表是否包含jack" enabled="true">
            <collectionProp name="Asserion.test_strings">
              <stringProp name="3254239">jack</stringProp>
            </collectionProp>
            <stringProp name="Assertion.custom_message">jack is null</stringProp>
            <stringProp name="Assertion.test_field">Assertion.response_data</stringProp>
            <boolProp name="Assertion.assume_success">false</boolProp>
            <intProp name="Assertion.test_type">2</intProp>
          </ResponseAssertion>
		  
          <hashTree/>
		  
          <!-- 结果树 -->
          <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="用户列表结果树" enabled="true">
            <boolProp name="ResultCollector.error_logging">false</boolProp>
            <objProp>
              <name>saveConfig</name>
              <value class="SampleSaveConfiguration">
                <time>true</time>
                <latency>true</latency>
                <timestamp>true</timestamp>
                <success>true</success>
                <label>true</label>
                <code>true</code>
                <message>true</message>
                <threadName>true</threadName>
                <dataType>true</dataType>
                <encoding>false</encoding>
                <assertions>true</assertions>
                <subresults>true</subresults>
                <responseData>false</responseData>
                <samplerData>false</samplerData>
                <xml>false</xml>
                <fieldNames>true</fieldNames>
                <responseHeaders>false</responseHeaders>
                <requestHeaders>false</requestHeaders>
                <responseDataOnError>false</responseDataOnError>
                <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
                <assertionsResultsToSave>0</assertionsResultsToSave>
                <bytes>true</bytes>
                <sentBytes>true</sentBytes>
                <url>true</url>
                <threadCounts>true</threadCounts>
                <idleTime>true</idleTime>
                <connectTime>true</connectTime>
              </value>
            </objProp>
            <stringProp name="filename"></stringProp>
          </ResultCollector>
		  
          <hashTree/>
		  
        <!-- 聚合报告 -->
          <ResultCollector guiclass="StatVisualizer" testclass="ResultCollector" testname="用户列表聚合报告" enabled="true">
            <boolProp name="ResultCollector.error_logging">false</boolProp>
            <objProp>
              <name>saveConfig</name>
              <value class="SampleSaveConfiguration">
                <time>true</time>
                <latency>true</latency>
                <timestamp>true</timestamp>
                <success>true</success>
                <label>true</label>
                <code>true</code>
                <message>true</message>
                <threadName>true</threadName>
                <dataType>true</dataType>
                <encoding>false</encoding>
                <assertions>true</assertions>
                <subresults>true</subresults>
                <responseData>false</responseData>
                <samplerData>false</samplerData>
                <xml>false</xml>
                <fieldNames>true</fieldNames>
                <responseHeaders>false</responseHeaders>
                <requestHeaders>false</requestHeaders>
                <responseDataOnError>false</responseDataOnError>
                <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
                <assertionsResultsToSave>0</assertionsResultsToSave>
                <bytes>true</bytes>
                <sentBytes>true</sentBytes>
                <url>true</url>
                <threadCounts>true</threadCounts>
                <idleTime>true</idleTime>
                <connectTime>true</connectTime>
              </value>
            </objProp>
            <stringProp name="filename"></stringProp>
          </ResultCollector>
		  
          <hashTree/>
        </hashTree>
		
        <!-- 全局结果树 -->
        <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="获取用户列表结果树" enabled="true">
          <boolProp name="ResultCollector.error_logging">false</boolProp>
          <objProp>
            <name>saveConfig</name>
            <value class="SampleSaveConfiguration">
              <time>true</time>
              <latency>true</latency>
              <timestamp>true</timestamp>
              <success>true</success>
              <label>true</label>
              <code>true</code>
              <message>true</message>
              <threadName>true</threadName>
              <dataType>true</dataType>
              <encoding>false</encoding>
              <assertions>true</assertions>
              <subresults>true</subresults>
              <responseData>false</responseData>
              <samplerData>false</samplerData>
              <xml>false</xml>
              <fieldNames>true</fieldNames>
              <responseHeaders>false</responseHeaders>
              <requestHeaders>false</requestHeaders>
              <responseDataOnError>false</responseDataOnError>
              <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
              <assertionsResultsToSave>0</assertionsResultsToSave>
              <bytes>true</bytes>
              <sentBytes>true</sentBytes>
              <url>true</url>
              <threadCounts>true</threadCounts>
              <idleTime>true</idleTime>
              <connectTime>true</connectTime>
            </value>
          </objProp>
          <stringProp name="filename"></stringProp>
        </ResultCollector>
		
        <hashTree/>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>

三、自定义变量和CSV可变参数实操


1、JMeter用户自定义变量实战

1)线程组 -> add -> Config Element(配置原件)-> User Definde Variable(用户定义的变量)

2)编写测试接口

@RequestMapping(value = "info")
public List<String> info(String name){
    List<String> userList = new ArrayList<>();
    userList.add(name);
    userList.add(String.valueOf(name.length()));
    return userList;
}

3)引用方式${XXX},在接口中变量中使用

4)原始查看结果树和非原生查看(基础按钮)

2、JMeter实战之CSV可变参数压测

1)线程组->add -> Config Element(配置原件)-> CSV data set config (CSV数据文件设置)

2)实战操作jmeter读取txt文本文件里面的参数进行压测

user1
user2
user3

3)实战操作jmeter读取csv文本文件里面的参数进行压测

user1
user2
user3

3、CSV文件多参数使用

1)修改接口

@RequestMapping(value = "info")
public List<String> info(String name,String pwd){
    List<String> userList = new ArrayList<>();
    userList.add(name);
    userList.add(pwd);
    return userList;
}

2)修改txt文件

user1|pwd1
user2|pwd2
user3|pwd3

3)修改cvs文件

user1	pwd1
user2	pwd2
user3	pwd3

四、MySQL数据库压测实操


1、JMeter压测实战之JDBC request压测MySQL

1)Thread Group -> add -> sampler -> jdbc request

2)jar包添加 mysql-connector-java-8.0.15.jar

3)JDBC request->add -> config element -> JDBC connection configuration

核心配置:

  • Max Number of Connections:最大连接数(20)
  • Max Wait(ms):最大等待时间(10000)
  • Auto Commit: 是否自动提交事务(True)
  • DataBase URL:数据库连接地址(jdbc:mysql://127.0.0.1:3306/jmeter_test?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true)
  • JDBC Driver class:数据库驱动(com.mysql.cj.jdbc.Driver)
  • Username:数据库用户名(root)
  • Password:数据库密码(root)

2、JMeter压测实战之JDBC request压测参数详解

1)预处理查询语句

2)预处理更新语句

3)Thread Group -> add -> sampler -> debug sampler

参数说明(sql语句结尾不要加分号):

  • Variable Name of Pool declared in JDBC Connection Configuration:指定JDBC连接配置的名称
  • Query Type:查询类型
  • Parameter values:参数值
  • Parameter types:参数类型
  • Variable names:sql执行结果变量名
  • Result variable names:所有结果当做一个对象存储
  • Query timeouts:查询超时时间
  • Handle results:处理结果集

五、高级篇之分布式压测基础知识


1、分布式压测介绍

  • 普通压测:单台机可以对目标机器产生的压力比较小,受限因素包括CPU,网络,IO等
  • 分布式压测:利用多台机器向目标机器产生压力,模拟几万用户并发访问

2、Jmeter分布式压测原理

Jmeter分布式压测原理:

  • 总控机器的节点叫master,其他产生压力的机器叫肉鸡
  • master会把压测脚本发送到肉鸡上面
  • 执行的时候,肉鸡上只需要把jmeter-server打开就可以了,不用启动jmeter
  • 结束后,肉鸡会把压测数据回传给master,然后master汇总输出报告
  • 配置详情

六、高级篇之阿里云Linux服务器压测接口实战


1、Spring Boot接口打包,并用jar包方式部署

命令行执行mvn打包命令:

mvn package

命令行执行jar包:

java -jar cyan-jmeter-0.0.1-SNAPSHOT.jar 

2、阿里云Linux服务器下安装启动JDK8并配置环境变量

官方下载地址: www.oracle.com/technetwork…

将下载好的文件上传至服务器,并执行解压命令:

$ tar -zxvf jdk-8u201-linux-x64.tar.gz -C /usr/local/
$ cd /usr/local/
$ ln -s jdk1.8.0_201/ jdk
$ cd jdk/
$ pwd
/usr/local/jdk

配置jdk环境变量:

$ vim /etc/profile

# 进入后在该文件末尾添加如下配置
JAVA_HOME=/usr/local/jdk
export JAVA_HOME
CLASSPATH=.:$JAVA_HOME/lib
export CLASSPATH
PATH=$PATH:$JAVA_HOME/bin:$CLASSPATH
export PATH

# :wq保存并退出后重启该配置文件
$ source /etc/profile

验证是否安装成功:

$ java
$ javac
$ java -version

3、部署java项目到云服务器(阿里云)和并守护进程启动

1)将打包好的jar上传至云服务器

注意点:

  • 关闭防火墙
  • 开放端口

** 2)linux上运行jar包**

java -jar cyan-jmeter-0.0.1-SNAPSHOT.jar

3)守护进程运行jar包

nohup java -jar cyan-jmeter-0.0.1-SNAPSHOT.jar &

4、阿里云Linux服务器安装Jmeter 4.0

官方下载地址: jmeter.apache.org/download_jm…

将下载好的文件上传至服务器,并执行解压命令:

$ tar -zxvf apache-jmeter-5.1.1.tgz -C /usr/local/
$ cd /usr/local/
$ ln -s apache-jmeter-5.1.1/ jmeter
$ cd jmeter/
$ pwd
/usr/local/jmeter

5、JMeter非GUI界面参数详解及压测实战

非GUI界面,压测参数讲解:

-h 帮助
-n 非GUI模式
-t 指定要运行的JMeter测试脚本文件
-l 记录结果的文件,每次运行之前要确保之前没有运行过,即xxx.jtl不存在,不然报错)
-r Jmter.properties文件remote_hosts属性指定的所有远程服务器中进行测试
-e 在脚本运行结束后生成html报告
-o 用于存放html报告的目录(目录要为空,不然报错)

官方配置参数详解地址: jmeter.apache.org/usermanual/…

测试准备: 将本地的测试计划(jmeterTest.jmx文件)上传至云服务器

官方推荐命令:

jmeter -n -t [jmx file] -l [results file] -e -o [Path to web report folder]

在云服务器上执行如下命令进行压测:

$ ./jmeter -n -t /usr/local/jmeter/bin/jmeterTest.jmx -l result.jtl -e -o /usr/local/jmeter/bin/temp
Creating summariser <summary>
Created the tree successfully using /usr/local/jmeter/bin/jmeterTest.jmx
Starting the test @ Wed Mar 04 13:01:17 CST 2020 (1583298077099)
Waiting for possible Shutdown/StopTestNow/HeapDump/ThreadDump message on port 4445
summary =     10 in 00:00:05 =    2.2/s Avg:    13 Min:     9 Max:    39 Err:     0 (0.00%)
Tidying up ...    @ Wed Mar 04 13:01:22 CST 2020 (1583298082100)
... end of run

七、高级篇之阿里云压测html可视化压测报告详解


1、Linux服务器JMeter压测实战之jtl文件查看

查看准备: 将压测生成的result.jtl文件下载到本地

可以通过打开jmeter,新建线程组->summary report->浏览文件进行查看:

2、JMeter压测接口的性能优化

JMeter压测减少资源使用的一些建议:

  • 使用非GUI模式:jmeter -n -t test.jmx -l result.jtl
  • 少使用Listener(监听器),如果使用-l参数,它们都可以被删除或禁用。
  • 在加载测试期间不要使用查看结果树或查看结果表监听器,只能在脚本阶段使用它们来调试脚本。
  • 只保存你需要的数据,尽可能少地使用断言
  • 如果测试需要大量数据,可以提前准备好测试数据放到数据文件中,以CSV Read方式读取。
  • 用内网压测,减少其他带宽影响压测结果
  • 如果压测大流量,尽量用多几个节点以非GUI模式向服务器施压

官方推荐: jmeter.apache.org/usermanual/…

3、项目实战之JMeter压测生成多维度图形化HTML测试报告

把Jmtere压测结果转换为Html:

$ ./jmeter -n -t /usr/local/jmeter/bin/jmeterTest.jmx -l result.jtl -e -o /usr/local/jmeter/bin/temp

转换后目录结构如下:

[root@cyan temp]# ll
total 24
drwxr-xr-x 5 root root 4096 Mar  4 13:01 content
-rw-r--r-- 1 root root 9463 Mar  4 13:01 index.html
drwxr-xr-x 5 root root 4096 Mar  4 13:01 sbadmin2-1.0.7
-rw-r--r-- 1 root root  874 Mar  4 13:01 statistics.json

下载到本机即可查看(index.html)

4、Jmeter图形化HTML压测报告dashboard详解

压测报告html里面Dashboard的核心指标说明:

1)Test and Report informations

  • Source file:jtl文件名
  • Start Time :压测开始时间
  • End Time :压测结束时间
  • Filter for display:过滤器

2)APDEX(Application performance Index)

  • apdex:应用程序性能指标,范围在0~1之间,1表示达到所有用户均满意
  • T(Toleration threshold):可接受阀值
  • F(Frustration threshold):不可接受阀值
  • Lable:sampler采样器名称

3)Requests Summary

  • OK:成功率
  • KO:失败率

4)Statistics 统计数据

  • Lable:sampler采样器名称
  • samples:请求总数,并发数*循环次数
  • KO:失败次数
  • Error%:失败率
  • Average:平均响应时间
  • Min:最小响应时间
  • Max:最大响应时间
  • 90th pct:90%的用户响应时间不会超过这个值(关注这个就可以了)
  • 95th pct:95%的用户响应时间不会超过这个值
  • 99th pct:99%的用户响应时间不会超过这个值 (存在极端值)
  • throughtput:Request per Second吞吐量 qps
  • received:每秒从服务器接收的数据量
  • send:每秒向服务器发送的数据量

5、JMeter图形化HTML压测报告Charts报表讲解

压测报告html里面Charts的核心指标说明:

1)Over Time(随时间变化)

  • Response Times Over Time:响应时间变化趋势
  • Response Time Percentiles Over Time (successful responses):最大,最小,平均,用户响应时间分布
  • Active Threads Over Time:并发用户数趋势
  • Bytes Throughput Over Time:每秒接收和请求字节数变化,蓝色表示发送,黄色表示接受
  • Latencies Over Time:平均响应延时趋势
  • Connect Time Over Time:连接耗时趋势

2)Throughput(吞吐量)

  • Hits Per Second (excluding embedded resources):每秒点击次数
  • Codes Per Second (excluding embedded resources):每秒状态码数量
  • Transactions Per Second:即TPS,每秒事务数
  • Total Transactions Per Second:每秒总事务数
  • Response Time Vs Request:响应时间和请求数对比
  • Latency Vs Request:延迟时间和请求数对比

3)Response Times(响应时间)

  • Response Time Percentiles:响应时间百分比
  • Response Time Overview:响应时间概述
  • Time Vs Threads:活跃线程数和响应时间
  • Response Time Distribution:响应时间分布图

八、高级篇之多节点JMeter分布式压测实战


1、JMeter5.1分布式压测准备工作

1)压测注意事项

  • the firewalls on the systems are turned off or correct ports are opened:系统上的防火墙被关闭或正确的端口被打开。
  • all the clients are on the same subnet:所有的客户端都在同一个子网上。
  • the server is in the same subnet, if 192.x.x.x or 10.x.x.x IP addresses are used. If the server doesn't use 192.xx or 10.xx IP address, there shouldn't be any problems:如果使用192.x.x.x或10.x.x.xIP地址,则服务器位于同一子网中。如果服务器不使用192.xx或10.xxIP地址,则不应该有任何问题。
  • Make sure JMeter can access the server:确保JMeter可以访问服务器。
  • Make sure you use the same version of JMeter and Java on all the systems. Mixing versions will not work correctly:确保在所有系统上使用相同版本的JMeter和Java。混合版本将无法正常工作。
  • You have setup SSL for RMI or disabled it:您已为RMI设置SSL或将其禁用。

官网地址 jmeter.apache.org/usermanual/…

压测注意事项: 一定要用内网IP,不用公网IP(有带宽限制),用ping去检查

2)专业名字

  • master:司令
  • slave:奴隶
  • target:目标

3)网络拓扑图:

4)远程拷贝(内网地址):

scp -r /usr/local/software/jdk-8u141-linux-x64.tar.gz root@172.18.230.233:/usr/local/software
scp -r /usr/local/software/jmeter/apache-jmeter-4.0.tgz root@172.18.230.233:/usr/local/software/jmeter

5)启动

./jmeter-server
nohup ./jmeter-server &

6)检查启动是否成功

ps -ef|grep jmeter-server
ps aux|grep jmeter-server

2、云服务器jmeter压测常见问题处理

1)内存不足

$ cd /usr/local/jmeter/
$ ./bin/jmeter
Java HotSpot(TM) 64-Bit Server VM warning: INFO: os::commit_memory(0x00000000c0000000, 1073741824, 0) failed; error='Cannot allocate memory' (errno=12)
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 1073741824 bytes for committing reserved memory.
# An error report file with more information is saved as:
# /usr/local/jmeter/apache-jmeter-4.0/bin/hs_err_pid5855.log

解决方案:编辑jmeter文件,修改启动堆内存和最大堆内存

$ vim bin/jmeter

# 修改如下启动堆内存和最大堆内存
: "${HEAP:="-Xms1g -Xmx1g -XX:MaxMetaspaceSize=256m"}"

2)拥有rmi over ssl的有效秘钥库,或者禁用了ssl

$ ./bin/jmeter-server 
Server failed to start: java.rmi.server.ExportException: Listen failed on port: 0; nested exception is: 
        java.io.FileNotFoundException: rmi_keystore.jks (No such file or directory)
An error occurred: Listen failed on port: 0; nested exception is: 
        java.io.FileNotFoundException: rmi_keystore.jks (No such file or directory)

解决方案:禁用SSL

$ vim bin/jmeter.properties 

# 禁用SSL
server.rmi.ssl.disable=true

再次启动jmeter:

$ ./bin/jmeter-server 
Created remote object: UnicastServerRef2 [liveRef: [endpoint:[172.17.156.214:41187](local),objID:[3ff15d6a:170a80f2a47:-7fff, 3197885818151024044]]]

3、Jmeter5.1分布式压测实战

1)压测修改master节点信息

$ vim bin/jmeter.properties 

# remote_hosts值是slave机器的ip+端口号,如果有多个,用逗号分隔
# remote_hosts=127.0.0.1
remote_hosts=192.168.1.25:8899,192.168.1.26:8899
server.rmi.ssl.disable=true
# server_port=1099

2)压测修改slave节点信息

server_port=8899
server.rmi.ssl.disable=true

3)启动slave机器,注意要同个网段,ip地址用内网ip

$ ./bin/jmeter-server 

4)压测

5)本地非GUI分布式压测(-r)

$ ./jmeter -n -t /usr/local/jmeter/bin/jmeterTest.jmx -r -l result.jtl -e -o /usr/local/jmeter/bin/temp
Creating summariser <summary>
Created the tree successfully using /Users/jack/Desktop/remote.jmx
Configuring remote engine: 172.20.10.3:8899
Using local port: 8899
Configuring remote engine: 172.20.10.11:8899
Starting remote engines
Starting the test @ Thu Mar 29 23:21:13 CST 2018 (1522336873931)
Remote engines have been started
Waiting for possible Shutdown/StopTestNow/Heapdump message on port 4445
summary =      4 in 00:00:22 =    0.2/s Avg:  5582 Min:    94 Max: 21006 Err:     1 (25.00%)
Tidying up remote @ Thu Mar 29 23:21:36 CST 2018 (1522336896842)
... end of run
```
**学习资料一:**
https://www.cnblogs.com/Fine-Chan/p/6233823.html

**学习资料二:**
https://blog.csdn.net/liujingqiu/article/details/52635289

**学习资料三:**
https://www.cnblogs.com/puresoul/p/4844539.html