首页 > 解决方案 > Spring Integration Tcp连接单用VS setSoKeepAlive

问题描述

我正在使用

TcpNetClientConnectionFactory cf = new TcpNetClientConnectionFactory(host, port);

对于 TcpOutboundGateway,通常 TcpOutboundGateway 正在工作请求/回复顺序,但在我的情况下,我扩展 TcpOutboundGateway 以使用 MessageChannel 接收任意消息。这就是为什么我认为我应该使用

cf.setLeaveOpen(true)

保持连接打开。

虽然我开始使用该选项,但很长一段时间后,当我再次调用 tcp 服务器时,我收到了类似的异常

org.springframework.integration.MessageTimeoutException:等待响应超时

但我不明白为什么会出现此错误,因为我设置“true”以在我的连接工厂中保持连接打开。

然后

我做了一些谷歌,它应该使用 CachingClientConnectionFactory,我知道默认情况下它是 single-use=true 并且不应该将其更改为 false,但是我假设连接将在我的每个请求响应事务中打开和关闭所以在没有来自客户端的任何请求的情况下从服务器接收任意数据是否有障碍?

或者

我应该如何保持客户端和服务器之间的开放连接?我应该使用

cf.setSoKeepAlive(true) ?

保持连接打开?是

cf.setSoKeepAlive(true) 和 cf.setLeaveOpen(true)

彼此一样吗?

编辑

此外,当我使用 cf.setSoKeepAlive(true) 时,1 小时后我也遇到了同样的异常。

完整代码:

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);

    CachingClientConnectionFactory ccf = new CachingClientConnectionFactory(cf, 20);
    ccf.setSoKeepAlive(true);

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

    ccf.setSerializer(byteArrayCrLfSerializer);
    ccf.setDeserializer(byteArrayCrLfSerializer);

    TcpOutboundGateway tcpOutboundGateway;
    if (hasThisConnectionIrregularChannel) {
        String unsolicitedMessageChannelName = (String) message.getHeaders().get("irregularMessageChannelName");
        DirectChannel directChannel = getBeanFactory().getBean(unsolicitedMessageChannelName, DirectChannel.class);
        tcpOutboundGateway = new ExtendedTcpOutboundGateway(directChannel);
    } else {
        tcpOutboundGateway = new TcpOutboundGateway();
    }
    tcpOutboundGateway.setRemoteTimeout(20000);

    tcpOutboundGateway.setConnectionFactory(ccf);

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

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

    MessageChannel inputChannel = flowRegistration.getInputChannel();

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

标签: javaspringspring-boottcpspring-integration

解决方案


你为什么使用CachingClientConnectionFactory? 保持连接打开时不需要它;当您想要维护多个打开的连接时使用它。

等待响应超时

意味着当您发送请求时套接字打开得很好(从客户端的角度来看);我们只是没有得到答复。这可能意味着某些网络组件(路由器)由于不活动而默默地关闭了套接字。Keep-alives 应该对此有所帮助,但这取决于您的操作系统以及 TCP 堆栈配置为发送 keep-alives 的频率。


推荐阅读