【发布时间】:2021-06-23 14:56:18
【问题描述】:
我正在使用 Spring 的“WebClient”和项目反应器对 URL 列表进行非阻塞调用。我的要求是:
- 在 URL 列表上异步调用 GET
- 在调用每个 URL 时记录 URL
- 记录导致异常的调用的 URL
- 记录成功调用的 URL
- 记录导致非 2xx HTTP 状态的调用的 URL
- 发送一封电子邮件,其中包含调用导致异常或非 2xx HTTP 状态的 URL 列表
这是我的尝试:
List<Mono<ClientResponse>> restCalls = new ArrayList<>();
List<String> failedUrls = new ArrayList<>();
for (String serviceUrl : serviceUrls.getServiceUrls()) {
restCalls.add(
webClientBuilder
.build()
.get()
.uri(serviceUrl)
.exchange()
.doOnSubscribe(c -> log.info("calling service URL {}", serviceUrl))
.doOnSuccess(response -> log.info("{} success status {}", serviceUrl, response.statusCode().toString()))
.doOnError(response -> {log.info("{} error status {}", serviceUrl, response); failedUrls.add(serviceUrl);}));
}
Flux.fromIterable(restCalls)
.map((data) -> data.subscribe())
.onErrorContinue((throwable, e) -> {
log.info("Exception for URL {}", ((WebClientResponseException) throwable).getRequest().getURI());
failedUrls.add(serviceUrl);
})
.collectList()
.subscribe((data) -> {
log.info("all called");
email.send("Failed URLs are {}", failedUrls);
});
问题是电子邮件是在电话响应之前发送的。在调用email.send 之前,如何等待所有 URL 调用完成?
【问题讨论】:
-
您至少应该将
.map((data) -> data.subscribe())替换为.flatMap(data -> data),因为订阅会触发操作,但不允许观察其结果(返回值仅用于取消已启动的作业)。另外,请注意 onErrorContinue(更多信息on this issue)。稍后我会尝试添加更扩展的答案,但也许这些提示足以解决您的问题。
标签: spring spring-boot reactive-programming project-reactor spring-webclient