Spring boot 如何重新连接ReactorNettyWebSocketClient连接?

Spring boot 如何重新连接ReactorNettyWebSocketClient连接?,spring-boot,spring-webflux,reactor-netty,Spring Boot,Spring Webflux,Reactor Netty,我需要访问websocket服务,该服务在24小时后关闭打开的websocket连接。如何实现与Spring Boot 2和Webflux的重新连接 这是我到目前为止所做的(摘自): @GetMapping(path=“/stream”,products=MediaType.TEXT\u EVENT\u stream\u VALUE) public Flux getStreaming()抛出URISyntaxException{ ReactorNettyWebSocketClient=新的Rea

我需要访问websocket服务,该服务在24小时后关闭打开的websocket连接。如何实现与Spring Boot 2和Webflux的重新连接

这是我到目前为止所做的(摘自):

@GetMapping(path=“/stream”,products=MediaType.TEXT\u EVENT\u stream\u VALUE)
public Flux getStreaming()抛出URISyntaxException{
ReactorNettyWebSocketClient=新的ReactorNettyWebSocketClient();
EmitterProcessor输出=EmitterProcessor.create();
Mono sessionMono=client.execute(新URI(“ws://localhost:8080/echo”),
会话->会话.接收()
.超时(持续时间秒(3))
.map(WebSocketMessage::getPayloadAsText)
.th(输出)
.然后());
返回output.doOnSubscribe(s->sessionMono.subscribe());
}

一旦连接丢失(3秒钟不再输入),就会抛出TimeoutException。但是如何重新连接套接字呢?

没有现成的解决方案,重新连接机制不是JSR356-JavaAPI for WebSocket的一部分。但您可以自己实现它-一个简单的Spring事件示例:

步骤1-创建事件类。

public class ReconnectionEvent extends ApplicationEvent {

    private String url;

    public ReconnectionEvent(String url) {
        super(url);
        this.url = url;
    }

    public String getUrl() {
        return url;
    }

}
@EventListener(ReconnectEvent.class)
public void onApplicationEvent(ReconnectEvent event) {
    connect(event.getUrl());
}
步骤2-提供连接websocket的方法。示例:

...
@Autowired
private ApplicationEventPublisher publisher;
...
public void connect(String url) {

    ReactorNettyWebSocketClient client = new ReactorNettyWebSocketClient();

    EmitterProcessor<String> output = EmitterProcessor.create();

    Mono<Void> sessionMono = client.execute(URI.create(url),

            session -> session.receive()
                    .map(WebSocketMessage::getPayloadAsText)
                    .log()
                    .subscribeWith(output)
                    .doOnTerminate(() -> publisher.publishEvent(new ReconnectEvent(url)))
                    .then());

    output
            .doOnSubscribe(s -> sessionMono.subscribe())
            .subscribe();
}

我使用反应堆的
单播处理器
做了一些事情

...
public abstract class AbstractWsReconnectClient {
    private Logger ...

    protected UnicastProcessor<AbstractWsReconnectClient> reconnectProcessor = UnicastProcessor.create();

    protected AbstractWsReconnectClient(Duration reconnectDuration) {
        reconnect(reconnectDuration);
    }

    public abstract Mono<Void> connect();

    private void reconnect(Duration duration) {
        reconnectProcessor.publish()
            .autoConnect()
            .delayElements(duration)
            .flatMap(AbstractWsReconnectClient::connect)
            .onErrorContinue(throwable -> true,
                (throwable, o) -> {
                    if (throwable instanceof ConnectException) {
                        logger.warn(throwable.getMessage());
                    } else {
                        logger.error("unexpected error occur during websocket reconnect");
                        logger.error(throwable.getMessage());
                    }
                })
            .doOnTerminate(() -> logger.error("websocket reconnect processor terminate "))
            .subscribe();
    }
}

你好,乔安娜,非常感谢-我很快会查出来的!不能将
dointerminate
简化为
()->连接(url)
?需要发送应用程序事件的原因是什么?
...
public abstract class AbstractWsReconnectClient {
    private Logger ...

    protected UnicastProcessor<AbstractWsReconnectClient> reconnectProcessor = UnicastProcessor.create();

    protected AbstractWsReconnectClient(Duration reconnectDuration) {
        reconnect(reconnectDuration);
    }

    public abstract Mono<Void> connect();

    private void reconnect(Duration duration) {
        reconnectProcessor.publish()
            .autoConnect()
            .delayElements(duration)
            .flatMap(AbstractWsReconnectClient::connect)
            .onErrorContinue(throwable -> true,
                (throwable, o) -> {
                    if (throwable instanceof ConnectException) {
                        logger.warn(throwable.getMessage());
                    } else {
                        logger.error("unexpected error occur during websocket reconnect");
                        logger.error(throwable.getMessage());
                    }
                })
            .doOnTerminate(() -> logger.error("websocket reconnect processor terminate "))
            .subscribe();
    }
}
public Mono<Void> connect() {
    WebSocketClient client = new ReactorNettyWebSocketClient();
    logger.info("trying to connect to sso server {}", uri.toString());
    return client.execute(uri, headers, ssoClientHandler)
        .doOnTerminate(() -> {
            logger.warn("sso server {} disconnect", uri.toString());
            super.reconnectProcessor.onNext(this);
        });
}