当前位置: 首页 > 知识库问答 >
问题:

使用多个客户端的Spring webflux超时

史烨
2023-03-14

我有一个与其他几个服务交互的服务。因此,我为它们创建了单独的webclients(因为BasePath不同)。我已经根据https://docs.spring.io/spring/docs/5.1.6.release/spring-framework-reference/web-reactive.html#webflux-client-builder-reactor-timeout分别为它们设置了超时,但这似乎并不有效。其中一个服务尝试将ReadTimeout降低到2秒,但该服务似乎没有超时(使用logging.level.org.springframework.web.reactive=debug的日志显示,完成请求大约需要6-7秒)。

我使用的是Spring5.1和Netty0.8,我在webclient中使用阻塞,因为我们还没有完全使用webflux。我尝试了一下每个调用的超时时间,似乎有些调用确实响应了超时,而有些调用则没有(更多细节与代码一起在下面)

如何初始化webclients-

@Bean
public WebClient serviceAWebClient(@Value("${serviceA.basepath}") String basePath,
                                          @Value("${serviceA.connection.timeout}") int connectionTimeout,
                                          @Value("${serviceA.read.timeout}") int readTimeout,
                                          @Value("${serviceA.write.timeout}") int writeTimeout) {

    return getWebClientWithTimeout(basePath, connectionTimeout, readTimeout, writeTimeout);
}

@Bean
public WebClient serviceBWebClient(@Value("${serviceB.basepath}") String basePath,
                                           @Value("${serviceB.connection.timeout}") int connectionTimeout,
                                           @Value("${serviceB.read.timeout}") int readTimeout,
                                           @Value("${serviceB.write.timeout}") int writeTimeout) {

    return getWebClientWithTimeout(basePath, connectionTimeout, readTimeout, writeTimeout);
}

@Bean
public WebClient serviceCWebClient(@Value("${serviceC.basepath}") String basePath,
                                           @Value("${serviceC.connection.timeout}") int connectionTimeout,
                                           @Value("${serviceC.read.timeout}") int readTimeout,
                                           @Value("${serviceC.write.timeout}") int writeTimeout) {

    return getWebClientWithTimeout(basePath, connectionTimeout, readTimeout, writeTimeout);
}

private WebClient getWebClientWithTimeout(String basePath,
                                          int connectionTimeout,
                                          int readTimeout,
                                          int writeTimeout) {


    TcpClient tcpClient = TcpClient.create()
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, connectionTimeout)
            .doOnConnected(connection ->
                    connection.addHandlerLast(new ReadTimeoutHandler(readTimeout))
                            .addHandlerLast(new WriteTimeoutHandler(writeTimeout)));

    return WebClient.builder().baseUrl(basePath)
            .clientConnector(new ReactorClientHttpConnector(HttpClient.from(tcpClient))).build();

我是如何使用它的(为每个webclient提供包装器类)-

Mono<ResponseA> serviceACallMono = ..;
Mono<ResponseB> serviceBCallMono = ..;
Mono.zip(serviceACallMono,serviceBCallMono,
(serviceAResponse, serviceBResponse) -> serviceC.getImportantData(serviceAResponse,serviceBResponse))
.flatMap(Function.identity)
.block();

所以在上面,我注意到了以下--

编辑:更新,所以我可以用一种更简单的方式再现这个问题。所以,就像-

return serviceACallMono
                .flatMap(notUsed -> serviceBCallMono);

serviceACallMono的超时是值得尊敬的,但是无论您为serviceB降低多少,它都不会超时。

如果你只是翻转订单-

return serviceBCallMono
                .flatMap(notUsed -> serviceACallMono);
@Override
    public Mono<ServiceCResponse> getImportantData(ServiceAResponse requestA,
                                                   ServiceBResponse requestB) {

        return serviceCWebClient.post()
                .uri(GET_IMPORTANT_DATA_PATH, requestB.getAccountId())
                .body(BodyInserters.fromObject(formRequest(requestA)))
                .retrieve()
                .bodyToMono(ServiceC.class);
    }

formRequest是一种简单的POJO转换方法。

共有1个答案

祝俊雄
2023-03-14

我使用spring-boot starter parent来拉取各种spring依赖项。将其从2.1.2升级到2.1.4似乎可以解决这个问题。

 类似资料:
  • 如果您更喜欢使用配置属性来配置所有@FaignClient,您可以使用默认的假名创建配置属性。也可以通过命名客户端来为每个特定客户端设置这些超时。当然,我们可以列出一个全局设置,也可以毫无问题地将每个客户端覆盖在一起。 我的客户: 我试图做到这一点,我希望foo-client.read超时覆盖default.read超时时,我使用foo客户端: 但这并没有发生。我不确定Hystrix的Timeou

  • 我正在使用Netty4创建一个需要为多个客户端连接提供服务的服务器。ServerBootstrap由父线程组和工作线程组构成。根据ServerBootStrap上的文档。group()方法it “为父(接收器)和子(客户端)设置EventLoopGroup。这些EventLoopGroup用于处理SocketChannel和Channel的所有事件和IO。” 据我所知,ParentExecutor

  • 问题内容: RMI是否自己处理多个客户端?即 是否可以同时使用多个客户端的服务器功能? 如果没有,我该怎么做? 如果是,它如何工作?每次 调用 都会创建一个新线程吗?如果一个客户端阻止了该功能,那么下一个客户端会发生什么?等等 问题答案: 是 这个怎么运作?每次调用都会创建一个新线程吗?如果一个客户端阻止了该功能,那么下一个客户端会发生什么?等等 它为每个客户端连接创建一个线程。 如果一个客户端调

  • 我需要让客户能够建立许多连接。我使用Netty 4.0。不幸的是,所有现有的示例都没有显示如何创建大量连接。 这是正确的决定吗?还是会更好?

  • 我刚刚把我的Netty 3软件转换成5,我遇到了一个问题。只有一个客户,一切都很好。我可以使用两个解码器(它们可以正常切换)并允许我登录。 当我尝试连接另一个客户端时,无论第一个客户端是否仍然连接,都会出现问题。第一个客户端保持连接绝对正常,但第二个客户端根本无法连接(不通过第一个解码器)。 这是我的引导程序: 第一解码器: http://pastebin.com/9FWzXSVE 第二个解码器:

  • 我正在使用Apache HTTP客户端联系外部服务。这项服务可能需要几个小时(如果不是更长的话)才能产生响应。我尝试了一些不同的方法,但要么以套接字结束,要么以读取超时结束。我刚刚尝试使用RequestConfig将套接字和连接超时设置为0,根据文档,这应该是无限的,但请求总是在1小时后返回。有什么想法吗?