基于spring集成的tcp服务器运行良好。
如果服务需要很长时间,它还处理服务器上的回复超时。当服务的时间长于在中设置的回复超时时,它会将消息发送到错误通道,而该通道又会将错误消息发送回客户机。
这是我的代码:
<int:transformer id="errorHandler"
input-channel="errorChannel"
ref="myTransformer" method="transform" />
<bean id="myTransformer" class="com.sample.MyTransformer" />
public class MyTransformer {
private static Logger logger = Logger.getLogger(MyTransformer.class);
public String transform(org.springframework.integration.handler.ReplyRequiredException e) {
logger.error("timeout exception is thrown");
return "Error in processing request.";
}
}
上面的代码工作正常,客户端得到“处理请求时出错”,服务器日志中有“超时异常被抛出”条目。但我在日志中也看到了以下异常:
2016-06-30 16:25:27,827 ERROR [org.springframework.integration.handler.LoggingHandler] org.springframework.integration.handler.ReplyRequiredException: No reply produced by handler 'org.springframework.integration.config.ServiceActivatorFactoryBean#0', and its 'requiresReply' property is set to true.
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:109)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:147)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:120)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:442)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:150)
at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:45)
at org.springframework.messaging.core.AbstractMessagingTemplate.sendAndReceive(AbstractMessagingTemplate.java:42)
at org.springframework.integration.core.MessagingTemplate.sendAndReceive(MessagingTemplate.java:97)
at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:422)
at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceiveMessage(MessagingGatewaySupport.java:390)
at org.springframework.integration.ip.tcp.TcpInboundGateway.doOnMessage(TcpInboundGateway.java:119)
at org.springframework.integration.ip.tcp.TcpInboundGateway.onMessage(TcpInboundGateway.java:97)
at org.springframework.integration.ip.tcp.connection.TcpNetConnection.run(TcpNetConnection.java:182)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
MyTransformer的实现似乎不正确。
你能帮我定制变压器吗?
如何在Transform方法中获取有效负载,以便我可以在处理请求时作为“错误”回复客户机。有效载荷='+有效载荷?
谢谢
更新:为了避免记录replyrequiredexception,我更改了TCP入站网关上的错误通道,如下所示:
<int-ip:tcp-inbound-gateway id="gatewayCrLf"
connection-factory="crLfServer"
request-channel="requestChannel"
error-channel="tcpErrorChannel"
reply-timeout="10000"
/>
<int:channel id="tcpErrorChannel" />
<int:service-activator input-channel="requestChannel" ref="gateway" requires-reply="true"/>
<int:gateway id="gateway" default-request-channel="timeoutChannel" default-reply-timeout="10000" />
<int:object-to-string-transformer id="serverBytes2String"
input-channel="timeoutChannel"
output-channel="serviceChannel"/>
<int:channel id="timeoutChannel">
<int:dispatcher task-executor="timeoutExecutor"/>
</int:channel>
<bean id="timeoutExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="100" />
<property name="queueCapacity" value="50" />
</bean>
但我收到了MessageDeliveryException。tcperrorchannel设置似乎错误。你能建议一下吗?这是StackTrace:
2016-07-05 12:17:34,266 ERROR [org.springframework.integration.ip.tcp.connection.TcpNetConnection] Exception sending message: GenericMessage [payload=byte[67], headers={timestamp=1467735444239, id=30eb099e-955d-1bd3-1789-49aa9fc84b6f, ip_tcp_remotePort=64055, ip_address=127.0.0.1, ip_localInetAddress=/127.0.0.1, ip_hostname=127.0.0.1, ip_connectionId=127.0.0.1:64055:5678:908d39a1-d027-4753-b144-59b9c0390fd7}]
org.springframework.messaging.MessagingException: failure occurred in error-handling flow; nested exception is org.springframework.messaging.MessageDeliveryException: Dispatcher has no subscribers for channel 'org.springframework.context.support.FileSystemXmlApplicationContext@4876db09.tcpErrorChannel'.; nested exception is org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:452)
at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceiveMessage(MessagingGatewaySupport.java:390)
at org.springframework.integration.ip.tcp.TcpInboundGateway.doOnMessage(TcpInboundGateway.java:119)
at org.springframework.integration.ip.tcp.TcpInboundGateway.onMessage(TcpInboundGateway.java:97)
at org.springframework.integration.ip.tcp.connection.TcpNetConnection.run(TcpNetConnection.java:182)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Caused by: org.springframework.messaging.MessageDeliveryException: Dispatcher has no subscribers for channel 'org.springframework.context.support.FileSystemXmlApplicationContext@4876db09.tcpErrorChannel'.; nested exception is org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:81)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:442)
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115)
at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:150)
at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:45)
at org.springframework.messaging.core.AbstractMessagingTemplate.sendAndReceive(AbstractMessagingTemplate.java:42)
at org.springframework.integration.core.MessagingTemplate.sendAndReceive(MessagingTemplate.java:97)
at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:449)
... 7 more
Caused by: org.springframework.integration.MessageDispatchingException: Dispatcher has no subscribers
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:153)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:120)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
... 14 more
通过将ErrorChennel更改为TcperrorChannel,上述异常将消失:
非常感谢阿耳特姆的完美解决方案。
最佳答案
看起来这是你另一个问题的继续。
嗯,ReplyRequiredException
是<int:service-activator input-channel="requestChannel" ref="gateway" requires-reply="true"/>
的结果。requires-reply="true"
-请阅读其说明。不过,您可以使用它并将其设为false
(默认值),但是“超时”的逻辑将不起作用。所以,除非继续生活下去,否则你别无选择:
ERROR [org.springframework.integration.handler.LoggingHandler] org.springframework.integration.handler.ReplyRequiredException
不过,这只是默认的订阅服务器之一的影响。
关于你最后一个问题。所有异常都被包装到
errorChannel
中并发送到该ErrorMessage
中。通常情况下,异常被包装到errorChannel
中,例如,在这种情况下,它类似于:else if (this.requiresReply && !isAsync()) {
throw new ReplyRequiredException(message, "No reply produced by handler '" +
getComponentName() + "', and its 'requiresReply' property is set to true.");
}
请注意
MessagingException
ctor参数在我们的场景中是一个没有应答的message
参数。您可以从中提取所需的requestMessage
。因此,现在您可以从
payload
中的failedMessage
获取ReplyRequiredException
,并提取其transform()
以实现您的目标。更新
由于此
payload
是已知的异常,因此不需要将其视为错误。好吧,即使它是一个已知的异常,但它在其他组件和场景中是一个重要的异常,当它可能不合适时,不要接收回复。
ReplyRequiredException
在框架组件中非常常见,因此将它移到不同的类别对于您的应用程序来说可能是一个很大的架构错误。为了避免这些日志,您不应该使用默认的
ReplyRequiredException
,而应该使用来自TCP入站网关的其他日志。就这样。默认的errorChannel
仍将拥有error-channel="tcpErrorChannel"
作为订户,但您已经不会向该频道发送错误消息。