spring webflux - websocketclient线程无法终止

时间:2017-11-19 21:27:34

标签: java spring websocket spring-webflux

我正在使用Spring WebFlux WebSocketClient来订阅和处理来自远程Web套接字的消息。在处理期间,来自远程套接字的消息的Flux有时会意外地完成(或在出错时终止),从而导致Web套接字客户端的onComplete(或onError)回调执行。发生这种情况时,我的onCompleteonError回调会发布一个事件。事件侦听器通过调用创建另一个Web套接字客户端的函数来响应,该客户端连接到同一个外部Web套接字并且套接字处理重新开始。

我的问题是,在客户端完成处理后,我无法弄清楚如何释放WebSocketClient资源。这会导致未使用的线程在JVM中累积。特别是运行第一个WebSocketClientWebSocketClient-SecureIO-1WebSocketClient-SecureIO-2parallel-1)的线程保持等待状态,并为新的“WebSocketClient”启动新线程。我认为在close()上调用WebSocketSession可以解决问题,但事实并非如此。

我的实施模式是:

public void startProcessing() {
   WebSocketClient client = new StandardWebSocketClient();
   Mono<String> subscribeMsg = Mono.just("...");

   client
      .execute(uri, webSocketSession ->
          webSocketSession
             .send(subscribeMsg.map(webSocketSession::textMessage))
             .thenMany(webSocketSession.receive())
             .map(webSocketMessage -> ...)
             .buffer(Duration.ofSeconds(bufferDuration))
             .doOnNext(handler)
             .doOnComplete(() -> webSocketSession.close())
             .then())
       .subscribe(
            aVoid -> LOGGER.info("subscription started"),
            throwable -> {... publish restart event ...},
            () -> {... publish restart event ...});
}

public void restartEventListener() {
    startProcessing();
}

关于如何防止未使用的WebSocketClient线程在JVM中累积的任何建议?

1 个答案:

答案 0 :(得分:1)

一些想法:

WebSocketClient正在汇集资源,因此您应该为许多请求重用相同的客户端。

您应避免在doOn*运算符内进行处理。这些是副作用运算符,并在当前Scheduler上同步执行。为了提高效率,您应该使用其他运营商。您可以将websocket消息映射到Flux<DataBuffer>,然后使用DataBufferUtils::write将这些消息写入文件,并仍使用相同的响应管道而不是使用副作用运算符。

关闭其中一个websocket会话并不是一个坏主意,尽管我会使用doOnTerminate来触发成功和错误情景。

此外,我不了解发布事件以重新启动处理阶段的目标。使用retryrepeat运算符以及相同的客户端应该可以正常工作并且效率更高。