【问题标题】:Spring Integration TCP - Initiate handshake with a message before sending dataSpring Integration TCP - 在发送数据之前使用消息启动握手
【发布时间】:2018-07-15 21:21:59
【问题描述】:

我正在使用@MessagingGateway 将数据发送到服务器。我为出站网关配置了 AbstractClientConnectionFactory 和 @ServiceActivator。

为了向我的服务器发送数据,我需要在连接启动时发送握手消息。如果来自服务器的响应是我期望的握手响应,那么我发送有意义的数据。我最初的解决方案是

if (gateway.handshake(HANDSHAKE).equals(HANDSHAKE_RESPONSE)) gateway.sendData(data);

当我扩大规模时,这不是很好,因为我已经通过 tcp 将我的呼叫增加了一倍,因为我只需要在连接启动时发送发送握手,而不是每次都发送。另外,我计划保持连接活跃。

那么在连接启动时,我怎样才能实现这个自定义握手呢?

@Bean
public AbstractClientConnectionFactory clientCF() {
    TcpNetClientConnectionFactory tcpNetClientConnectionFactory = new TcpNetClientConnectionFactory(host, port);

    tcpNetClientConnectionFactory.setSerializer(new serializerDeserializer());
    tcpNetClientConnectionFactory.setDeserializer(new serializerDeserializer());
    tcpNetClientConnectionFactory.setSoKeepAlive(true);
    tcpNetClientConnectionFactory.setSoTimeout(soTimeout);
    return tcpNetClientConnectionFactory;

}

@Bean
@ServiceActivator(inputChannel = "toTcp")
public MessageHandler tcpOutGate(AbstractClientConnectionFactory connectionFactory) {
    TcpOutboundGateway gate = new TcpOutboundGateway();
    gate.setConnectionFactory(connectionFactory);
    return gate;
}


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

【问题讨论】:

    标签: sockets tcp spring-integration


    【解决方案1】:

    Connection Interceptors

    可以使用对 TcpConnectionInterceptorFactoryChain 的引用来配置连接工厂。拦截器可用于向连接添加行为,例如协商、安全和其他设置。框架目前没有提供拦截器,但例如,请参阅源存储库中的 InterceptedSharedConnectionTests。

    测试用例中使用的HelloWorldInterceptor的工作原理如下:

    ...

    虽然框架中没有标准拦截器,但有test cases that show how to use them for an initial handshake, for example herehere

    测试比您需要的更复杂,因为它们测试多个嵌套的拦截器。

    第一次打开套接字时,hello world test interceptors 发送 Hello 并期待 World!。它们为客户端和服务器端实现握手。

    【讨论】:

    • hello world 示例为我提供了我需要的确切内容。作为后续工作,我开始按照我的意图进行连接池。我说过使用 CachingClientConnectionFactory,但它不符合我的要求。我需要在不将 singleUse 设置为 true 的情况下启用连接池。
    • 我看到 CachingClientConnectionFactory 的文档,并且我看到“缓存来自底层目标工厂的连接的连接工厂。底层工厂将被重新配置为 singleUse=true 以便将连接返回到使用后缓存。用户不应随后将基础属性设置为 false,否则将导致缓存不足。是否没有其他实现可用于设置始终处于活动状态的连接池,这样我就不会使用刚刚添加的协商拦截器拦截每个连接?
    • single use 不是真的 - 它只是向使用类发出信号以在使用后“关闭”套接字 - 它将它返回到缓存 - 它实际上并没有关闭。缓存的连接本身就是一个拦截器,close() 只是做this.pool.releaseItem(getTheConnection())。另外,它必须是一次性使用的,以便底层工厂在每次请求连接时分发新连接。如果一次性使用是false,则只有一个连接可用。
    • 没错,我不想在使用后关闭套接字。我觉得 CachingClientConnectionFactory 不是我问题的答案。我需要的是有一个保持活动连接池,以便我可以通过 tcp 发送大量数据。我觉得我可以使用“协作出站和入站通道适配器”来实现高吞吐量,而不是使用常规网关和 CachingClientConnectionFactory。 Spring集成有我可以参考的“tcp-client-server-multiplex”项目。你认为我在朝着正确的方向前进吗?
    • 你想要的正是 CCCF 所做的。就试一试吧。套接字不关闭;当通道适配器“关闭”连接时,它会保持打开状态并返回到池中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-24
    相关资源
    最近更新 更多