mirror of
https://github.com/Estom/notes.git
synced 2026-04-08 21:39:17 +08:00
JAVA
This commit is contained in:
@@ -17,6 +17,8 @@ OOM,全称“Out Of Memory”,翻译成中文就是“内存用完了”,
|
||||
|
||||
而在Java语言中,由于存在了垃圾自动回收机制,所以,我们一般不用去主动释放不用的对象所占的内存,也就是理论上来说,是不会存在“内存泄露”的。但是,如果编码不当,比如,将某个对象的引用放到了全局的Map中,虽然方法结束了,但是由于垃圾回收器会根据对象的引用情况来回收内存,导致该对象不能被及时的回收。如果该种情况出现次数多了,就会导致内存溢出,比如系统中经常使用的缓存机制。Java中的内存泄露,不同于C++中的忘了delete,往往是逻辑上的原因泄露。
|
||||
|
||||
|
||||
|
||||
# 3.OOM类型
|
||||
|
||||
JVM内存模型:
|
||||
@@ -61,4 +63,9 @@ dump堆内存信息后,需要对dump出的文件进行分析,从而找到OOM
|
||||
|
||||
涉及到的虚拟机的技术或者工具,往往需要考虑到虚拟机规范以及不同的虚拟机实现。尤其是针对虚拟机调优时,往往需要针对虚拟机在某些方面的实现策略来考虑,比如,不同的虚拟机的垃圾回收算法是不一样的,而这直接影响了虚拟机某些参数的设置,以达到虚拟机的最佳性能。
|
||||
|
||||
而针对JVM运行时的分析与诊断,则需要掌握分析基本方法,针对具体情况,运用虚拟机的原理,具体分析。一句话,水很深啊。
|
||||
而针对JVM运行时的分析与诊断,则需要掌握分析基本方法,针对具体情况,运用虚拟机的原理,具体分析。一句话,水很深啊。
|
||||
|
||||
|
||||
## 6. Mat使用简介
|
||||
|
||||
MAT,全称Memory Analysis Tools,是一款分析Java堆内存的工具,可以快速定位到堆内泄漏问题。该工具提供了两种使用方式,一种是插件版,可以安装到Eclipse使用,另一种是独立版,可以直接解压使用。
|
||||
503
Java/Java问题排查和性能优化/04 Jmeter压测工具.md
Normal file
503
Java/Java问题排查和性能优化/04 Jmeter压测工具.md
Normal file
@@ -0,0 +1,503 @@
|
||||
## 1 为什么性能测试
|
||||
|
||||
### 概述
|
||||
|
||||
软件性能测试是一种非功能性测试,其中应用程序的性能在预期或更高负载下进行评估。
|
||||
进行性能测试以测量系统的不同性能属性,如响应时间(速度),可靠性,资源使用,可扩展性,各种负载条件下的稳定性等。
|
||||
|
||||
### 基本功能
|
||||
|
||||
JMeter也称为“Apache JMeter”,它是一个开源的,100%基于Java的应用程序,带有图形界面。 它旨在分析和衡量Web应用程序和各种服务的性能和负载功能行为。
|
||||
|
||||
JMeter主要用于测试Web应用程序或FTP应用程序,但目前,它适用于功能测试,JDBC数据库连接,Web服务,通用TCP连接和OS本机进程。 您可以执行各种测试活动,如性能,负载,压力,回归和功能测试,以便针对您的Web服务器获得准确的性能指标。
|
||||
|
||||
* Web Services - SOAP / XML-RPC
|
||||
* Web - HTTP, HTTPS sites ‘web 1.0’ web 2.0 (ajax, flex 和 flex-ws-amf)
|
||||
* 通过JDBC驱动程序的数据库
|
||||
* 目录 - LDAP
|
||||
* 通过JMS面向消息传递的服务
|
||||
* 服务 - POP3, IMAP, SMTP
|
||||
|
||||
## 2 使用教程
|
||||
|
||||
### 基本界面
|
||||
|
||||

|
||||
|
||||
### 核心概念
|
||||
|
||||
> https://www.yiibai.com/jmeter/build-jmeter-test-plan.html
|
||||
|
||||
* 测试计划(TestPlans)
|
||||
|
||||
* 线程组(Thread Groups)
|
||||
|
||||
* 采样器(Samplers)
|
||||
* 监听器
|
||||
* 配置文件
|
||||
* 监听器
|
||||
* 配置文件
|
||||
* 监听器
|
||||
* 配置文件
|
||||
|
||||

|
||||
|
||||
测试计划:可以将测试计划可视化为用于运行测试的JMeter脚本。测试计划由测试元素组成,例如线程组,逻辑控制器,样本生成控制器,监听器,定时器,断言和配置元素。每个测试计划中至少应有一个线程组。 我们可以根据要求添加或删除元素。
|
||||
|
||||
* JMeter文件或测试计划以 `.JMX`扩展文件的形式保存。JMX是一种基于开放测试的格式,它使测试计划能够在文本编辑器中启动。
|
||||
* “测试计划(Test plan)”节点包含测试计划的名称和用户定义的变量。当您在测试计划的多个部分中有重复值时,可使用用户定义变量,它提供了灵活性。
|
||||
|
||||

|
||||
|
||||
线程组:线程组表示JMeter在测试期间将使用的线程组。 线程组元素是任何测试计划的起点。
|
||||
|
||||
* 设置线程数。
|
||||
* 设置加速期。
|
||||
* 设置执行测试的次数。
|
||||
|
||||

|
||||
|
||||
控制器—采样器:采样器是允许JMeter将特定类型的请求发送到服务器的组件。它模拟用户对目标服务器的页面的请求。
|
||||
|
||||
* 采样器是必须将组件添加到测试计划中的,因为它只能让JMeter知道需要将哪种类型的请求发送到服务器。 请求可以是HTTP,HTTP(s),FTP,TCP,SMTP,SOAP等。
|
||||
|
||||

|
||||
|
||||
控制器-逻辑控制器:逻辑控制器可帮助您控制线程中采样器处理顺序的流程。 它还可以更改来自其子元素的请求的顺序。
|
||||
|
||||
* 运行时控制器
|
||||
* IF控制器
|
||||
* 事务控制器
|
||||
* 录音控制器
|
||||
* 简单控制器
|
||||
* while控制器
|
||||
* Switch控制器
|
||||
* ForEach控制器
|
||||
* 模块控制器
|
||||
* 包括控制器
|
||||
* 循环控制器
|
||||
* 仅一次控制器
|
||||
* 交错控制器
|
||||
* 随机控制器
|
||||
* 随机顺序控制器
|
||||
* 吞吐量控制器
|
||||
|
||||

|
||||
|
||||
监听器:性能测试就是以各种形式分析服务器响应,然后将其呈现给客户端。当JMeter的采样器组件被执行时,监听器提供JMeter收集的关于那些测试用例的数据的图形表示。它便于用户在某些日志文件中以表格,图形,树或简单文本的形式查看采样器结果。监听器可以在测试的任何地方进行调整,直接包括在测试计划下。JMeter提供了大约15个监听器,但主要使用的是表,树和图形。
|
||||
|
||||
* 图表结果
|
||||
* 样条曲线可视化器
|
||||
* 断言结果
|
||||
* 简单的数据编写者
|
||||
* 监控结果
|
||||
* 分布图(alpha)
|
||||
* 聚合图
|
||||
* 梅勒展示台
|
||||
* BeanShell监听器
|
||||
* 总结报告
|
||||
* 示例结果保存配置
|
||||
* 图表完整结果
|
||||
* 查看结果树
|
||||
* 汇总报告
|
||||
* 查看表格中的结果
|
||||
|
||||

|
||||
|
||||
配置:配置元素的工作与采样器的工作类似。但是,它不发送请求,但它允许修改采样器发出的请求。这是一个简单的元素,您可以在其中收集所有采样器的关联配置值,如webserver的主机名或数据库URL等。配置元素只能从放置元素的分支内部访问。
|
||||
|
||||
* Java请求默认值
|
||||
* LDAP请求默认值
|
||||
* LDAP扩展请求默认值
|
||||
* 密钥库配置
|
||||
* JDBC连接配置
|
||||
* 登录配置元素
|
||||
* CSV数据集配置
|
||||
* FTP请求默认值
|
||||
* TCP采样器配置
|
||||
* 用户定义的变量
|
||||
* HTTP授权管理器
|
||||
* HTTP缓存管理器
|
||||
* HTTP Cookie管理器
|
||||
* HTTP代理服务器
|
||||
* HTTP请求默认值
|
||||
* HTTP标头管理器
|
||||
* 简单的配置元素
|
||||
* 随机变量
|
||||
|
||||

|
||||
|
||||
预处理器元素在采样器发出请求之前执行,如果预处理器附加到采样器元素,那么它将在该采样器元素运行之前执行。
|
||||
预处理器元素用于在运行之前修改样本请求的设置,或更新未从响应文本中提取的变量。
|
||||
以下是JMeter提供的所有预处理器元素的列表:
|
||||
|
||||
* JDBC预处理器
|
||||
* JSR223预处理器
|
||||
* RegEx用户参数
|
||||
* BeanShell预处理器
|
||||
* BSF预处理器
|
||||
* HTML链接解析器
|
||||
* HTTP URL重写修饰符
|
||||
* HTTP用户参数修饰符
|
||||
* 用户参数
|
||||
|
||||

|
||||
|
||||
在发出采样器请求之后执行后处理器元素。 如果后处理器连接到Sampler元素,那么它将在该sampler元素运行之后执行。
|
||||
|
||||
后处理器最常用于处理响应数据,例如,为了将来目的而提取特定值。
|
||||
|
||||
下面给出了JMeter提供的所有后处理器元素的列表:
|
||||
|
||||
* CSS/JQuery抽取器
|
||||
* BeanShell后处理器
|
||||
* JSR223后处理器
|
||||
* JDBC后处理器
|
||||
* 调试后处理器
|
||||
* 正则表达式提取器
|
||||
* XPath抽取器
|
||||
* 结果状态操作处理程序
|
||||
* BSF后处理器
|
||||
|
||||

|
||||
|
||||
### 启动命令
|
||||
|
||||
在服务器上一版使用命令行启动测试脚本。
|
||||
|
||||
使用命令行启动 JMeter 时,可以通过命令行参数来配置 JMeter 的运行方式,比如设置测试计划文件、日志文件、执行模式以及各种系统属性等。以下是一些常用的 JMeter 命令行启动参数:
|
||||
|
||||
* `-n`:指定 JMeter 以**非图形界面模式**运行,适用于批量运行或分布式测试。
|
||||
* `-t [测试计划.jmx]`:指定 JMeter 测试计划文件的路径。
|
||||
* `-l [结果文件.jtl]`:指定 JMeter 测试结果的输出文件路径。
|
||||
* `-j [日志文件.log]`:指定 JMeter 运行日志的输出文件路径。
|
||||
* `-r`:告诉 JMeter 的 Master 连接到定义在 `jmeter.properties` 文件中的远程 Slave 服务器。只有在 `-n` 也被指定时才能使用 `-r`。
|
||||
* `-R [逗号分隔的服务器列表]`:指定远程 Slave 服务器的列表,用于分布式测试。如 `-R 192.168.0.1,192.168.0.2`。
|
||||
* `-d [目录]`:指定 JMeter 的“起始目录”,即 JMeter 将在该目录下查找用户类路径和插件。
|
||||
* `-p [属性文件]`:指定 JMeter 属性文件的路径,通常是 `jmeter.properties` 文件。
|
||||
* `-q [额外属性文件]`:指定一个额外的 JMeter 属性文件,可以用于覆盖默认的属性设置。
|
||||
* `-J[属性名]=[值]`:直接在命令行中设置某个 JMeter 属性的值,如 `-JthreadNum=10` 设置属性 `threadNum` 的值为 10。
|
||||
* `-G[属性名]=[值]`:用于分布式测试,给远程的 Slave 服务器设置全局属性。
|
||||
* `-e`:在测试完成后以图形界面模式打开生成的报告分析数据。
|
||||
* `-o [输出目录]`:指定输出文件夹,用于存放使用 `-e` 参数生成的 HTML 报告。如果文件夹不存在,JMeter 将会创建它。
|
||||
* `-H [代理主机名]` 和 `-P [代理端口]`:配置 JMeter 使用代理服务器,如 `-H my.proxy.server -P 8000` 指定代理服务器。
|
||||
* `-u` 和 `-a`:指定订阅和发布的令牌(JMeter 5.0 引入)。
|
||||
|
||||
典型的启动命令如下
|
||||
|
||||
jmeter -n -t /path/to/your/testplan.jmx -l /path/to/resultsfile.jtl
|
||||
|
||||
## 3 使用实例
|
||||
|
||||
web的使用实例:
|
||||
|
||||
https://www.yiibai.com/jmeter/jmeter-web-test-plan.html
|
||||
|
||||
## 4 自定义Jmeter采样器
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>步骤</th>
|
||||
<th>动作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>创建一个Java类并继承<code>AbstractJavaSamplerClient</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>实现<code>setupTest</code>方法,用于初始化</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>实现<code>runTest</code>方法,用于执行具体的请求</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>4</td>
|
||||
<td>实现<code>teardownTest</code>方法,用于清理资源</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>5</td>
|
||||
<td>编译并将生成的jar文件放入JMeter的lib/ext目录下</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>6</td>
|
||||
<td>在JMeter中创建一个新的线程组</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>7</td>
|
||||
<td>添加一个<code>Java Request</code>到线程组中,并设置相应的参数</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>8</td>
|
||||
<td>运行测试,查看结果</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
#### 步骤 1: 创建一个Java类并继承 `AbstractJavaSamplerClient`
|
||||
|
||||
引入对应的依赖
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>org.apache.jmeter</groupId>
|
||||
<artifactId>ApacheJMeter_core</artifactId>
|
||||
<version>4.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.jmeter</groupId>
|
||||
<artifactId>ApacheJMeter_java</artifactId>
|
||||
<version>4.0</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
首先,我们需要创建一个Java类,并继承 `AbstractJavaSamplerClient`。这个类将成为我们自定义Sampler的入口点。
|
||||
|
||||
1、setupTest 用来做一些初始化的操作,每一线程只会调用该方法一次。
|
||||
|
||||
2、teardownTest 用来做一些清理的操作,每一线程只会调用该方法一次。
|
||||
|
||||
3、getDefaultParameters 设置sample的参数以及默认值,这个方法设置的参数会显示在Java request组件的界面上。
|
||||
|
||||
4、runTest 这个方法就是sample的核心方法,每次迭代都会调用,并且返回SampleResult对象。由于该方法是抽象方法,所以自定的sample一定要实现该方法,其他方法可根据情况选择是否重写。
|
||||
|
||||
```java
|
||||
package lym.iflytek.mt_scylla;
|
||||
|
||||
import org.apache.jmeter.config.Arguments;
|
||||
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
|
||||
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
|
||||
import org.apache.jmeter.samplers.SampleResult;
|
||||
|
||||
public class TestSample extends AbstractJavaSamplerClient {
|
||||
private IatDemo iat;#业务类,具体代码不再贴出来
|
||||
|
||||
public Arguments getDefaultParameters() {
|
||||
/*
|
||||
这个方法由JMeter调用,添加的Arguments参数会在界面上展示出来,可以设置默认值。
|
||||
* */
|
||||
Arguments arg = new Arguments();
|
||||
arg.addArgument("addr", "");
|
||||
arg.addArgument("appid", "");
|
||||
arg.addArgument("token", "");
|
||||
arg.addArgument("rate", "");
|
||||
arg.addArgument("filePath", "");
|
||||
arg.addArgument("printLog", "false");
|
||||
arg.addArgument("encoding", "utf-8");
|
||||
arg.addArgument("costTimeType", "3");
|
||||
return arg;
|
||||
}
|
||||
|
||||
|
||||
public void setupTest(JavaSamplerContext context) {
|
||||
/*进行初始化操作,每一个线程只执行一次*/
|
||||
String addr = context.getParameter("addr");
|
||||
String appid = context.getParameter("appid");
|
||||
String token = context.getParameter("token");
|
||||
String rate = context.getParameter("rate");
|
||||
String printLog = context.getParameter("printLog");
|
||||
String costTimeType = context.getParameter("costTimeType");
|
||||
iat = new IatDemo(addr, appid, token, rate, printLog, costTimeType);
|
||||
System.out.println(Thread.currentThread().getName()+":初始完成");
|
||||
|
||||
}
|
||||
|
||||
public void teardownTest(JavaSamplerContext context){
|
||||
/*做一些清理操作,每个线程只执行一次*/
|
||||
try {
|
||||
iat.UninitializeEx();
|
||||
System.out.println(Thread.currentThread().getName()+":逆初始化完成");
|
||||
} catch (IflytekException e) {
|
||||
getNewLogger().error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public SampleResult runTest(JavaSamplerContext javaSamplerContext) {
|
||||
/*每次迭代都会调用,并且返回SampleResult对象,该对象保存了每次运行的执行结果*/
|
||||
String filePath = javaSamplerContext.getParameter("filePath");
|
||||
String encoding = javaSamplerContext.getParameter("encoding");
|
||||
String costTimeType = javaSamplerContext.getParameter("costTimeType");
|
||||
#SampleResult ,用来保存每次运行的结果,以便JMeter进行数据统计。
|
||||
SampleResult sampleResult = new SampleResult();
|
||||
#通过参数控制运行时间的统计范围,如果你的业务没那么复杂,
|
||||
#完全可以在runTest开始时设置开始时间,方法结束时设置结束时间。
|
||||
if (costTimeType.equals("1")) {
|
||||
sampleResult.sampleStart();#设置运行的开始时间
|
||||
}
|
||||
try {
|
||||
String allresult = iat.start(filePath, sampleResult);
|
||||
|
||||
sampleResult.setSamplerData(filePath);#设置输入数据
|
||||
sampleResult.setDataType(SampleResult.TEXT);#设置数据类型
|
||||
sampleResult.setResponseData(allresult, encoding);#设置sample接收到的数据
|
||||
sampleResult.setSuccessful(true);#设置sample执行结果
|
||||
sampleResult.setResponseCodeOK();#设置sample执行状态码
|
||||
|
||||
} catch (Exception e) {
|
||||
sampleResult.setSuccessful(false);
|
||||
sampleResult.setResponseCode("500");
|
||||
sampleResult.setResponseMessage(e.getMessage());
|
||||
getNewLogger().error(e.getMessage(), e);
|
||||
}
|
||||
if (costTimeType.equals("1")) {
|
||||
#设置运行的结束时间,结束时间-开始时间,就是整个sample的运行时间
|
||||
#(JMeter就是用这个时间来计算平均响应时间的)。可以根据实际情况,设置在不同的位置。
|
||||
sampleResult.sampleEnd();
|
||||
}
|
||||
|
||||
if (sampleResult.getStartTime() == 0) {
|
||||
sampleResult.sampleStart();
|
||||
}
|
||||
|
||||
if (sampleResult.getEndTime() == 0) {
|
||||
sampleResult.sampleEnd();
|
||||
}
|
||||
return sampleResult;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
IflytekSample sample = new IflytekSample();
|
||||
Arguments arg = new Arguments();
|
||||
arg.addArgument("addr", "192.168.0.1:1234");
|
||||
arg.addArgument("appid", "00000000");
|
||||
arg.addArgument("token", "11111111");
|
||||
arg.addArgument("rate", "41000");
|
||||
arg.addArgument("filePath", "1.wav");
|
||||
arg.addArgument("printLog", "true");
|
||||
arg.addArgument("costTimeType", "2");
|
||||
|
||||
JavaSamplerContext javaSamplerContext = new JavaSamplerContext(arg);
|
||||
sample.setupTest(javaSamplerContext);
|
||||
SampleResult sampleResult = sample.runTest(javaSamplerContext);
|
||||
System.out.println(sampleResult.getResponseDataAsString());
|
||||
sample.teardownTest(javaSamplerContext);
|
||||
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
#### 步骤 2: 实现 `setupTest`方法
|
||||
|
||||
`setupTest`方法在每个线程开始之前执行,用于初始化一些资源或设置。在这个方法中,你可以进行一些预处理的操作。
|
||||
|
||||
```java
|
||||
@Override
|
||||
public void setupTest(JavaSamplerContext context) {
|
||||
// TODO: 初始化操作
|
||||
}
|
||||
1.2.3.4.
|
||||
```
|
||||
|
||||
#### 步骤 3: 实现 `runTest`方法
|
||||
|
||||
`runTest`方法是实际执行请求的地方。在这个方法中,你可以使用各种HTTP或其他类型的客户端库来发送请求,并处理响应。
|
||||
|
||||
```java
|
||||
@Override
|
||||
public SampleResult runTest(JavaSamplerContext context) {
|
||||
SampleResult result = new SampleResult();
|
||||
result.sampleStart(); // 标记请求的开始时间
|
||||
|
||||
// TODO: 执行实际的请求操作
|
||||
|
||||
result.sampleEnd(); // 标记请求的结束时间
|
||||
return result;
|
||||
}
|
||||
```
|
||||
|
||||
#### 步骤 4: 实现 `teardownTest`方法
|
||||
|
||||
`teardownTest`方法在每个线程结束之后执行,用于清理资源或做一些收尾的工作。
|
||||
|
||||
```java
|
||||
@Override
|
||||
public void teardownTest(JavaSamplerContext context) {
|
||||
// TODO: 清理操作
|
||||
}
|
||||
```
|
||||
|
||||
#### 步骤 5: 编译并将生成的jar文件放入JMeter的lib/ext目录下
|
||||
|
||||
完成以上步骤后,我们需要将代码编译成jar文件,并将该文件放入JMeter的lib/ext目录下。这样,JMeter就能够找到并加载我们自定义的Sampler。
|
||||
|
||||
#### 步骤 6: 在JMeter中创建一个新的线程组
|
||||
|
||||
在JMeter中,我们需要创建一个新的线程组来运行我们的测试。线程组表示一组并发的用户,可以设置线程数、循环次数等参数。
|
||||
|
||||
#### 步骤 7: 添加一个 `Java Request`到线程组中,并设置相应的参数
|
||||
|
||||
在线程组中,我们需要添加一个 `Java Request`。在该请求中,我们需要设置一些参数,例如类名、方法名等,以告诉JMeter我们要运行哪个自定义的Sampler。
|
||||
|
||||
#### 步骤 8: 运行测试,查看结果
|
||||
|
||||
最后,我们可以运行测试并查看结果。在结果树中,我们可以看到每个请求的响应时间、错误率等信息。
|
||||
|
||||
## 5 创建Jmeter集群
|
||||
|
||||
### 原理
|
||||
|
||||
1、Jmeter分布式测试时,选择其中一台作为控制机(Controller),其它机器做为代理机(Agent)。
|
||||
|
||||
2、执行时,Controller会把脚本发送到每台Agent上,Agent 拿到脚本后开始执行,Agent执行时不需要启动Jmeter,只需要把jmeter-server.bat文件打开,它应该是通 过命令行模式来执行的。
|
||||
|
||||
3、执行后,Agent会把结果回传给Controller,Controller会收集所有Agent的信息并汇总。
|
||||
|
||||
### Slave配置
|
||||
|
||||
配置Slave的地址名称。Jmeter/bin/jmeter.properties,找到”remote_hosts=127.0.0.1”,把这一行修改为”remote_hosts=192.168.8.149:1099
|
||||
|
||||
```properties
|
||||
# Remote Hosts - comma delimited
|
||||
remote_hosts=127.0.0.1:1099
|
||||
#remote_hosts=localhost:1099,localhost:2010
|
||||
|
||||
# RMI port to be used by the server (must start rmiregistry with same port)
|
||||
server_port=1099
|
||||
```
|
||||
|
||||
启动jmeter slave
|
||||
|
||||
```properties
|
||||
jmeter-server
|
||||
```
|
||||
|
||||
### Master配置
|
||||
|
||||
GUI方式:可以通过配置文件决定连接的remote。Jmeter/bin/jmeter.properties,找到”remote_hosts=127.0.0.1”,把这一行修改为”remote_hosts=192.168.8.149:1099,192.168.8.174:1099,1099是端口号,可以随意自定义。如果有多台代理机,这里需要把所有的代理机的IP地址和端口号都加入进来。
|
||||
|
||||
```properties
|
||||
remote_hosts=192.168.8.149:1099,192.168.8.174:1099
|
||||
```
|
||||
|
||||
命令行方式
|
||||
|
||||
```properties
|
||||
jmeter -n -t Test.jmx -l test_results.csv -JserverAddr=123 -R remote_host1,remote_host2
|
||||
```
|
||||
|
||||
### 其他问题
|
||||
|
||||
一个比较标准的参数解决方案如下:
|
||||
|
||||
```
|
||||
Jserver.rmi.ssl.disable=true -Jjava.net.preferIPv4Stack=true -Jjava.net.preferIPv6Addresses=false -Jsearch_paths=/home/admin/run
|
||||
```
|
||||
|
||||
配置user.properties关闭http用户校验
|
||||
|
||||
```properties
|
||||
server.rmi.ssl.disable=true
|
||||
```
|
||||
|
||||
配置system.properties中ipv4网络协议
|
||||
|
||||
```properties
|
||||
java.net.preferIPv4Stack=true
|
||||
java.net.preferIPv6Addresses=false
|
||||
```
|
||||
87
Java/Java问题排查和性能优化/06 JVM参数调优.md
Normal file
87
Java/Java问题排查和性能优化/06 JVM参数调优.md
Normal file
@@ -0,0 +1,87 @@
|
||||
|
||||
引言
|
||||
Jvm(Java虚拟机)是Java语言的基石,对于Java应用的性能至关重要。而Jvm启动参数的优化是提高Java应用性能的一个重要手段。本文将介绍Jvm启动参数的优化和一些示例,帮助开发者更好地理解和优化Jvm的启动参数。
|
||||
java启动参数共分为三类;
|
||||
其一是标准参数(-),所有的JVM实现都必须实现这些参数的功能,而且向后兼容;
|
||||
其二是非标准参数(-X),默认jvm实现这些参数的功能,但是并不保证所有jvm实现都满足,且不保证向后兼容;
|
||||
其三是非Stable参数(-XX),此类参数各个jvm实现会有所不同,将来可能会随时取消,需要慎重使用;
|
||||
|
||||
Jvm性能优化
|
||||
Jvm性能优化是应用开发过程中关注的一个重要方面。通过优化Jvm启动参数,可以显著提升Java应用的性能。以下是一些常见的Jvm性能优化参数:
|
||||
|
||||
-Xms: 指定Jvm的初始堆大小。
|
||||
-Xmx: 指定Jvm的最大堆大小。
|
||||
-Xmn: 指定Jvm的年轻代堆大小。
|
||||
-XX:MaxPermSize: 指定Jvm的永久代(或元空间)大小。
|
||||
-XX:SurvivorRatio: 指定Jvm的年轻代中Eden区和Survivor区的比例。
|
||||
-XX:+UseParallelGC: 使用并行垃圾回收器。
|
||||
-XX:+UseConcMarkSweepGC: 使用并发标记-清除垃圾回收器。
|
||||
内存管理
|
||||
Jvm的内存管理对于Java应用的性能有着重要的影响。通过合理地管理Jvm的内存,可以避免内存泄漏和过度的垃圾回收。以下是一些与Jvm内存管理相关的启动参数:
|
||||
|
||||
-XX:NewSize: 指定Jvm的年轻代的初始大小。
|
||||
-XX:MaxNewSize: 指定Jvm的年轻代的最大大小。
|
||||
-XX:NewRatio: 指定Jvm的年轻代和老年代的比例。
|
||||
-XX:SurvivorRatio: 指定Jvm的年轻代中Eden区和Survivor区的比例。
|
||||
-XX:MaxTenuringThreshold: 指定Jvm对象的年龄阈值。
|
||||
垃圾回收
|
||||
垃圾回收是Jvm中的重要子系统,对于Java应用的性能和稳定性至关重要。通过选择合适的垃圾回收器和调整相关参数,可以有效提升Jvm的垃圾回收性能。以下是一些与垃圾回收相关的启动参数:
|
||||
|
||||
-XX:+UseSerialGC: 使用串行垃圾回收器。
|
||||
-XX:+UseParallelGC: 使用并行垃圾回收器。
|
||||
-XX:+UseConcMarkSweepGC: 使用并发标记-清除垃圾回收器。
|
||||
-XX:+UseG1GC: 使用G1垃圾回收器。
|
||||
-XX:ParallelGCThreads: 指定并行垃圾回收器的线程数。
|
||||
-XX:ConcGCThreads: 指定并发垃圾回收器的线程数。
|
||||
并发
|
||||
并发是现代应用开发中普遍面临的挑战。Jvm提供了多种并发管理的选项,可以通过调整相关参数来优化并发性能。以下是一些与Jvm并发管理相关的启动参数:
|
||||
|
||||
-XX:ParallelGCThreads: 指定并行垃圾回收器的线程数。
|
||||
-XX:ConcGCThreads: 指定并发垃圾回收器的线程数。
|
||||
-XX:ThreadStackSize: 指定线程的堆栈大小。
|
||||
-XX:+UseThreadPriorities: 启用线程优先级。
|
||||
-XX:ThreadPriorityPolicy: 指定线程优先级策略。
|
||||
示例
|
||||
对于小型服务器配置(如2核心4GB内存)
|
||||
对于小型的服务器配置,如CPU为2核心,内存为4GB的服务器,JVM的配置可以考虑如下:
|
||||
|
||||
java -Xms1024m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=256m -jar app.jar
|
||||
1
|
||||
其中,参数 -Xms1024m 和 -Xmx1024m 分别表示JVM堆的最小值和最大值都为1024MB。一般情况下,为了避免JVM因为动态调整堆大小产生的性能开销,应该设置 -Xms 和 -Xmx 为相同值。
|
||||
|
||||
参数 -XX:PermSize=128m 和 -XX:MaxPermSize=256m 分别表示JVM永久代(PermGen)的初始大小为128MB,最大值为256MB。永久代用于存放JVM加载的类和方法等静态数据,如果服务器运行的Java应用需要加载大量的类,就需要增大永久代的大小。
|
||||
|
||||
对于大型服务器配置
|
||||
对于拥有更多CPU和内存的大型服务器,JVM的配置则需要考虑不同的策略。例如,对于一个拥有8核心,16GB内存的服务器,一个合理的JVM配置可能是:
|
||||
|
||||
java -Xms8192m -Xmx8192m -XX:PermSize=256m -XX:MaxPermSize=512m -XX:ParallelGCThreads=8 -XX:+UseConcMarkSweepGC -jar app.jar
|
||||
1
|
||||
在之前的基础上,我们增加了两个新的参数: -XX:ParallelGCThreads=8 和 -XX:+UseConcMarkSweepGC。
|
||||
|
||||
-XX:ParallelGCThreads=8 表示垃圾回收时的并行线程数为8。由于服务器有8个CPU核心,设置并行线程数为CPU核心数可充分利用CPU资源进行垃圾回收。
|
||||
|
||||
-XX:+UseConcMarkSweepGC 表示使用CMS(Concurrent Mark Sweep)垃圾收集器。CMS是一款以获取最短回收停顿时间为目标的收集器,适合对响应时间有高要求的服务器。大型服务器应用通常对性能要求较高,因此选择CMS进行垃圾回收是合适的。
|
||||
|
||||
JVM参数解析
|
||||
下面我们对前面提到的一些常用的JVM参数进行更详细的解析。
|
||||
|
||||
-Xmx 和 -Xms
|
||||
-Xmx 和 -Xms 分别用于设置JVM堆的最大值和最小值。JVM的堆内存是用于存放Java对象的地方,如果设置得太小,会导致频繁的垃圾回收,影响性能;如果设置得太大,有可能会导致长时间的GC停顿,也会影响性能。因此,需要根据服务的实际需求合理设置堆的大小。
|
||||
|
||||
-XX:PermSize 和 -XX:MaxPermSize
|
||||
-XX:PermSize 和 -XX:MaxPermSize 用于设置JVM的永久代大小。永久代用于存放静态文件,如Java类、方法等。如果服务器运行的应用需要加载大量的类,就需要增大这两个参数的值。
|
||||
|
||||
-XX:ParallelGCThreads
|
||||
-XX:ParallelGCThreads 用于设置并行垃圾回收器的线程数。这个参数的值一般设置为服务器CPU核心数,这样可以充分利用CPU资源进行垃圾回收。
|
||||
|
||||
-XX:+UseConcMarkSweepGC
|
||||
-XX:+UseConcMarkSweepGC 用于启用CMS垃圾回收器。CMS是一种以获取最短回收停顿时间为目标的收集器。大型服务器应用通常对性能要求较高,因此选择CMS进行垃圾回收是合适的。
|
||||
|
||||
以上就是对JVM启动参数的一些基本介绍和优化策略,希望能够对你有所帮助。记住,无论是什么样的优化策略,都需要通过实际的性能测试来进行验证和调整。
|
||||
|
||||
欢迎来访我的个人博客网站:http://refblogs.com/ 可以互换友链
|
||||
————————————————
|
||||
|
||||
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
|
||||
|
||||
原文链接:https://blog.csdn.net/qq_41389354/article/details/132044864
|
||||
BIN
Java/Java问题排查和性能优化/image/04Jmeter压测工具/1712477758187.png
Normal file
BIN
Java/Java问题排查和性能优化/image/04Jmeter压测工具/1712477758187.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 186 KiB |
Reference in New Issue
Block a user