Webflux WebCient 的时间成本

问题描述 投票:0回答:1

我有一个 Spring Boot 服务,它使用 WebClient 调用另一个外部服务。外部服务的平均延迟约为 15 ms(通过 Datadog 测量)。但是,当通过我们的服务调用外部 API 时,使用 webClient 调用外部 API 所花费的平均时间远高于该值,约为 65 毫秒。

这是如何调用外部API的示例代码。

public Foo fetchFoo() {
    return webClient.get()
        .uri(uriBuilder -> uriBuilder
            .path(externalAPIEndPoint)
            .build())
        .retrieve()
        .bodyToMono(Foo.class)
        .retry(defaultMaxRetry)
        .block();
}

造成如此巨大时差的原因是什么?我们可以采取哪些方法来减少所需时间?

java spring-boot spring-webflux reactive-programming project-reactor
1个回答
0
投票

造成延误的原因有很多。例如:

延迟原因:

  • 您正在使用的方法

    .block();
    可能会导致延迟,您可以删除它并继续重试。

  • 对 externalAPIEndpoint 的调用可能会因创建新连接或由于

    handshake/TLS
    检查而产生网络延迟。这可以通过使用
    connection pool
    来改进。

  • retry() 方法也会导致延迟,因为通常重试都有重要的参数,例如重试延迟和重试次数。因此,优化您的重试策略(根据需要)也有助于减少延迟。

我建议的改进:

  • 利用连接池,例如:

代码示例:

HttpClient httpClient = HttpClient.create(ConnectionProvider.builder("custom")
    .maxConnections(100)
    .build());
WebClient client = WebClient.builder()
    .clientConnector(new ReactorClientHttpConnector(httpClient))
    .build();
  • 删除
    block()
    方法,你的代码变成:

代码示例

public Mono<Foo> fetchFoo() {
    return webClient.get()
        .uri(uriBuilder -> uriBuilder.path(externalAPIEndPoint).build())
        .retrieve()
        .bodyToMono(Foo.class)
        .retry(defaultMaxRetry);
}
  • 为了更好地了解延迟,您应该检查运行状况和指标,基于此您可以更好地了解到底需要改进什么。

额外内容(它们可能超出了本文的范围,但也许值得一提):

  • 您还可以添加缓存策略,以提高性能,以防负载流量较高。

  • 您还可以根据特定指标添加自动缩放。

© www.soinside.com 2019 - 2024. All rights reserved.