java - reactor-netty:使用 keep-alive HTTP 客户端

标签 java project-reactor reactor-netty

我使用reactor-netty来请求一组URL。大多数 URL 属于同一主机。 Reactor-netty 似乎会为每个 URL 建立一个全新的 TCP 连接,即使已经为前一个 URL 建立了与主机的连接。当建立数百个同时连接时,某些服务器会丢弃新连接或开始响应缓慢。

代码示例:

    Flux.just(...)
    .groupBy(link -> {
        String host = "";
        try {
            host = new URL(link).getHost();
        } catch (MalformedURLException e) {
            LOGGER.warn("Cannot determine host {}", link, e);
        }
        return host;
    })
    .flatMap(group -> {
        HttpClient client = HttpClient.create()
                .keepAlive(true)
                .tcpConfiguration(tcp -> tcp.host(group.key()));
        return group.flatMap(link -> client.get()
            .uri(link)
            .response((resp, cont) -> resp.status().code() == 200 ? cont.aggregate().asString() : Mono.empty())
            .doOnSubscribe(s -> LOGGER.debug("Requesting {}", link))
            .timeout(Duration.ofMinutes(1))
            .doOnError(e -> LOGGER.warn("Cannot get response from {}", link, e))
            .onErrorResume(e -> Flux.empty())
            .collect(Collectors.joining())
            .filter(s -> StringUtils.isNotBlank(s)));
    })
    .blockLast();

在日志中,我看到同一远程主机的本地端口不同,并且 Activity 和非 Activity 连接的总和远高于不同主机的数量。这就是为什么我认为 Reactor-netty 没有重用已经建立的连接。

DEBUG [2019-04-29 08:15:18,711] reactor-http-nio-10 r.n.r.PooledConnectionProvider: [id: 0xaed18e87, L:/192.168.1.183:56832 - R:capcp2.naad-adna.pelmorex.com/52.242.33.4:80] Releasing channel
DEBUG [2019-04-29 08:15:18,711] reactor-http-nio-10 r.n.r.PooledConnectionProvider: [id: 0xaed18e87, L:/192.168.1.183:56832 - R:capcp2.naad-adna.pelmorex.com/52.242.33.4:80] Channel cleaned, now 1 active connections and 239 inactive connections
...
DEBUG [2019-04-29 08:15:20,158] reactor-http-nio-10 r.n.r.PooledConnectionProvider: [id: 0xd6c6c5db, L:/192.168.1.183:56965 - R:capcp2.naad-adna.pelmorex.com/52.242.33.4:80] Releasing channel
DEBUG [2019-04-29 08:15:20,158] reactor-http-nio-10 r.n.r.PooledConnectionProvider: [id: 0xd6c6c5db, L:/192.168.1.183:56965 - R:capcp2.naad-adna.pelmorex.com/52.242.33.4:80] Channel cleaned, now 0 active connections and 240 inactive connections

是否可以使用 keep-alive HTTP 客户端通过与主机的同一 TCP 连接请求同一主机上的多个 URL?如果没有,如何限制对同一主机的同时连接数或按顺序向同一主机执行请求(仅在收到上一个请求的响应后才进行下一个请求)?

我使用Californium-SR6发布列车。

最佳答案

是的,reactor netty 支持 keep-alive、连接重用和连接池。

请注意,.flatMap 是并行处理内部流的异步操作。因此,当您调用 group.flatMap(... 时,内部请求将并行执行。由于它们是并行执行的,因此需要建立多个连接。

如果您想按顺序对同一主机执行请求,请将示例更改为使用 group.concatMap 而不是 .flatMap

如果您仍想并行执行它们,但限制对单个主机的 Activity 请求数量,请更改示例以使用 .flatMap 的重载版本之一,该版本采用 并发参数。

此外,由于您使用的是 HttpClient.create(),因此您的示例使用默认的全局 http 连接池。如果您想对连接池进行更多控制,可以指定不同的 ConnectionProvider通过HttpClient.create(ConnectionProvider)

关于java - reactor-netty:使用 keep-alive HTTP 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55899414/

相关文章:

java - 无法打开 JDBC 连接 oracle 和 spring boot

java - 如何通过 Spring Webflux 中的 websockets 向特定客户端发送消息?

java - Reactor 和 Webflux 中的 Mono 链的超时运算符究竟测量了什么?

java - 使用 SpringFlux 的 webclient 重复 Mono

Netty HttpClient - 响应超时与读取超时

http - 如何在 Reactor Netty 客户端中使用简单的 HTTP 代理?

httpclient - webClient 问题 - ReactorClientHttpConnector 和 httpClient 之间

java - 在 Eclipse 中轻松浏览 Java 注释

java - 在java中获取调用的方法堆栈

java - 是否可以在Java中进行JavaScript样式设置?