簡體   English   中英

Spring 集成 如果服務器關閉連接怎么辦,接收任意事件時如何處理和打開

[英]Spring integration what if server close connection, how handle it and open while receiving arbitrary events

我正在使用動態 tcp 路由的基本代碼,並在 Gary Russell 的幫助下對其進行擴展,

子流代碼:在這里我可以接收帶有擴展 TcpOutboundGateway 的任意消息。 如果消息是任意來的,沒有客戶端的請求,它由 ExtendedTcpOutBoundGateway 的直接消息通道處理

private MessageChannel createNewSubflow(Message<?> message) {
    String host = (String) message.getHeaders().get("host");
    Integer port = (Integer) message.getHeaders().get("port");

    boolean hasThisConnectionIrregularChannel = message.getHeaders().containsKey("irregularMessageChannelName");

    Assert.state(host != null && port != null, "host and/or port header missing");
    String flowRegisterKey;

    if (hasThisConnectionIrregularChannel) {
        flowRegisterKey = host + port + ".extended";
    } else {
        flowRegisterKey = host + port;
    }

    TcpNetClientConnectionFactory cf = new TcpNetClientConnectionFactory(host, port);
    cf.setSoTimeout(0);
    cf.setSoKeepAlive(true);

    ByteArrayCrLfSerializer byteArrayCrLfSerializer = new ByteArrayCrLfSerializer();
    byteArrayCrLfSerializer.setMaxMessageSize(1048576);

    cf.setSerializer(byteArrayCrLfSerializer);
    cf.setDeserializer(byteArrayCrLfSerializer);

    TcpOutboundGateway tcpOutboundGateway;
    if (hasThisConnectionIrregularChannel) {
        log.info("TcpRouter # createNewSubflow extended TcpOutboundGateway will be created");
        String unsolicitedMessageChannelName = (String) message.getHeaders().get("irregularMessageChannelName");
        DirectChannel directChannel = getBeanFactory().getBean(unsolicitedMessageChannelName, DirectChannel.class);
        tcpOutboundGateway = new ExtendedTcpOutboundGateway(directChannel);
    } else {
        log.info("TcpRouter # createNewSubflow extended TcpOutboundGateway will be created");
        tcpOutboundGateway = new TcpOutboundGateway();
    }

    tcpOutboundGateway.setConnectionFactory(cf);

    tcpOutboundGateway.setAdviceChain(Arrays.asList(new Advice[]{tcpRetryAdvice()}));

    IntegrationFlow flow = f -> f.handle(tcpOutboundGateway);

    IntegrationFlowContext.IntegrationFlowRegistration flowRegistration =
        this.flowContext.registration(flow)
            .addBean(cf)
            .id(flowRegisterKey + ".flow")
            .register();

    MessageChannel inputChannel = flowRegistration.getInputChannel();

    this.subFlows.put(flowRegisterKey, inputChannel);
    return inputChannel;
}

在這里,我可以處理重試建議以再次設置連接。

@Bean
public RequestHandlerRetryAdvice tcpRetryAdvice() {
    SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy();
    retryPolicy.setMaxAttempts(2);

    ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
    backOffPolicy.setInitialInterval(100);
    backOffPolicy.setMaxInterval(1000);
    backOffPolicy.setMultiplier(2);

    RetryTemplate retryTemplate = new RetryTemplate();
    retryTemplate.setRetryPolicy(retryPolicy);
    retryTemplate.setBackOffPolicy(backOffPolicy);

    RequestHandlerRetryAdvice tcpRetryAdvice = new RequestHandlerRetryAdvice();
    tcpRetryAdvice.setRetryTemplate(retryTemplate);

    // This allows fail-controlling
    tcpRetryAdvice.setRecoveryCallback(new ErrorMessageSendingRecoverer(failMessageChannel()));

    return tcpRetryAdvice;
}

@Bean
public MessageChannel failMessageChannel() {
    return new DirectChannel();
}

@ServiceActivator(inputChannel = "failMessageChannel")
public void messageAggregation(String in) {
    log.error("TcpRouter # connection retry failed with message : " + in);
}

但現在我需要處理另一種情況;

如果在接收來自服務器的任意消息期間連接關閉怎么辦? 不知何故,連接可以從服務器端關閉,我需要處理連接關閉事件並再次設置連接以繼續接收任意事件。

我應該如何通過 spring 集成捕獲該事件並再次重新建立連接?

編輯 1

我用谷歌搜索了一些相同的問題,發現來自這個鏈接EventListener 主題的 EventListener 但在那個鏈接中,據我所知只有一個連接,所以在我的情況下,我是客戶端並使用動態 tcp 路由,這就是為什么我需要實現邏輯來處理不同的連接。

編輯 2

這是確定目標渠道

@Override
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
    MessageChannel channel;
    boolean hasThisConnectionIrregularChannel = message.getHeaders().containsKey("irregularMessageChannelName");
    if (hasThisConnectionIrregularChannel) {
        channel = this.subFlows.get(message.getHeaders().get("host", String.class) + message.getHeaders().get("port") + ".extended");
    } else {
        channel = this.subFlows.get(message.getHeaders().get("host", String.class) + message.getHeaders().get("port"));
    }

    if (channel == null) {
        channel = createNewSubflow(message);
    }
    return Collections.singletonList(channel);
}

這是ToTCP接口

@Component
@MessagingGateway(defaultRequestChannel = "toTcp.input")
public interface ToTCP {
    byte[] send(String data, @Header("host") String host, @Header("port") int port, @Header("irregularMessageChannelName") String channelName);

byte[] send(String data, @Header("host") String host, @Header("port") int port);

}

.addBean(cf)

如果您使用.addBean("someBeanName", cf)您可以檢查TcpConnectionClosedEventconnectionFactoryName (這將是您在addBean()中給 cf 的 id)。

然后,您可以將新消息路由到具有該工廠以重新建立連接的流。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM