【问题标题】:'Write-Only' over a TCP connection with Spring Integration通过带有 Spring Integration 的 TCP 连接“只写”
【发布时间】:2013-09-24 06:16:48
【问题描述】:

我正在使用int-ip:tcp-connection-factoryint-ip:tcp-outbound-gateway 与外部服务器通信。服务器提供的大多数服务的协议都遵循标准的请求-响应样式……效果很好。但是,在某些情况下,我只需要发送一个请求,而无需响应。

我的问题是,如何配置我的频道和连接,以便我可以指定是否等待响应?目前我找不到方法,即使我不期待响应,Spring 也会在发送请求后阻塞。

编辑: 正如建议的那样,我使用了tcp-outbound-channel-adapter。我的配置文件只有以下内容:

<int:channel id="requestChannel" />

<int-ip:tcp-outbound-channel-adapter
    channel="requestChannel" connection-factory="client" />

<int-ip:tcp-connection-factory id="client"
    type="client" host="smtp.gmail.com" port="587" single-use="false"
    so-timeout="10000" />

这是我的主要课程:

public final class Main {

    private static final Logger LOGGER = Logger.getLogger(Main.class);

    public static void main(final String... args) throws IOException {
        LOGGER.debug("entered main()...");

        final AbstractApplicationContext context = new ClassPathXmlApplicationContext(
                "classpath:*-context.xml");

        MessageChannel requestChannel = context.getBean("requestChannel", MessageChannel.class);
        requestChannel.send(MessageBuilder.withPayload("QUIT").build());

        LOGGER.debug("exiting main()...");
    }

}

最后这是我在日志中得到的:

11:57:15.877 INFO  [main][com.together.email.Main] entered main()...
11:57:16.295 INFO  [main][org.springframework.integration.config.xml.DefaultConfiguringBeanFactoryPostProcessor] No bean named 'errorChannel' has been explicitly defined. Therefore, a default PublishSubscribeChannel will be created.
11:57:16.295 INFO  [main][org.springframework.integration.config.xml.DefaultConfiguringBeanFactoryPostProcessor] No bean named 'taskScheduler' has been explicitly defined. Therefore, a default ThreadPoolTaskScheduler will be created.
11:57:16.480 INFO  [main][org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory] started client
11:57:16.480 INFO  [main][org.springframework.integration.endpoint.EventDrivenConsumer] Adding {ip:tcp-outbound-channel-adapter} as a subscriber to the 'requestChannel' channel
11:57:16.480 INFO  [main][org.springframework.integration.channel.DirectChannel] Channel 'requestChannel' has 1 subscriber(s).
11:57:16.480 INFO  [main][org.springframework.integration.endpoint.EventDrivenConsumer] started org.springframework.integration.config.ConsumerEndpointFactoryBean#0
11:57:16.480 INFO  [main][org.springframework.integration.endpoint.EventDrivenConsumer] Adding {logging-channel-adapter:_org.springframework.integration.errorLogger} as a subscriber to the 'errorChannel' channel
11:57:16.481 INFO  [main][org.springframework.integration.channel.PublishSubscribeChannel] Channel 'errorChannel' has 1 subscriber(s).
11:57:16.481 INFO  [main][org.springframework.integration.endpoint.EventDrivenConsumer] started _org.springframework.integration.errorLogger
11:57:16.509 DEBUG [main][org.springframework.integration.channel.DirectChannel] preSend on channel 'requestChannel', message: [Payload=QUIT][Headers={timestamp=1381021036509, id=860ebe82-06c6-4393-95c7-0ece1a0a0e5d}]
11:57:16.509 DEBUG [main][org.springframework.integration.ip.tcp.TcpSendingMessageHandler] org.springframework.integration.ip.tcp.TcpSendingMessageHandler#0 received message: [Payload=QUIT][Headers={timestamp=1381021036509, id=860ebe82-06c6-4393-95c7-0ece1a0a0e5d}]
11:57:16.509 DEBUG [main][org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory] Opening new socket connection to smtp.gmail.com:587
11:57:16.745 DEBUG [main][org.springframework.integration.ip.tcp.connection.TcpNetConnection] New connection smtp.gmail.com:587:550c9b68-10a0-442d-b65d-d25d28df306b
11:57:16.748 DEBUG [main][org.springframework.integration.ip.tcp.TcpSendingMessageHandler] Got Connection smtp.gmail.com:587:550c9b68-10a0-442d-b65d-d25d28df306b
11:57:16.749 DEBUG [pool-1-thread-1][org.springframework.integration.ip.tcp.connection.TcpNetConnection] TcpListener exiting - no listener and not single use
11:57:16.750 DEBUG [main][org.springframework.integration.ip.tcp.connection.TcpNetConnection] Message sent [Payload=QUIT][Headers={timestamp=1381021036509, id=860ebe82-06c6-4393-95c7-0ece1a0a0e5d}]
11:57:16.750 DEBUG [main][org.springframework.integration.channel.DirectChannel] postSend (sent=true) on channel 'requestChannel', message: [Payload=QUIT][Headers={timestamp=1381021036509, id=860ebe82-06c6-4393-95c7-0ece1a0a0e5d}]
11:57:16.751 INFO  [main][com.together.email.Main] exiting main()...

我已将 Spring 的日志记录设置为调试级别,以便为您提供更多详细信息。从日志的最后一行可以看出,我的 main 退出了。然而,不幸的是,应用程序并没有因为[pool-1-thread-1] 继续运行而终止。只要在requestChannel 上调用send,这个线程就会出现。知道这里发生了什么吗?

[在本例中,我将在应用程序连接到 Google 后立即发送 SMTP QUIT 消息。在实践中,我实际上不会从 QUIT 开始。例如,一开始我可能会从 HELO 消息开始。我尝试使用tcp-inbound-channel-adapter 来获取消息响应,效果很好。问题在于我不希望回复的消息。]

【问题讨论】:

  • 在那些“单向”案例中使用&lt;tcp-outbound-channel-adapter&gt; 有什么问题?并在发送命令前添加&lt;router&gt;
  • 您的意思是&lt;tcp-outbound-channel-adapter&gt; 是TCP 只写适配器吗?我已经尝试过了,它在发送数据后仍然处于读取模式。我错过了什么吗?
  • 请分享您的配置,并指出您观察到阻塞的位置
  • 我已按照建议在问题中提供了更多详细信息

标签: spring spring-integration


【解决方案1】:

所以,我建议你向&lt;int-ip:tcp-connection-factory&gt; 注入一些“假”task-executor

public class NullExecutor implements Executor {

    public void execute(Runnable command) {}
}

在这种情况下,您来自 AbstractClientConnectionFactory#obtainConnection() 的连接不会被配置(运行)以从套接字读取。

但是,System.exit(0); 作为 ma​​in 的最后一行就足够了。在这种情况下,所有线程都将被终止,如果它们不是守护进程的话。

【讨论】:

  • 感谢 Artem 的解决方案。这实际上解决了问题。然而,在我的实际应用程序中,我无法执行 System.exit(0),因为它将是一个 Web 应用程序,并且每次需要时都必须实例化新的 SMTP 会话。因此,流程就像连接 --> 发送 HELO --> 发送其他协议命令 --> 发送 QUIT --> 为每个会话断开连接。我的粗略猜测,我将不得不使用 auto-startup="false" 然后按需启动/停止适配器。如果您觉得这行不通,或者您可以分享更好的方法,我们将不胜感激。
猜你喜欢
  • 1970-01-01
  • 2016-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多