gpt4 book ai didi

java - 如何在 Spring Web MVC Controller 中利用非阻塞请求

转载 作者:行者123 更新时间:2023-11-30 01:51:00 31 4
gpt4 key购买 nike

我试图演示在 Spring MVC 中使用响应式流的优势。为此,我有一个运行两个端点的小型 Jetty 服务器:

  • /normal 返回 POJO
  • /flux 返回包装在 Mono 中的相同对象

然后,我启动一个客户端,并在这些端点之一发起数千个并发请求。我本来希望在第二个端点上看到更少的错误,其中处理是异步发生的。但是,我有时会在启用异步的端点上观察到更多个错误;在这两种情况下,连接被拒绝:没有更多信息的错误率在 60 - 90% 之间。

要么我在这里做错了什么,要么我不太明白。 连接被拒绝正是我希望避免的事情。

服务器

这是我来自服务器的代码。在正常情况下,我实际上用.sleep()阻塞线程:

@Controller
public class FluxController {
@GetMapping(value = "/normal", produces = MediaType.APPLICATION_JSON_VALUE)
public Map normal() throws Exception {
Thread.sleep(randomTime());
return Collections.singletonMap("type", "normal");
}

@GetMapping(value = "/flux", produces = MediaType.APPLICATION_JSON_VALUE)
public Mono<Map> flux() {
return Mono.delay(Duration.ofMillis(randomTime()))
.map(x -> Collections.singletonMap("type", "flux"));
}

private static long randomTime() {
return ThreadLocalRandom.current().nextLong(200, 1000);
}
}

服务器通过 Maven 在 Jetty 9.4.15 上运行,web.xml 定义如下:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">

客户端

我的客户端使用 Spring WebClient:

public class ClientApplication {

private static final String ENDPOINT = "normal";

private static final int REPETITIONS = 10_000;

public static void main(String[] args) {
WebClient client = WebClient.create("http://localhost:8080");

AtomicInteger errors = new AtomicInteger(0);

List<Mono<Response>> responses = IntStream.range(0, REPETITIONS)
.mapToObj(i -> client.get()
.uri(ENDPOINT)
.retrieve()
.bodyToMono(Response.class)
.doOnError(e -> errors.incrementAndGet())
.onErrorResume(e -> Mono.empty())
)
.collect(Collectors.toList());
Mono.when(responses)
.block();
System.out.println(String.format("%-2f %% errors", errors.get() * 100.0 / REPETITIONS));
}

static class Response {
public String type;
}

}

与此处问题类似的前提:WebFlux async processing 。主要区别在于我测试的是错误率,或者同步连接数;我预计速度不会提高。

最佳答案

事实证明,虽然 Servlet 3.1 规范支持非阻塞 IO,但 Spring MVC 不支持。要充分利用响应式(Reactive) API,您必须使用 WebFlux。请参阅此处了解更多信息:https://youtu.be/Dp_aJh-akkU?t=1738 .

此图展示了 Spring MVC(左侧)与 Webflux(右侧)相比的工作原理。

Spring MVC vs Webflux Stack

我使用 Gatling 执行了更多测试并有类似的结果:两者花费的时间大致相同,异步的可靠性稍差。但是,我确实注意到一个半可重现的差异:异步结果有时响应速度更快:

正常

Response Time Distribution when returning standard type

第 50 个百分位数:33.6 秒第 95 个百分位数:35.4 秒

响应式(Reactive)

Response Time Distribution when returning Flux

第 50 个百分位数:6.51 秒第 95 个百分位数:49.5 秒

我仍然不清楚在 Spring MVC 中使用异步调用(例如 DeferredResult)或 Reactive Streams API 的优点。因此,如果有人能够通过具体用例来澄清这一点,我们将不胜感激。

关于java - 如何在 Spring Web MVC Controller 中利用非阻塞请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56079761/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com