我正在使用Spring WebFlux WebSocketClient
来订阅和处理来自远程Web套接字的消息。在处理期间,来自远程套接字的消息的Flux有时会意外地完成(或在出错时终止),从而导致Web套接字客户端的onComplete
(或onError
)回调执行。发生这种情况时,我的onComplete
和onError
回调会发布一个事件。事件侦听器通过调用创建另一个Web套接字客户端的函数来响应,该客户端连接到同一个外部Web套接字并且套接字处理重新开始。
我的问题是,在客户端完成处理后,我无法弄清楚如何释放WebSocketClient
资源。这会导致未使用的线程在JVM中累积。特别是运行第一个WebSocketClient
(WebSocketClient-SecureIO-1
,WebSocketClient-SecureIO-2
和parallel-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中累积的任何建议?
答案 0 :(得分:1)
一些想法:
WebSocketClient
正在汇集资源,因此您应该为许多请求重用相同的客户端。
您应避免在doOn*
运算符内进行处理。这些是副作用运算符,并在当前Scheduler
上同步执行。为了提高效率,您应该使用其他运营商。您可以将websocket消息映射到Flux<DataBuffer>
,然后使用DataBufferUtils::write
将这些消息写入文件,并仍使用相同的响应管道而不是使用副作用运算符。
关闭其中一个websocket会话并不是一个坏主意,尽管我会使用doOnTerminate
来触发成功和错误情景。
此外,我不了解发布事件以重新启动处理阶段的目标。使用retry
和repeat
运算符以及相同的客户端应该可以正常工作并且效率更高。