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

反应式WebClient未发出响应

仇睿
2023-03-14

我有一个关于Spring Reactive WebClient的问题...几天前,我决定在Spring Framework中玩新的反应式东西,我做了一个仅用于个人目的的抓取数据的小项目。(向一个网页发出多个请求并组合结果)。

我开始使用新的反应式WebClient发出请求,但我发现的问题是客户端没有对每个请求发出响应。听起来很奇怪。下面是我为获取数据所做的工作:

private Mono<String> fetchData(String uri) {
    return this.client
            .get()
            .uri(uri)
            .header("X-Fsign","SW9D1eZo")
            .retrieve()
            .bodyToMono(String.class)
            .timeout(Duration.ofSeconds(35))
            .log("category", Level.ALL, SignalType.ON_ERROR, SignalType.ON_COMPLETE, SignalType.CANCEL, SignalType.REQUEST);
}

以及调用fetchData的函数:

public Mono<List<Stat>> fetch() {
    return fetchData(URL)
            .map(this::extractUrls)
            .doOnNext(System.out::println)
            .doOnNext(s-> System.out.println("all ids are "+s.size()))
            .flatMapIterable(q->q)
            .map(s -> s.substring(7, 15))
            .map(s -> "http://d.flashscore.com/x/feed/d_hh_" + s + "_en_1") // list of N-length urls
            .flatMap(this::fetchData)
            .map(this::extractHeadToHead)
            .collectList();
}

和订户:

    FlashScoreService bean = ctx.getBean(FlashScoreService.class);
    bean.fetch().subscribe(s->{
        System.out.println("finished !!! " + s.size()); //expecting same N-length list size
    },Throwable::printStackTrace);

问题是如果我提出更多的要求

我发出的请求基于字符串列表(URL),在发出所有响应后,我应该以列表的形式接收所有请求,因为我使用的是collectList()。当我执行100个请求时,我希望收到100个响应的列表,但实际上我有时收到100个,有时96个,等等。。。可能是什么东西悄悄地失败了。这很容易复制,这里是我的github项目链接。

示例输出:

all ids are 176
finished !!! 171

请给我建议如何调试或我做错了什么。感谢您的帮助。

更新时间:

日志显示如果我通过126网址例如:

onNext(ReactorClientHttpResponse{request=[GET/some_url],status=200}) is called 121 times. May be here is the problem.
onComplete() is called 126 times which is the exact same length of the passed list of urls

但是,如何在不调用onNext()或onError()的情况下完成某些请求呢?(Mono中的成功与错误)

我认为问题不在于WebClient,而在于其他地方。环境或服务器阻止了请求,但可能是我应该收到一些错误日志。

附:谢谢你的帮助!

共有1个答案

甄阳朔
2023-03-14

这是一个棘手的问题。调试实际收到的HTTP帧,似乎我们真的没有收到某些请求的响应。使用Wireshark进行更多调试,看起来远程服务器正在使用FIN,确认字符TCP数据包请求连接结束,并且客户端确认了它。问题是这个连接仍然从池中取出,以便在第一个FIN,确认字符TCP数据包之后发送另一个GET请求。

可能远程服务器在服务了大量请求后正在关闭连接;无论如何,这是完全合法的行为。请注意,我并没有始终如一地再现这一点。

您可以在客户端上禁用连接池;这将更加缓慢,显然不会引发此问题。为此,请使用以下方法:

this.client = WebClient.builder()
                .clientConnector(new ReactorClientHttpConnector(new Consumer<HttpClientOptions.Builder>() {
                    @Override
                    public void accept(HttpClientOptions.Builder builder) {
                        builder.disablePool();
                    }
                }))
                .build();

根本问题是,当TCP连接关闭时,HTTP客户端不应在不发送响应的情况下完成。或者更好的是,HTTP客户端在关闭连接时不应重用连接。等我知道更多的时候,我会在这里汇报的。

 类似资料:
  • 问题内容: 目前,我在使用新的Spring 5 WebClient时遇到问题,需要一些帮助来解决它。问题是: 我请求一些返回json响应的URL,其内容类型为 text / html; charset = utf-8 。 但不幸的是,我仍然遇到异常: org.springframework.web.reactive.function.UnsupportedMediaTypeException:不支

  • 我正在尝试为Vertx web客户端编写一个包装器,以便使用reactivestreams中的Publisher从服务器加载响应正文: 此解决方案是不正确的,因为它通过调用以阻塞方式读取所有正文字节。 是否可以分块读取来自Vertx网络客户端的响应,并将其转换为发布者(或Rx可流动的)?

  • 目前我有一个问题与新的Spring5WebClient,我需要一些帮助来解决它。问题是: 我请求一些url返回内容类型为text/html;charset=utf-8的json响应。 顺便说一句,我在accept头中指向哪种类型并不重要,总是返回text/html。那么如何最终转换我的响应呢?

  • 我使用了来自org的openapi生成器maven插件。在我的Spring Boot项目中启用了被动配置的openapitools。我的一个endpoint返回一个列表体响应,该响应自动生成为Mono 如何使用WebTestClient在联调中测试endpoint控制器的主体? 如果我尝试这样做,它不会起作用,因为我接收到的是通量,而不是预期的dto对象。

  • 我希望从spring reactive WebClient进行SOAP调用。我找不到任何文件。想知道会有什么方法。现在我在想 null 缺点和其他方法是什么?

  • 我正在尝试理解WebFlux,但在WebClient调用方面遇到了一些问题。我没有看到这一行System.out.println("CusterId="CusterId);执行它似乎不调用endpoint。但是如果我使用。订阅(客户-