开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 25 天,点击查看活动详情
如果您正在用 Java 构建 Web 应用程序,您有多种处理异步处理的选项。
一种方法是在 Spring 中使用 @Async 注释将长时间运行的任务委托给单独的线程。另一种方法是使用 Spring WebFlux,它提供了一种非阻塞、事件驱动的编程模型来构建反应式 Web 应用程序。
在本文中,我们将探索使用 Spring WebFlux 而不是 @Async 注释的好处。
一个典型的应用程序会执行各种 I/O 事件,例如从数据库、外部 API 和文件中读取和写入数据。 缓存数据、与消息队列交互以及流式传输数据也是常见的 I/O 事件。
我选择了一个外部服务调用 (GET ipinfo.io/161.185.160…) 作为演示,并将通过使用 @Async 和 Web-flux 进行外部 API 调用来记录性能指标。
您可以找到项目中包含的文件 I/O 代码。
Webflux 控制器
@RestController
public class ExternalAPIController {
private final WebClient webClient;
public ExternalAPIController(WebClient.Builder webClientBuilder) {
this.webClient = webClientBuilder.baseUrl("https://ipinfo.io").build();
}
@GetMapping(value = "/data", produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<String> getData() {
System.out.println("Hit **");
return webClient.get()
.uri("/161.185.160.93/geo")
.retrieve()
.bodyToMono(String.class);
}
}
异步注解控制器
public class ExternalCall {
private final RestTemplate restTemplate;
public ExternalCall(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@GetMapping(value = "/data", produces = MediaType.APPLICATION_JSON_VALUE)
public CompletableFuture<String> getData() {
return getDataAsync();
}
@Async
public CompletableFuture<String> getDataAsync() {
String result = restTemplate.getForObject("https://ipinfo.io/161.185.160.93/geo", String.class);
return CompletableFuture.completedFuture(result);
}
}
衡量两种服务的性能,可以使用Apache JMeter或Gatling等负载测试工具,模拟大量请求,测量各种条件下每种方法的响应时间和吞吐量。
您还可以使用 Micrometer 等工具来收集有关应用程序性能的指标。
我使用 Apache JMeter 在两个不同的 VM 上分别加载和测试这两个应用程序。
我每秒生成 100 个请求来测试性能。
以下是 Jmeter 的统计数据:
在压力测试期间,我们观察到 Webflux 服务优于@Async方法。
从JMeter 中 Webflux 的平均(4021) 和最大(8090) 统计数据可以看出这一点。
当我们使用 Postman 执行筒仓测试时,我们注意到 Webflux 服务的响应时间显着减少。
Webflux 与 Spring 中的 @Async 方法相比有几个好处。它使用反应式编程和非阻塞 I/O,使其高效且响应迅速。
请务必记住,性能优化需要平衡各种因素,例如速度、资源使用以及开发和维护的便利性。
因此,在决定使用哪种方法时,考虑应用程序的具体要求和限制至关重要。