本文目录导读:

在Java中实现压力测试,通常有几种成熟的方法:使用专业工具(如JMeter、Gatling)、使用Java原生并发工具(如ExecutorService、CountDownLatch)、或是结合HTTP客户端(如OkHttp、Apache HttpClient)进行自定义测试。
下面我会提供最常用、最典型的几种实现案例,涵盖Web接口压测和方法级压测。
使用 Java 原生并发工具(模拟高并发)
这是最基础、最灵活的方式,适合测试某个具体方法或系统接口的瓶颈。
案例:使用 CountDownLatch + ExecutorService 模拟高并发请求
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class SimpleStressTest {
// 模拟要压测的服务
static class MyService {
public String process(String request) {
try {
// 模拟业务处理耗时 (50ms)
Thread.sleep(50);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "processed: " + request;
}
}
public static void main(String[] args) throws InterruptedException {
final int concurrency = 100; // 并发线程数
final int totalRequests = 1000; // 总请求数
MyService service = new MyService();
ExecutorService executor = Executors.newFixedThreadPool(concurrency);
// 计数器:所有线程都准备好后同时发起请求
CountDownLatch readyLatch = new CountDownLatch(concurrency);
// 计数器:所有请求执行完后主线程继续
CountDownLatch endLatch = new CountDownLatch(totalRequests);
AtomicInteger successCount = new AtomicInteger(0);
long startTime = System.currentTimeMillis();
for (int i = 0; i < totalRequests; i++) {
final int requestId = i;
executor.submit(() -> {
try {
readyLatch.countDown(); // 报告准备就绪
readyLatch.await(); // 等待所有线程准备就绪(实现“齐射”效果)
// 执行请求
service.process("req-" + requestId);
successCount.incrementAndGet();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
endLatch.countDown();
}
});
}
// 等待所有请求完成
endLatch.await();
long endTime = System.currentTimeMillis();
executor.shutdown();
// 输出结果
long totalTime = endTime - startTime;
double tps = (double) totalRequests / (totalTime / 1000.0);
System.out.println("总耗时: " + totalTime + " ms");
System.out.println("成功请求数: " + successCount.get());
System.out.println("QPS (TPS): " + String.format("%.2f", tps));
}
}
运行效果:
并发 100 个线程,共 1000 次调用,输出如:
总耗时: 5523 ms
QPS (TPS): 181.05
压测 REST API(使用 HttpClient)
如果你的目标是压测一个真正的 HTTP 接口,Spring Boot 应用,可以用以下案例。
依赖(Maven)
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3.1</version>
</dependency>
代码实现:并发调用远程 HTTP 接口
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class HttpStressTest {
public static void main(String[] args) throws InterruptedException {
String url = "http://localhost:8080/api/test"; // 替换为你的接口
int concurrency = 50;
int totalRequests = 500;
ExecutorService executor = Executors.newFixedThreadPool(concurrency);
CountDownLatch startLatch = new CountDownLatch(1); // 统一开始
CountDownLatch endLatch = new CountDownLatch(totalRequests);
AtomicInteger success = new AtomicInteger(0);
AtomicInteger failure = new AtomicInteger(0);
for (int i = 0; i < totalRequests; i++) {
executor.submit(() -> {
try {
startLatch.await(); // 等待主线程发令
try (CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(new HttpGet(url))) {
if (response.getCode() == 200) {
success.incrementAndGet();
} else {
failure.incrementAndGet();
}
} catch (Exception e) {
failure.incrementAndGet();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
endLatch.countDown();
}
});
}
long startTime = System.currentTimeMillis();
startLatch.countDown(); // 发令:所有线程同时开始
endLatch.await(); // 等待所有请求完成
long endTime = System.currentTimeMillis();
executor.shutdown();
System.out.println("总耗时: " + (endTime - startTime) + " ms");
System.out.println("成功: " + success.get() + ", 失败: " + failure.get());
System.out.println("QPS: " + String.format("%.2f", totalRequests / ((endTime - startTime) / 1000.0)));
}
}
使用专业工具(推荐)
虽然上面都是纯 Java 实现,但在生产环境或正式压测中,强烈建议使用专门的压力测试工具,它们提供更丰富的报告、更强大的并发控制。
| 工具 | 特点 | 适用场景 |
|---|---|---|
| JMeter | 图形化界面,支持多种协议,插件丰富 | 一般压测需求 |
| Gatling | Scala 编写,高性能,生成 HTML 报告美观 | 持续集成、DevOps 场景 |
| ab (Apache Bench) | 命令行工具,简单快速 | 快速验证 |
| wrk / wrk2 | C 编写,极高并发能力 | 高性能测试 |
💡 快速使用 ab 压测
# 安装 (Mac) brew install ab # 压测:100 并发,共 1000 请求 ab -n 1000 -c 100 http://localhost:8080/api/test
输出包含:Requests per second(QPS)、Time per request、Transfer rate 等关键指标。
使用 Java + JMH(微基准测试)
如果你的目标是压测单个方法的性能(而非完整的 HTTP 请求链),请使用 JMH(Java Microbenchmark Harness)。
示例代码(简化)
@BenchmarkMode(Mode.Throughput) // 吞吐量
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
public class MyBenchmark {
@Benchmark
public void testMethod() {
// 这里放你要测试的方法
MyService service = new MyService();
service.process("test");
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(MyBenchmark.class.getSimpleName())
.forks(1)
.warmupIterations(3)
.measurementIterations(5)
.threads(4)
.build();
new Runner(opt).run();
}
}
注意:JMH 适合
微基准,不适合压测数据库或外部网络依赖。
压测实战建议
-
配置 JVM 参数
压测时,注意调整堆内存、GC 策略,避免被 GC 干扰结果。-Xms2g -Xmx2g -XX:+UseG1GC
-
预留预热期
JVM 有 JIT 编译和类加载,压测前先“预热”几次(Warm-up),使数据有效。 -
监控系统资源
使用top、jstat、VisualVM观察 CPU、内存、GC 情况,发现瓶颈。 -
分布式压测
单机性能有限,需压测上万并发时,考虑 JMeter 分布式、Gatling 集群。
| 场景 | 推荐方式 |
|---|---|
| 快速验证单个方法性能 | Java 原生并发 + CountDownLatch |
| 压测 REST API | 上面的 HttpStressTest + 适当提高并发 |
| 专业级 HTTP 压测 | JMeter (GUI友好) 或 Gatling (代码驱动) |
| 微基准测试 | JMH |
| 命令行快速调试 | ab 或 wrk |
如果你能提供更具体的需求(如:压测数据库连接池、WebSocket、gRPC),我可以给出针对性的案例。