Spring Boot 中的发件箱模式

75 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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 的统计数据:

image.png

image.png

image.png

在压力测试期间,我们观察到 Webflux 服务优于@Async方法。

从JMeter 中 Webflux 的平均(4021) 和最大(8090) 统计数据可以看出这一点。

当我们使用 Postman 执行筒仓测试时,我们注意到 Webflux 服务的响应时间显着减少。

Webflux 与 Spring 中的 @Async 方法相比有几个好处。它使用反应式编程和非阻塞 I/O,使其高效且响应迅速。

请务必记住,性能优化需要平衡各种因素,例如速度、资源使用以及开发和维护的便利性。

因此,在决定使用哪种方法时,考虑应用程序的具体要求和限制至关重要。