【发布时间】:2015-08-13 15:41:52
【问题描述】:
您好,我又来这里询问 spring integration 的 tcp-ip 相关问题了。
假设我有一个动态配置的 tcp-ip 连接工厂:
<int-ip:tcp-connection-factory id="chatRoomTcpIpClientFactory"
type="client"
host="${host}"
port="${port}"
single-use="false"
using-nio="false"
so-keep-alive="false"
so-timeout="${timeout}"
serializer="${seri-deseri}"
deserializer="${seri-deseri}"/>
在这里,主机和端口一开始都是未知的。有时程序不能保证主机和端口是有效的。假设有一个 ip/port 8.8.8.8:12345 在目标服务器上未打开。现在spring框架抛出:
2015-08-13 22:07:52.906 ERROR 24479 --- [nio-8080-exec-1] o.s.i.ip.tcp.TcpSendingMessageHandler : Error creating connection
java.net.ConnectException: Connection refused
假设我的业务逻辑严重依赖于 tcp-ip 连接,并且程序想要对这个特定的套接字连接错误进行一些错误处理。 (例如,将错误写入 redis 缓存,使用另一个 ip/port 重新连接等...)
我已经寻找解决方案,现在我知道“errorChannel”不会在这种低级异常上触发。这同样适用于 tcp-connection-event-inbound-channel-adapter。
经过一番谷歌搜索,似乎工厂 bean 中的“建议”或带有 chainFactory 的 TcpConnectionInterceptorSupport 是要走的路……但我还是很困惑。 tcp 连接失败是很常见的。有没有更简单的方法来处理连接异常?
编辑:我深入研究了源代码,现在我在我的方法周围添加了一个 try-catch。现在可以了。至于 tcp-connection-event-inbound-channel-adapter,还是不行。好像没有发布socket创建异常...
当服务尝试通过套接字发送消息时,该异常被 TcpSendingMessageHandler 拾取...
编辑 2: 跟踪堆栈跟踪:
2015-08-14 10:31:53.694 ERROR 2531 --- [nio-8080-exec-1] o.s.i.ip.tcp.TcpSendingMessageHandler : Error creating connection
java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at java.net.Socket.connect(Socket.java:538)
at java.net.Socket.<init>(Socket.java:434)
at java.net.Socket.<init>(Socket.java:211)
at javax.net.DefaultSocketFactory.createSocket(SocketFactory.java:271)
at org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory.createSocket(TcpNetClientConnectionFactory.java:76)
at org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory.buildNewConnection(TcpNetClientConnectionFactory.java:49)
at org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory.obtainNewConnection(AbstractClientConnectionFactory.java:114)
at org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory.obtainConnection(AbstractClientConnectionFactory.java:77)
at org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory.getConnection(AbstractClientConnectionFactory.java:67)
at org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory.getConnection(AbstractClientConnectionFactory.java:31)
at org.springframework.integration.ip.tcp.TcpSendingMessageHandler.obtainConnection(TcpSendingMessageHandler.java:72)
at org.springframework.integration.ip.tcp.TcpSendingMessageHandler.doWrite(TcpSendingMessageHandler.java:144)
at org.springframework.integration.ip.tcp.TcpSendingMessageHandler.handleMessageInternal(TcpSendingMessageHandler.java:120)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:287)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:245)
at (My service call)
这里,在 TcpNetClientConnectionFactory.buildNewConnecton() 中,
写成:
protected TcpConnectionSupport buildNewConnection() throws IOException, SocketException, Exception {
Socket socket = createSocket(this.getHost(), this.getPort()); //<--- Where exception is thrown
setSocketAttributes(socket);
TcpConnectionSupport connection = new TcpNetConnection(socket, false, this.isLookupHost(),
this.getApplicationEventPublisher(), this.getComponentName());
connection = wrapConnection(connection);
initializeConnection(connection, socket);
this.getTaskExecutor().execute(connection);
this.harvestClosedConnections();
return connection;
}
因此,甚至没有达到 TcpConnectionSupport。事件驱动适配器无法处理套接字创建期间发生的异常。这就是为什么我苦苦寻找答案的原因。
在 TcpSendingMessageHandler 中,
protected TcpConnection obtainConnection(Message<?> message) {
TcpConnection connection = null;
Assert.notNull(this.clientConnectionFactory, "'clientConnectionFactory' cannot be null");
try {
connection = this.clientConnectionFactory.getConnection();
}
catch (Exception e) {
logger.error("Error creating connection", e);
throw new MessageHandlingException(message, "Failed to obtain a connection", e);
}
return connection;
}
这里只是简单地记录了错误并再次抛出一个新的异常。
【问题讨论】:
标签: spring exception-handling spring-integration tcp-ip socketexception