java—如何在SpringWebFlux应用程序中断开空闲客户机的连接?

noj0wjuj  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(581)

我有一个 spring-webflux 应用(引擎盖下有网状物)。有这样一种控制器方法:

public Mono<Response> submitBinaryData(@RequestHeader HttpHeaders headers,
                                       @RequestBody(required = false) Flux<DataBuffer> data) {
    return process(data.timeout(Duration.ofSeconds(10)), getContentLength(headers));
}
``` `process()` 方法不太有趣,它只是将二进制数据写入存储器。重要的是它预先知道有多少数据(通过 `Content-Length` 标题)。
那么,假设我们有一个客户被卡住了,就像这样:

byte[] bufferOf1Mb = new byte[1024 * 1024];
HttpRequest request = HttpRequest.newBuilder(new URI("http://localhost:8080/")
.setHeader("Accept", "application/json")
.setHeader("Content-Type", "application/octet-stream")
.POST(BodyPublishers.fromPublisher(JdkFlowAdapter.publisherToFlowPublisher(
Flux.just(ByteBuffer.wrap(bufferOf1Mb)).concatWith(Flux.never())), 10 * bufferOf1Mb.length))
.build();
HttpResponse httpResponse = client.send(request, BodyHandlers.ofString());

这个客户机宣布10mb的数据,但只写1mb,然后永远等待。
我希望这样的客户端在一段时间后被断开连接,以避免在可能永远中断的客户端上浪费资源。在控制器方法中,有 `timeout()` 投出一个 `TimeoutException` 如果数据在一段时间内不流动。然后异常被异常处理程序(未显示)捕获和处理:它只返回一个 `Response` 对象(作为json)。
问题是,即使发生了超时(可以在日志中看到),客户机也不会注意到任何事情。客户机可能正在等待服务器使用它的数据,只有这样它才会查看响应。但是输入永远不会被发送。服务器不会关闭连接,因为它希望客户端读取响应。因此,这种联系永远是开放的。
调试器还显示,发生这种情况时, `writeWith()` 以及 `setComplete()` 在响应对象上调用。
有没有办法断开这样一个客户的连接?使用超时设置(尽管 `server.netty.` 只有一个超时相关设置, `connection-timeout` 这不是这里所需要的),或者编程方式(当客户端明显丢失时,强制切断连接),或者其他方式?
cnjp1d6j

cnjp1d6j1#

如果将webclient用于http请求,则可以在构建webclient时在httpclient中设置responsetimeout。

@Bean
  public WebClient getWebClient(WebClient.Builder webClientBuilder) {

    ClientHttpConnector connector = new ReactorClientHttpConnector(
        HttpClient.create().responseTimeout(Duration.ofSeconds(10))
    );

    return webClientBuilder
        .clientConnector(connector)
        .build();

  }

参考文献:https://docs.spring.io/spring-framework/docs/5.0.7.release/spring-framework-reference/web-reactive.html#webflux-客户端生成器

相关问题