在春季集成中处理低级套接字错误的最佳做法? [英] Best practice for handling low-level socket error in spring integration?

查看:253
本文介绍了在春季集成中处理低级套接字错误的最佳做法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



假设我有一个动态配置的tcp-ip连接工厂:

 < int-ip:tcp-connection-factory id =chatRoomTcpIpClientFactory
type =client
主机=$ {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错误24479 --- [nio-8080- exec-1] osiip.tcp.TcpSendingMessageHandler:创建连接时出错
java.net.ConnectException:拒绝连接

假设我的业务逻辑在很大程度上依赖于tcp-ip连接,并且程序想要对这个特定的套接字连接错误进行一些错误处理。 (例如,将错误写入redis缓存,使用另一个ip /端口重新连接等等)



我已经寻找解决方案,现在我知道errorChannel在这样的低级异常时不被触发。 tcp-connection-event-inbound-channel-adapter也是一样的。



经过一些搜索,似乎在工厂bean或TcpConnectionInterceptorSupport中的advice chainFactory是要走的路...但我还是很困惑。 tcp连接失败非常常见。有没有更简单的方法处理连接异常?






编辑:我深入了源代码,现在我添加了一个试试我的方法。它现在工作了对于tcp-connection-event-inbound-channel-adapter来说,它仍然不起作用。似乎套接字创建异常未发布...



当服务尝试通过套接字发送消息时,TcpSendingMessageHandler接收到异常...






编辑2:
跟踪堆栈跟踪:

  2015-08-14 10:31:53.694错误2531 --- [nio-8080-exec-1] osiip.tcp.TcpSendingMessageHandler:创建连接时出错

java.net.ConnectException:连接拒绝
在java.net.PlainSocketImpl.socketConnect(本机方法)
在java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345)
在java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
在java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
在java.net.SocksSocketImpl.connect(SocksSocketImpl.java :392)
在java.net.Socket.connect(Socket.java:589)
在java.net.Socket.connect(Socket.java:538)
在java.net。 。插座< init>(Socket.java:434)
在java.net.Socket。< init>(Socket.java:211)
在javax.net.DefaultSocketFactory.createSocket(SocketFactory.java:271)
在org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory.createSocket(TcpNetClientConnectionFactory.java:76)
在org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory.buildNewConnection(TcpNetClientConnectionFactory。 java:49)
在org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory.obtainNewConnection(AbstractClientConnectionFactory.java:114)
在org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory。 getConnection(AbstractClientConnectionFactory.java:77)
在org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory.getConnection(AbstractClientConnectionFactory.java:67)
在org.springframework.integration.ip.tcp。 connection.AbstractClientConnectionFactory.getConnection(AbstractC lientConnectionFactory.java:31)
在org.springframework.integration.ip.tcp.TcpSendingMessageHandler.obtainConnection(TcpSendingMessageHandler.java:72)
在org.springframework.integration.ip.tcp.TcpSendingMessageHandler.doWrite( TcpSendingMessageHandler.java:144)
在org.springframework.integration.ip.tcp.TcpSendingMessageHandler.handleMessageInternal(TcpSendingMessageHandler.java:120)
在org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler。 java:78)
在org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
在org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:101)
在org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
在org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
在org.springf ramework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:287)
在org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:245)
at(我的服务调用)

这里,在TcpNetClientConnectionFactory.buildNewConnecton()中,



它写为:

  protected TcpConnectionSupport buildNewConnection()throws IOException,SocketException,Exception {
Socket socket = createSocket(this.getHost(),this.getPort()); //< ---其中异常抛出
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();
返回连接;
}

因此,TcpConnectionSupport甚至没有达到。事件驱动的适配器无法处理套接字创建期间发生的异常。这就是为什么我一直在努力解决这个问题。



在TcpSendingMessageHandler中,

  protected TcpConnection getsConnection(Message<?> message){
TcpConnection connection = null;
Assert.notNull(this.clientConnectionFactory,'clientConnectionFactory'不能为null);
try {
connection = this.clientConnectionFactory.getConnection();
}
catch(异常e){
logger.error(创建连接时出错,e);
抛出新的MessageHandlingException(消息,无法获取连接,e);
}
返回连接;
}

这里只是记录错误,并再次抛出一个新的异常。 p>

解决方案

请查看 TcpConnectionEvent 层次结构,特别是 TcpConnectionExceptionEvent 。并调查由 TcpConnection 实现发出的地方。



请查看有关此事的更多信息参考手册


Hi I'm here again asking for spring integration's tcp-ip related question.

Suppose I have a dynamically configured tcp-ip connection factory:

<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}"/>

Here, the host & port are both unknown at the beginning. Sometimes the program cannot grantee that the host & port are valid. Say there is an ip/port 8.8.8.8:12345 which is not open on the destination server. Now the spring framework throws:

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

Suppose that my business logic relies heavily on the tcp-ip connection and the program wants to do some error-handling to this specific socket connection error. (e.g. write the error to redis cache, re-connect using another ip/port, etc...)

I've looked for solutions and now I know that the "errorChannel" is not triggered on such low-level exception. The same applies to the tcp-connection-event-inbound-channel-adapter.

After some googling, it seems that the "advice" inside the factory bean or TcpConnectionInterceptorSupport with the chainFactory is the way to go... But I'm still rather confused. It's very common for the tcp-connection to fail. Is there any simpler method to handle connection exceptions?


Edit: I delved into the source code, and now I added a try-catch around my method. It works now. As for the tcp-connection-event-inbound-channel-adapter, it still does not work. It seems that the socket creation exception is not published...

The exception is picked up by TcpSendingMessageHandler when the service tries to send a message through the socket...


Edit 2: Following the stack trace:

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)

Here, in TcpNetClientConnectionFactory.buildNewConnecton(),

it is written as:

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

Hence, the TcpConnectionSupport is not even reached. The event-driven adapter cannot deal with the exception occurred during socket creation. This is why I struggled so long for an answer.

In 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;
}

Here the error is simply logged and a new exception is thrown again.

解决方案

Please, take a look to the TcpConnectionEvent hierarchy, especially TcpConnectionExceptionEvent. And investigate the places where it is emitted by the TcpConnection implementations.

Please, find more information on the matter in the Reference Manual.

这篇关于在春季集成中处理低级套接字错误的最佳做法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆