1、JVM监控系统
JMH 测试报告
Benchmark注解:标识在某个具体方法上,表示这个方法将是一个被测试的最小方法,在JMH中成为一个OPS
BenmarkMode:测试类型,JMH提供了几种不同的Mode
Throughput:整体吞吐量
AverageTime:调用的平均时间,每次OPS执行的时间
SampleTime:取样,给出不同比例的ops时间,例如99%的ops时间,99.99%的ops时间
fork:fork的次数,如果设置为2,JMH会fork出两个进程来测试
Threads:很容易理解,这个参数表示这个方法同时被多少个线程执行
BenchMark介绍
BenchMark 又叫做基准测试,主要用来测试一些方法的性能,可以根据不同的参数以不同的单位进行计算(例如可以使用吞吐量为单位,也可以使用平均时间作为单位,在 BenchmarkMode 里面进行调整)。
开始前的步骤
项目使用的是 Maven,因此只要对 pom.xml 添加依赖即可。
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.19</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.19</version>
<scope>provided</scope>
</dependency>
代码
package com.psd.benchmark;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* Author: Shadowdsp
* Date: 18/07/22
*/
@BenchmarkMode(Mode.Throughput) // 吞吐量
@OutputTimeUnit(TimeUnit.MILLISECONDS) // 结果所使用的时间单位
@State(Scope.Thread) // 每个测试线程分配一个实例
@Fork(2) // Fork进行的数目
@Warmup(iterations = 4) // 先预热4轮
@Measurement(iterations = 10) // 进行10轮测试
public class BenchMark {
@Param({"10", "40", "70", "100"}) // 定义四个参数,之后会分别对这四个参数进行测试
private int n;
private List<Integer> array;
private List<Integer> list;
@Setup(Level.Trial) // 初始化方法,在全部Benchmark运行之前进行
public void init() {
array = new ArrayList<>(0);
list = new LinkedList<>();
for (int i = 0; i < n; i++) {
array.add(i);
list.add(i);
}
}
@Benchmark
public void arrayTraverse() {
for (int i = 0; i < n; i++) {
array.get(i);
}
}
@Benchmark
public void listTraverse() {
for (int i = 0; i < n; i++) {
list.get(i);
}
}
@TearDown(Level.Trial) // 结束方法,在全部Benchmark运行之后进行
public void arrayRemove() {
for (int i = 0; i < n; i++) {
array.remove(0);
list.remove(0);
}
}
public static void main(String[] args) throws RunnerException {
Options options = new OptionsBuilder().include(BenchMark.class.getSimpleName()).build();
new Runner(options).run();
}
}
报告
E:\Java\JDK8\bin\java "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin" -Dfile.encoding=UTF-8 -classpath E:\Java\JDK8\jre\lib\charsets.jar;E:\Java\JDK8\jre\lib\deploy.jar;E:\Java\JDK8\jre\lib\ext\access-bridge-64.jar;E:\Java\JDK8\jre\lib\ext\cldrdata.jar;E:\Java\JDK8\jre\lib\ext\dnsns.jar;E:\Java\JDK8\jre\lib\ext\jaccess.jar;E:\Java\JDK8\jre\lib\ext\jfxrt.jar;E:\Java\JDK8\jre\lib\ext\localedata.jar;E:\Java\JDK8\jre\lib\ext\nashorn.jar;E:\Java\JDK8\jre\lib\ext\sunec.jar;E:\Java\JDK8\jre\lib\ext\sunjce_provider.jar;E:\Java\JDK8\jre\lib\ext\sunmscapi.jar;E:\Java\JDK8\jre\lib\ext\sunpkcs11.jar;E:\Java\JDK8\jre\lib\ext\zipfs.jar;E:\Java\JDK8\jre\lib\javaws.jar;E:\Java\JDK8\jre\lib\jce.jar;E:\Java\JDK8\jre\lib\jfr.jar;E:\Java\JDK8\jre\lib\jfxswt.jar;E:\Java\JDK8\jre\lib\jsse.jar;E:\Java\JDK8\jre\lib\management-agent.jar;E:\Java\JDK8\jre\lib\plugin.jar;E:\Java\JDK8\jre\lib\resources.jar;E:\Java\JDK8\jre\lib\rt.jar;E:\Java\IdeaProjects\Warehouse\target\classes;E:\Java\maven\LocalWarehouse\junit\junit\4.11\junit-4.11.jar;E:\Java\maven\LocalWarehouse\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-core\4.0.2.RELEASE\spring-core-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\commons-logging\commons-logging\1.1.3\commons-logging-1.1.3.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-web\4.0.2.RELEASE\spring-web-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-beans\4.0.2.RELEASE\spring-beans-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-context\4.0.2.RELEASE\spring-context-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-oxm\4.0.2.RELEASE\spring-oxm-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-tx\4.0.2.RELEASE\spring-tx-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-jdbc\4.0.2.RELEASE\spring-jdbc-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-webmvc\4.0.2.RELEASE\spring-webmvc-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-expression\4.0.2.RELEASE\spring-expression-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-aop\4.0.2.RELEASE\spring-aop-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-context-support\4.0.2.RELEASE\spring-context-support-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\springframework\spring-test\4.0.2.RELEASE\spring-test-4.0.2.RELEASE.jar;E:\Java\maven\LocalWarehouse\org\mybatis\mybatis\3.2.6\mybatis-3.2.6.jar;E:\Java\maven\LocalWarehouse\org\mybatis\mybatis-spring\1.2.2\mybatis-spring-1.2.2.jar;E:\Java\maven\LocalWarehouse\javax\javaee-api\7.0\javaee-api-7.0.jar;E:\Java\maven\LocalWarehouse\com\sun\mail\javax.mail\1.5.0\javax.mail-1.5.0.jar;E:\Java\maven\LocalWarehouse\javax\activation\activation\1.1\activation-1.1.jar;E:\Java\maven\LocalWarehouse\mysql\mysql-connector-java\5.1.30\mysql-connector-java-5.1.30.jar;E:\Java\maven\LocalWarehouse\commons-dbcp\commons-dbcp\1.2.2\commons-dbcp-1.2.2.jar;E:\Java\maven\LocalWarehouse\commons-pool\commons-pool\1.3\commons-pool-1.3.jar;E:\Java\maven\LocalWarehouse\jstl\jstl\1.2\jstl-1.2.jar;E:\Java\maven\LocalWarehouse\log4j\log4j\1.2.17\log4j-1.2.17.jar;E:\Java\maven\LocalWarehouse\com\alibaba\fastjson\1.1.41\fastjson-1.1.41.jar;E:\Java\maven\LocalWarehouse\org\slf4j\slf4j-api\1.7.7\slf4j-api-1.7.7.jar;E:\Java\maven\LocalWarehouse\org\slf4j\slf4j-log4j12\1.7.7\slf4j-log4j12-1.7.7.jar;E:\Java\maven\LocalWarehouse\org\codehaus\jackson\jackson-mapper-asl\1.9.13\jackson-mapper-asl-1.9.13.jar;E:\Java\maven\LocalWarehouse\org\codehaus\jackson\jackson-core-asl\1.9.13\jackson-core-asl-1.9.13.jar;E:\Java\maven\LocalWarehouse\commons-fileupload\commons-fileupload\1.3.1\commons-fileupload-1.3.1.jar;E:\Java\maven\LocalWarehouse\commons-io\commons-io\2.4\commons-io-2.4.jar;E:\Java\maven\LocalWarehouse\commons-codec\commons-codec\1.9\commons-codec-1.9.jar;E:\Java\maven\LocalWarehouse\org\junit\jupiter\junit-jupiter-api\5.3.0-M1\junit-jupiter-api-5.3.0-M1.jar;E:\Java\maven\LocalWarehouse\org\apiguardian\apiguardian-api\1.0.0\apiguardian-api-1.0.0.jar;E:\Java\maven\LocalWarehouse\org\opentest4j\opentest4j\1.1.0\opentest4j-1.1.0.jar;E:\Java\maven\LocalWarehouse\org\junit\platform\junit-platform-commons\1.3.0-M1\junit-platform-commons-1.3.0-M1.jar;E:\Java\maven\LocalWarehouse\org\openjdk\jmh\jmh-core\1.19\jmh-core-1.19.jar;E:\Java\maven\LocalWarehouse\net\sf\jopt-simple\jopt-simple\4.6\jopt-simple-4.6.jar;E:\Java\maven\LocalWarehouse\org\apache\commons\commons-math3\3.2\commons-math3-3.2.jar com.psd.benchmark.BenchMark
# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.arrayTraverse
# Parameters: (n = 10)
# Run progress: 0.00% complete, ETA 00:03:44
# Fork: 1 of 2
# Warmup Iteration 1: 189538.902 ops/ms
# Warmup Iteration 2: 287165.702 ops/ms
# Warmup Iteration 3: 282388.510 ops/ms
# Warmup Iteration 4: 277296.753 ops/ms
Iteration 1: 288687.174 ops/ms
Iteration 2: 277046.541 ops/ms
Iteration 3: 288680.458 ops/ms
Iteration 4: 279775.705 ops/ms
Iteration 5: 289098.257 ops/ms
Iteration 6: 287462.515 ops/ms
Iteration 7: 255330.788 ops/ms
Iteration 8: 282631.894 ops/ms
Iteration 9: 277038.372 ops/ms
Iteration 10: 277690.784 ops/ms
# Run progress: 6.25% complete, ETA 00:03:42
# Fork: 2 of 2
# Warmup Iteration 1: 286568.900 ops/ms
# Warmup Iteration 2: 288014.591 ops/ms
# Warmup Iteration 3: 281790.934 ops/ms
# Warmup Iteration 4: 279647.288 ops/ms
Iteration 1: 280839.175 ops/ms
Iteration 2: 289208.462 ops/ms
Iteration 3: 282724.949 ops/ms
Iteration 4: 289762.265 ops/ms
Iteration 5: 284551.820 ops/ms
Iteration 6: 283700.745 ops/ms
Iteration 7: 261083.800 ops/ms
Iteration 8: 283651.988 ops/ms
Iteration 9: 284418.725 ops/ms
Iteration 10: 282418.733 ops/ms
Result "com.psd.benchmark.BenchMark.arrayTraverse":
281290.158 ±(99.9%) 7750.303 ops/ms [Average]
(min, avg, max) = (255330.788, 281290.158, 289762.265), stdev = 8925.261
CI (99.9%): [273539.854, 289040.461] (assumes normal distribution)
# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.arrayTraverse
# Parameters: (n = 40)
# Run progress: 12.50% complete, ETA 00:03:27
# Fork: 1 of 2
# Warmup Iteration 1: 277185.994 ops/ms
# Warmup Iteration 2: 277343.966 ops/ms
# Warmup Iteration 3: 289105.366 ops/ms
# Warmup Iteration 4: 281931.930 ops/ms
Iteration 1: 279532.380 ops/ms
Iteration 2: 278419.091 ops/ms
Iteration 3: 281165.591 ops/ms
Iteration 4: 288999.045 ops/ms
Iteration 5: 277378.462 ops/ms
Iteration 6: 275360.726 ops/ms
Iteration 7: 282858.013 ops/ms
Iteration 8: 283601.524 ops/ms
Iteration 9: 279043.295 ops/ms
Iteration 10: 279976.466 ops/ms
# Run progress: 18.75% complete, ETA 00:03:12
# Fork: 2 of 2
# Warmup Iteration 1: 284211.718 ops/ms
# Warmup Iteration 2: 287327.346 ops/ms
# Warmup Iteration 3: 268548.012 ops/ms
# Warmup Iteration 4: 289429.098 ops/ms
Iteration 1: 283348.446 ops/ms
Iteration 2: 262579.782 ops/ms
Iteration 3: 283534.897 ops/ms
Iteration 4: 266160.111 ops/ms
Iteration 5: 289614.776 ops/ms
Iteration 6: 274270.699 ops/ms
Iteration 7: 267829.186 ops/ms
Iteration 8: 279612.742 ops/ms
Iteration 9: 283569.117 ops/ms
Iteration 10: 288172.441 ops/ms
Result "com.psd.benchmark.BenchMark.arrayTraverse":
279251.339 ±(99.9%) 6287.385 ops/ms [Average]
(min, avg, max) = (262579.782, 279251.339, 289614.776), stdev = 7240.561
CI (99.9%): [272963.955, 285538.724] (assumes normal distribution)
# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.arrayTraverse
# Parameters: (n = 70)
# Run progress: 25.00% complete, ETA 00:02:57
# Fork: 1 of 2
# Warmup Iteration 1: 276172.253 ops/ms
# Warmup Iteration 2: 284624.007 ops/ms
# Warmup Iteration 3: 288356.101 ops/ms
# Warmup Iteration 4: 284278.064 ops/ms
Iteration 1: 287831.035 ops/ms
Iteration 2: 286518.388 ops/ms
Iteration 3: 287016.992 ops/ms
Iteration 4: 282654.336 ops/ms
Iteration 5: 287899.254 ops/ms
Iteration 6: 287299.594 ops/ms
Iteration 7: 284624.713 ops/ms
Iteration 8: 287280.777 ops/ms
Iteration 9: 268079.560 ops/ms
Iteration 10: 266327.469 ops/ms
# Run progress: 31.25% complete, ETA 00:02:42
# Fork: 2 of 2
# Warmup Iteration 1: 282831.765 ops/ms
# Warmup Iteration 2: 271396.073 ops/ms
# Warmup Iteration 3: 280114.449 ops/ms
# Warmup Iteration 4: 272365.705 ops/ms
Iteration 1: 287276.286 ops/ms
Iteration 2: 258473.510 ops/ms
Iteration 3: 287822.759 ops/ms
Iteration 4: 281849.137 ops/ms
Iteration 5: 281739.415 ops/ms
Iteration 6: 271390.808 ops/ms
Iteration 7: 279252.964 ops/ms
Iteration 8: 280445.016 ops/ms
Iteration 9: 287019.516 ops/ms
Iteration 10: 283679.804 ops/ms
Result "com.psd.benchmark.BenchMark.arrayTraverse":
281224.067 ±(99.9%) 7376.077 ops/ms [Average]
(min, avg, max) = (258473.510, 281224.067, 287899.254), stdev = 8494.301
CI (99.9%): [273847.990, 288600.143] (assumes normal distribution)
# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.arrayTraverse
# Parameters: (n = 100)
# Run progress: 37.50% complete, ETA 00:02:27
# Fork: 1 of 2
# Warmup Iteration 1: 277758.992 ops/ms
# Warmup Iteration 2: 283193.840 ops/ms
# Warmup Iteration 3: 280441.005 ops/ms
# Warmup Iteration 4: 284059.500 ops/ms
Iteration 1: 288156.207 ops/ms
Iteration 2: 277402.478 ops/ms
Iteration 3: 274760.100 ops/ms
Iteration 4: 280052.747 ops/ms
Iteration 5: 261148.816 ops/ms
Iteration 6: 281093.340 ops/ms
Iteration 7: 278472.671 ops/ms
Iteration 8: 257387.342 ops/ms
Iteration 9: 258938.869 ops/ms
Iteration 10: 281241.529 ops/ms
# Run progress: 43.75% complete, ETA 00:02:12
# Fork: 2 of 2
# Warmup Iteration 1: 261991.159 ops/ms
# Warmup Iteration 2: 272490.286 ops/ms
# Warmup Iteration 3: 283308.053 ops/ms
# Warmup Iteration 4: 262856.702 ops/ms
Iteration 1: 283588.427 ops/ms
Iteration 2: 289665.875 ops/ms
Iteration 3: 242227.467 ops/ms
Iteration 4: 235915.418 ops/ms
Iteration 5: 282235.546 ops/ms
Iteration 6: 262060.151 ops/ms
Iteration 7: 249476.606 ops/ms
Iteration 8: 289452.132 ops/ms
Iteration 9: 249939.347 ops/ms
Iteration 10: 268307.387 ops/ms
Result "com.psd.benchmark.BenchMark.arrayTraverse":
269576.123 ±(99.9%) 14237.446 ops/ms [Average]
(min, avg, max) = (235915.418, 269576.123, 289665.875), stdev = 16395.864
CI (99.9%): [255338.677, 283813.569] (assumes normal distribution)
# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.listTraverse
# Parameters: (n = 10)
# Run progress: 50.00% complete, ETA 00:01:58
# Fork: 1 of 2
# Warmup Iteration 1: 44140.774 ops/ms
# Warmup Iteration 2: 32207.674 ops/ms
# Warmup Iteration 3: 36260.862 ops/ms
# Warmup Iteration 4: 32678.534 ops/ms
Iteration 1: 35846.579 ops/ms
Iteration 2: 34837.967 ops/ms
Iteration 3: 36439.906 ops/ms
Iteration 4: 36522.320 ops/ms
Iteration 5: 35112.493 ops/ms
Iteration 6: 35687.937 ops/ms
Iteration 7: 35727.530 ops/ms
Iteration 8: 31676.889 ops/ms
Iteration 9: 36219.853 ops/ms
Iteration 10: 35857.764 ops/ms
# Run progress: 56.25% complete, ETA 00:01:43
# Fork: 2 of 2
# Warmup Iteration 1: 34479.354 ops/ms
# Warmup Iteration 2: 34805.614 ops/ms
# Warmup Iteration 3: 37839.045 ops/ms
# Warmup Iteration 4: 38778.482 ops/ms
Iteration 1: 37184.558 ops/ms
Iteration 2: 35340.593 ops/ms
Iteration 3: 37976.310 ops/ms
Iteration 4: 39359.895 ops/ms
Iteration 5: 37142.984 ops/ms
Iteration 6: 38973.376 ops/ms
Iteration 7: 38609.058 ops/ms
Iteration 8: 39516.419 ops/ms
Iteration 9: 33589.403 ops/ms
Iteration 10: 37153.584 ops/ms
Result "com.psd.benchmark.BenchMark.listTraverse":
36438.771 ±(99.9%) 1680.987 ops/ms [Average]
(min, avg, max) = (31676.889, 36438.771, 39516.419), stdev = 1935.828
CI (99.9%): [34757.784, 38119.758] (assumes normal distribution)
# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.listTraverse
# Parameters: (n = 40)
# Run progress: 62.50% complete, ETA 00:01:28
# Fork: 1 of 2
# Warmup Iteration 1: 6381.367 ops/ms
# Warmup Iteration 2: 6267.589 ops/ms
# Warmup Iteration 3: 6070.546 ops/ms
# Warmup Iteration 4: 6311.543 ops/ms
Iteration 1: 6294.215 ops/ms
Iteration 2: 6221.013 ops/ms
Iteration 3: 6196.371 ops/ms
Iteration 4: 5960.573 ops/ms
Iteration 5: 5748.201 ops/ms
Iteration 6: 5494.775 ops/ms
Iteration 7: 5594.778 ops/ms
Iteration 8: 6345.496 ops/ms
Iteration 9: 6141.148 ops/ms
Iteration 10: 6017.750 ops/ms
# Run progress: 68.75% complete, ETA 00:01:13
# Fork: 2 of 2
# Warmup Iteration 1: 6369.814 ops/ms
# Warmup Iteration 2: 6258.675 ops/ms
# Warmup Iteration 3: 5802.971 ops/ms
# Warmup Iteration 4: 6028.703 ops/ms
Iteration 1: 6192.258 ops/ms
Iteration 2: 5966.093 ops/ms
Iteration 3: 5958.597 ops/ms
Iteration 4: 6171.185 ops/ms
Iteration 5: 5617.002 ops/ms
Iteration 6: 5387.913 ops/ms
Iteration 7: 5299.407 ops/ms
Iteration 8: 5939.628 ops/ms
Iteration 9: 5640.087 ops/ms
Iteration 10: 6057.939 ops/ms
Result "com.psd.benchmark.BenchMark.listTraverse":
5912.221 ±(99.9%) 271.819 ops/ms [Average]
(min, avg, max) = (5299.407, 5912.221, 6345.496), stdev = 313.027
CI (99.9%): [5640.403, 6184.040] (assumes normal distribution)
# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.listTraverse
# Parameters: (n = 70)
# Run progress: 75.00% complete, ETA 00:00:59
# Fork: 1 of 2
# Warmup Iteration 1: 1904.675 ops/ms
# Warmup Iteration 2: 1829.190 ops/ms
# Warmup Iteration 3: 1799.166 ops/ms
# Warmup Iteration 4: 1823.508 ops/ms
Iteration 1: 1483.423 ops/ms
Iteration 2: 1733.061 ops/ms
Iteration 3: 1752.878 ops/ms
Iteration 4: 1877.448 ops/ms
Iteration 5: 1748.907 ops/ms
Iteration 6: 1836.011 ops/ms
Iteration 7: 1830.008 ops/ms
Iteration 8: 1733.991 ops/ms
Iteration 9: 1821.246 ops/ms
Iteration 10: 1827.086 ops/ms
# Run progress: 81.25% complete, ETA 00:00:44
# Fork: 2 of 2
# Warmup Iteration 1: 1858.409 ops/ms
# Warmup Iteration 2: 1816.699 ops/ms
# Warmup Iteration 3: 1810.298 ops/ms
# Warmup Iteration 4: 1704.668 ops/ms
Iteration 1: 1772.384 ops/ms
Iteration 2: 1619.981 ops/ms
Iteration 3: 1754.014 ops/ms
Iteration 4: 1767.706 ops/ms
Iteration 5: 1706.000 ops/ms
Iteration 6: 1646.038 ops/ms
Iteration 7: 1789.584 ops/ms
Iteration 8: 1746.964 ops/ms
Iteration 9: 1785.779 ops/ms
Iteration 10: 1813.610 ops/ms
Result "com.psd.benchmark.BenchMark.listTraverse":
1752.306 ±(99.9%) 77.143 ops/ms [Average]
(min, avg, max) = (1483.423, 1752.306, 1877.448), stdev = 88.838
CI (99.9%): [1675.163, 1829.449] (assumes normal distribution)
# JMH version: 1.19
# VM version: JDK 1.8.0_144, VM 25.144-b01
# VM invoker: E:\Java\JDK8\jre\bin\java.exe
# VM options: -javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\lib\idea_rt.jar=6182:C:\Program Files\JetBrains\IntelliJ IDEA 2017.3.1\bin -Dfile.encoding=UTF-8
# Warmup: 4 iterations, 1 s each
# Measurement: 10 iterations, 1 s each
# Timeout: 10 min per iteration
# Threads: 1 thread, will synchronize iterations
# Benchmark mode: Throughput, ops/time
# Benchmark: com.psd.benchmark.BenchMark.listTraverse
# Parameters: (n = 100)
# Run progress: 87.50% complete, ETA 00:00:29
# Fork: 1 of 2
# Warmup Iteration 1: 784.637 ops/ms
# Warmup Iteration 2: 803.586 ops/ms
# Warmup Iteration 3: 780.992 ops/ms
# Warmup Iteration 4: 812.284 ops/ms
Iteration 1: 771.280 ops/ms
Iteration 2: 725.038 ops/ms
Iteration 3: 781.465 ops/ms
Iteration 4: 753.939 ops/ms
Iteration 5: 753.920 ops/ms
Iteration 6: 813.238 ops/ms
Iteration 7: 778.423 ops/ms
Iteration 8: 809.902 ops/ms
Iteration 9: 769.837 ops/ms
Iteration 10: 767.709 ops/ms
# Run progress: 93.75% complete, ETA 00:00:14
# Fork: 2 of 2
# Warmup Iteration 1: 703.812 ops/ms
# Warmup Iteration 2: 752.538 ops/ms
# Warmup Iteration 3: 774.776 ops/ms
# Warmup Iteration 4: 813.269 ops/ms
Iteration 1: 796.985 ops/ms
Iteration 2: 687.697 ops/ms
Iteration 3: 808.395 ops/ms
Iteration 4: 736.341 ops/ms
Iteration 5: 761.328 ops/ms
Iteration 6: 746.422 ops/ms
Iteration 7: 767.855 ops/ms
Iteration 8: 814.670 ops/ms
Iteration 9: 772.441 ops/ms
Iteration 10: 731.986 ops/ms
Result "com.psd.benchmark.BenchMark.listTraverse":
767.444 ±(99.9%) 28.363 ops/ms [Average]
(min, avg, max) = (687.697, 767.444, 814.670), stdev = 32.662
CI (99.9%): [739.081, 795.806] (assumes normal distribution)
# Run complete. Total time: 00:03:56
(一般只需要关注这下面的东西)
Benchmark (n) Mode Cnt Score Error Units
BenchMark.arrayTraverse 10 thrpt 20 281290.158 ± 7750.303 ops/ms
BenchMark.arrayTraverse 40 thrpt 20 279251.339 ± 6287.385 ops/ms
BenchMark.arrayTraverse 70 thrpt 20 281224.067 ± 7376.077 ops/ms
BenchMark.arrayTraverse 100 thrpt 20 269576.123 ± 14237.446 ops/ms
BenchMark.listTraverse 10 thrpt 20 36438.771 ± 1680.987 ops/ms
BenchMark.listTraverse 40 thrpt 20 5912.221 ± 271.819 ops/ms
BenchMark.listTraverse 70 thrpt 20 1752.306 ± 77.143 ops/ms
BenchMark.listTraverse 100 thrpt 20 767.444 ± 28.363 ops/ms
Process finished with exit code 0
报告很长,因为这里的n有四种情况,然后有两个 @Benchmark 方法,因此会进行8次测试。
大多数情况只需要关注最下面的结果。
可以结合 Score 和 Unit 这两列,看到方法的效率。这里显然 arrayTraverse 的效率比 listTraverse 的高很多,因为 Unit 单位是 ops/ms,即单位时间内执行的操作数。所以显然在遍历的时候,ArrayList的效率是比LinkedList高的。
注解介绍
注解名 | 解释 |
@BenchmarkMode | Mode 表示 JMH 进行 Benchmark 时所使用的模式。通常是测量的维度不同,或是测量的方式不同。目前 JMH 共有四种模式:
|
@OutputTimeUnit | 输出的时间单位。 |
@Iteration | Iteration 是 JMH 进行测试的最小单位。在大部分模式下,一次 iteration 代表的是一秒,JMH 会在这一秒内不断调用需要 Benchmark 的方法,然后根据模式对其采样,计算吞吐量,计算平均执行时间等。 |
@WarmUp | Warmup 是指在实际进行 Benchmark 前先进行预热的行为。 为什么需要预热?因为 JVM 的 JIT 机制的存在,如果某个函数被调用多次之后,JVM 会尝试将其编译成为机器码从而提高执行速度。为了让 Benchmark 的结果更加接近真实情况就需要进行预热。 |
@State | 类注解,JMH测试类必须使用 @State 注解,它定义了一个类实例的生命周期,可以类比 Spring Bean 的 Scope。由于 JMH 允许多线程同时执行测试,不同的选项含义如下:
|
@Fork | 进行 fork 的次数。如果 fork 数是2的话,则 JMH 会 fork 出两个进程来进行测试。 |
@Meansurement | 提供真正的测试阶段参数。指定迭代的次数,每次迭代的运行时间和每次迭代测试调用的数量(通常使用 @BenchmarkMode(Mode.SingleShotTime) 测试一组操作的开销——而不使用循环) |
@Setup | 方法注解,会在执行 benchmark 之前被执行,正如其名,主要用于初始化。 |
@TearDown | 方法注解,与@Setup 相对的,会在所有 benchmark 执行结束以后执行,主要用于资源的回收等。 @Setup/@TearDown注解使用Level参数来指定何时调用fixture: | 名称 | 描述 | |
@Benchmark | 方法注解,表示该方法是需要进行 benchmark 的对象。 |
@Param | 成员注解,可以用来指定某项参数的多种情况。特别适合用来测试一个函数在不同的参数输入的情况下的性能。@Param 注解接收一个String数组,在 @Setup 方法执行前转化为为对应的数据类型。多个 @Param 注解的成员之间是乘积关系,譬如有两个用 @Param 注解的字段,第一个有5个值,第二个字段有2个值,那么每个测试方法会跑5*2=10次。 |
Arthas 性能监控
官网地址:Arthas
我们首先通过jps找到程序的进程号,然后直接通过arthas给到的as.sh对我们运行的程序进行字节码增强,然后启动arthas,命令如下
方法1:
curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar
快速入门——常用命令
1、dashboard
dashboard 展示当前进程信息
$ dashboard
ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTE DAEMON
-1 C2 CompilerThread0 - -1 - 1.55 0.077 0:8.684 false true
53 Timer-for-arthas-dashboard-07b system 5 RUNNABLE 0.08 0.004 0:0.004 false true
22 scheduling-1 main 5 TIMED_WAI 0.06 0.003 0:0.287 false false
-1 C1 CompilerThread0 - -1 - 0.06 0.003 0:2.171 false true
-1 VM Periodic Task Thread - -1 - 0.03 0.001 0:0.092 false true
49 arthas-NettyHttpTelnetBootstra system 5 RUNNABLE 0.02 0.001 0:0.156 false true
16 Catalina-utility-1 main 1 TIMED_WAI 0.0 0.000 0:0.029 false false
-1 G1 Young RemSet Sampling - -1 - 0.0 0.000 0:0.019 false true
17 Catalina-utility-2 main 1 WAITING 0.0 0.000 0:0.025 false false
34 http-nio-8080-ClientPoller main 5 RUNNABLE 0.0 0.000 0:0.016 false true
23 http-nio-8080-BlockPoller main 5 RUNNABLE 0.0 0.000 0:0.011 false true
-1 VM Thread - -1 - 0.0 0.000 0:0.032 false true
-1 Service Thread - -1 - 0.0 0.000 0:0.006 false true
-1 GC Thread#5 - -1 - 0.0 0.000 0:0.043 false true
Memory used total max usage GC
heap 36M 70M 4096M 0.90% gc.g1_young_generation.count 12
g1_eden_space 6M 18M -1 33.33% 86
g1_old_gen 30M 50M 4096M 0.74% gc.g1_old_generation.count 0
g1_survivor_space 491K 2048K -1 24.01% gc.g1_old_generation.time(ms) 0
nonheap 66M 69M -1 96.56%
codeheap_'non-nmethods' 1M 2M 5M 22.39%
metaspace 46M 47M -1 98.01%
Runtime
os.name Mac OS X
os.version 10.15.4
java.version 15
java.home /Library/Java/JavaVirtualMachines/jdk-15.jdk/Contents/Home
systemload.average 10.68
processors 8
uptime 272s
数据说明
- ID: Java 级别的线程 ID,注意这个 ID 不能跟 jstack 中的 nativeID 一一对应。
- NAME: 线程名
- GROUP: 线程组名
- PRIORITY: 线程优先级, 1~10 之间的数字,越大表示优先级越高
- STATE: 线程的状态
- CPU%: 线程的 cpu 使用率。比如采样间隔 1000ms,某个线程的增量 cpu 时间为 100ms,则 cpu 使用率=100/1000=10%
- DELTA_TIME: 上次采样之后线程运行增量 CPU 时间,数据格式为秒
- TIME: 线程运行总 CPU 时间,数据格式为分:秒
- INTERRUPTED: 线程当前的中断位状态
- DAEMON: 是否是 daemon 线程
JVM 内部线程
Java 8 之后支持获取 JVM 内部线程 CPU 时间,这些线程只有名称和 CPU 时间,没有 ID 及状态等信息(显示 ID 为-1)。 通过内部线程可以观测到 JVM 活动,如 GC、JIT 编译等占用 CPU 情况,方便了解 JVM 整体运行状况。
- 当 JVM 堆(heap)/元数据(metaspace)空间不足或 OOM 时,可以看到 GC 线程的 CPU 占用率明显高于其他的线程。
- 当执行trace/watch/tt/redefine等命令后,可以看到 JIT 线程活动变得更频繁。因为 JVM 热更新 class 字节码时清除了此 class 相关的 JIT 编译结果,需要重新编译。
JVM 内部线程包括下面几种:
- JIT 编译线程: 如 C1 CompilerThread0, C2 CompilerThread0
- GC 线程: 如GC Thread0, G1 Young RemSet Sampling
- 其它内部线程: 如VM Periodic Task Thread, VM Thread, Service Thread
截图展示
2、jad 来反编译 Main Class
通过 jad 来反编译 Main Class
ClassLoader:
+-sun.misc.Launcher$AppClassLoader@3d4eac69
+-sun.misc.Launcher$ExtClassLoader@66350f69
Location:
/tmp/math-game.jar
/*
* Decompiled with CFR 0_132.
*/
package demo;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;
public class MathGame {
private static Random random = new Random();
private int illegalArgumentCount = 0;
public static void main(String[] args) throws InterruptedException {
MathGame game = new MathGame();
do {
game.run();
TimeUnit.SECONDS.sleep(1L);
} while (true);
}
public void run() throws InterruptedException {
try {
int number = random.nextInt();
List<Integer> primeFactors = this.primeFactors(number);
MathGame.print(number, primeFactors);
}
catch (Exception e) {
System.out.println(String.format("illegalArgumentCount:%3d, ", this.illegalArgumentCount) + e.getMessage());
}
}
public static void print(int number, List<Integer> primeFactors) {
StringBuffer sb = new StringBuffer("" + number + "=");
Iterator<Integer> iterator = primeFactors.iterator();
while (iterator.hasNext()) {
int factor = iterator.next();
sb.append(factor).append('*');
}
if (sb.charAt(sb.length() - 1) == '*') {
sb.deleteCharAt(sb.length() - 1);
}
System.out.println(sb);
}
public List<Integer> primeFactors(int number) {
if (number < 2) {
++this.illegalArgumentCount;
throw new IllegalArgumentException("number is: " + number + ", need >= 2");
}
ArrayList<Integer> result = new ArrayList<Integer>();
int i = 2;
while (i <= number) {
if (number % i == 0) {
result.add(i);
number /= i;
i = 2;
continue;
}
++i;
}
return result;
}
}
Affect(row-cnt:1) cost in 970 ms.
3、watch命令来查看函数返回值
通过watch命令来查看demo.MathGame#primeFactors函数的返回值
让你能方便的观察到指定函数的调用情况。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看。
参数名称 | 参数说明 |
class-pattern | 类名表达式匹配 |
method-pattern | 函数名表达式匹配 |
express | 观察表达式,默认值:{params, target, returnObj} |
condition-express | 条件表达式 |
[b] | 在函数调用之前观察 |
[e] | 在函数异常之后观察 |
[s] | 在函数返回之后观察 |
[f] | 在函数结束之后(正常返回和异常返回)观察 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[x:] | 指定输出结果的属性遍历深度,默认为 1,最大值是 4 |
提示
观察表达式,默认值是{params, target, returnObj}
$ watch demo.MathGame primeFactors -x 2
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 32 ms, listenerId: 5
method=demo.MathGame.primeFactors location=AtExceptionExit
ts=2021-08-31 15:22:57; [cost=0.220625ms] result=@ArrayList[
@Object[][
@Integer[-179173],
],
@MathGame[
random=@Random[java.util.Random@31cefde0],
illegalArgumentCount=@Integer[44],
],
null,
]
method=demo.MathGame.primeFactors location=AtExit
ts=2021-08-31 15:22:58; [cost=1.020982ms] result=@ArrayList[
@Object[][
@Integer[1],
],
@MathGame[
random=@Random[java.util.Random@31cefde0],
illegalArgumentCount=@Integer[44],
],
@ArrayList[
@Integer[2],
@Integer[2],
@Integer[26947],
],
]
- 上面的结果里,说明函数被执行了两次,第一次结果是location=AtExceptionExit,说明函数抛出异常了,因此returnObj是 null
- 在第二次结果里是location=AtExit,说明函数正常返回,因此可以看到returnObj结果是一个 ArrayList
4、快速生成火焰图
#启动 profiler
$ profiler start
Started [cpu] profiling
提示
默认情况下,生成的是 cpu 的火焰图,即 event 为cpu。可以用--event参数来指定。
#获取已采集的 sample 的数量
$ profiler getSamples
23
#查看 profiler 状态
$ profiler status
[cpu] profiling is running for 4 seconds
可以查看当前 profiler 在采样哪种event和采样时间。
停止 profiler
生成 html 格式结果
默认情况下,结果文件是html格式,也可以用--format参数指定:
$ profiler stop --format html
profiler output file: /tmp/test/arthas-output/20211207-111550.html OK
或者在--file参数里用文件名指名格式。比如--file /tmp/result.html 。
通过浏览器查看 arthas-output 下面的 profiler 结果
默认情况下,arthas 使用 3658 端口,则可以打开: http://localhost:3658/arthas-output/在新窗口打开 查看到arthas-output目录下面的 profiler 结果:
点击可以查看具体的结果:
提示
如果是 chrome 浏览器,可能需要多次刷新。
命令手册大全
jvm 相关
- dashboard - 当前系统的实时数据面板
- getstatic - 查看类的静态属性
- heapdump - dump java heap, 类似 jmap 命令的 heap dump 功能
- jvm - 查看当前 JVM 的信息
- logger - 查看和修改 logger
- mbean - 查看 Mbean 的信息
- memory - 查看 JVM 的内存信息
- ognl - 执行 ognl 表达式
- perfcounter - 查看当前 JVM 的 Perf Counter 信息
- sysenv - 查看 JVM 的环境变量
- sysprop - 查看和修改 JVM 的系统属性
- thread - 查看当前 JVM 的线程堆栈信息
- vmoption - 查看和修改 JVM 里诊断相关的 option
- vmtool - 从 jvm 里查询对象,执行 forceGc
class/classloader 相关
- classloader - 查看 classloader 的继承树,urls,类加载信息,使用 classloader 去 getResource
- dump - dump 已加载类的 byte code 到特定目录
- jad - 反编译指定已加载类的源码
- mc - 内存编译器,内存编译.java文件为.class文件
- redefine - 加载外部的.class文件,redefine 到 JVM 里
- retransform - 加载外部的.class文件,retransform 到 JVM 里
- sc - 查看 JVM 已加载的类信息
- sm - 查看已加载类的方法信息
monitor/watch/trace 相关
注意
请注意,这些命令,都通过字节码增强技术来实现的,会在指定类的方法中插入一些切面来实现数据统计和观测,因此在线上、预发使用时,请尽量明确需要观测的类、方法以及条件,诊断结束要执行 stop 或将增强过的类执行 reset 命令。
- monitor - 方法执行监控
- stack - 输出当前方法被调用的调用路径
- trace - 方法内部调用路径,并输出方法路径上的每个节点上耗时
- tt - 方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测
- watch - 方法执行数据观测
profiler/火焰图
- profiler - 使用async-profiler在新窗口打开对应用采样,生成火焰图
- jfr - 动态开启关闭 JFR 记录
鉴权
- auth - 鉴权
options
- options - 查看或设置 Arthas 全局开关
管道
Arthas 支持使用管道对上述命令的结果进行进一步的处理,如sm java.lang.String * | grep 'index'
- grep - 搜索满足条件的结果
- plaintext - 将命令的结果去除 ANSI 颜色
- wc - 按行统计输出结果
后台异步任务
当线上出现偶发的问题,比如需要 watch 某个条件,而这个条件一天可能才会出现一次时,异步后台任务就派上用场了,详情请参考这里
- 使用 > 将结果重写向到日志文件,使用 & 指定命令是后台运行,session 断开不影响任务执行(生命周期默认为 1 天)
- jobs - 列出所有 job
- kill - 强制终止任务
- fg - 将暂停的任务拉到前台执行
- bg - 将暂停的任务放到后台执行
基础命令
- base64 - base64 编码转换,和 linux 里的 base64 命令类似
- cat - 打印文件内容,和 linux 里的 cat 命令类似
- cls - 清空当前屏幕区域
- echo - 打印参数,和 linux 里的 echo 命令类似
- grep - 匹配查找,和 linux 里的 grep 命令类似
- help - 查看命令帮助信息
- history - 打印命令历史
- keymap - Arthas 快捷键列表及自定义快捷键
- pwd - 返回当前的工作目录,和 linux 命令类似
- quit - 退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
- reset - 重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类
- session - 查看当前会话的信息
- stop - 关闭 Arthas 服务端,所有 Arthas 客户端全部退出
- tee - 复制标准输入到标准输出和指定的文件,和 linux 里的 tee 命令类似
- version - 输出当前目标 Java 进程所加载的 Arthas 版本号
2、性能优化
1、经典MVC模型优化
SpringBoot默认使用内嵌的tomcat作为Web容器,使用典型的MVC模式,最终访问到我们的数据
1.使用CDN加速文件获取
比较大的文件,尽量使用CDN(Content Delivery Network)分发。甚至是一些常用的前端脚本、样式、图片等,都可以放到CDN上。CDN通常能够加快这些文件的获取,网页加载也更加迅速。
2.合理设置Cache-Control值
浏览器会判断HTTP头Cache-Control的内容,用来决定是否使用浏览器缓存,这在管理一些静态文件的时候,非常有用。相同作用的头信息还有Expires。Cache-Control表示多久之后过期,Expires则表示什么时候过期。
这个参数可以在Nginx的配置文件中进行设置。
location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ {
# 缓存1年
add_header Cache-Control: no-cache, max-age=31536000;
}
3、开启gzip
开启gzip,可以先把内容压缩后,浏览器再进行解压。由于减少了传输的大小,会减少带宽的使用,提高传输效率。在nginx中可以很容易的开启。配置如下:
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_comp_level 6;
gzip_http_version 1.1;
gzip_types text/plain application/javascript text/css;
4.使用keepalive
由于连接的创建和关闭,都需要耗费资源。用户访问我们的服务后,后续也会有更多的互动,所以保持长连接可以显著减少网络交互,提高性能。
nginx默认开启了对客户端的keep avlide支持。你可以通过下面两个参数来调整它的行为。
http {
keepalive_timeout 120s 120s;
keepalive_requests 10000;
}
location ~ /{
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}