为什么 Spring 集成故障转移不显示异常
Why Spring Integration failover doesn't show exception
我对 Spring 集成调度程序的故障转移有一些问题,如果我的消息处理程序失败,它应该向我显示异常。
我有简单的 Spring 集成上下文:
<int:gateway default-request-channel="inboundChannel"
service-interface="com.some.gateway.PrinterGateway"/>
<int:channel id="inboundChannel">
<int:dispatcher failover="false"/>
</int:channel>
<!--first Message Handler (broken)-->
<bean id="printService" class="com.some.service.PrinterService"/>
<int:service-activator input-channel="inboundChannel"
method="print"
ref="printService"/>
<!--second Message Handler-->
<bean id="uppercasePrintService"
class="com.some.service.UppercasePrinterService"/>
<int:service-activator input-channel="inboundChannel"
method="printUppercase"
ref="uppercasePrintService"/>
还有我坏掉的消息处理程序class:
public class PrinterService {
public void print(Message<String> message) {
throw new RuntimeException("This is error");
}
}
- 你能解释一下为什么我的故障转移不起作用吗?
- 为什么跳过 RuntimeException 并将消息传递给下一个处理程序?
对我来说效果很好。
不清楚您要实现的目标;或许你对负载均衡有误解?
默认情况下,负载平衡策略是循环的,这意味着第一条消息将转到失败的端点;第二个将到达好的终点。
消息将交替出现。
19:23:16.867 [main] DEBUG org.springframework.integration.channel.DirectChannel - preSend on channel 'org.springframework.integration.channel.DirectChannel@1794d431', message: GenericMessage [payload=foo, headers={id=9c3b1493-0a9a-e324-6da3-262079677ed0, timestamp=1494199396867}]
org.springframework.messaging.MessageDeliveryException: failed to send Message to channel 'null'; nested exception is java.lang.RuntimeException: foo, failedMessage=GenericMessage [payload=foo, headers={id=9c3b1493-0a9a-e324-6da3-262079677ed0, timestamp=1494199396867}]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:449)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:373)
at com.example.So43836561Application.main(So43836561Application.java:16)
Caused by: java.lang.RuntimeException: foo
at com.example.So43836561Application.lambda[=10=](So43836561Application.java:13)
at com.example.So43836561Application$$Lambda/1121454968.handleMessage(Unknown Source)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:160)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:423)
... 2 more
19:23:18.875 [main] DEBUG org.springframework.integration.channel.DirectChannel - preSend on channel 'org.springframework.integration.channel.DirectChannel@1794d431', message: GenericMessage [payload=bar, headers={id=90aaa16c-a8c1-9162-ba8f-532fa3201c7f, timestamp=1494199398875}]
Second Service: GenericMessage [payload=bar, headers={id=90aaa16c-a8c1-9162-ba8f-532fa3201c7f, timestamp=1494199398875}]
19:23:18.876 [main] DEBUG org.springframework.integration.channel.DirectChannel - postSend (sent=true) on channel 'org.springframework.integration.channel.DirectChannel@1794d431', message: GenericMessage [payload=bar, headers={id=90aaa16c-a8c1-9162-ba8f-532fa3201c7f, timestamp=1494199398875}]
如果您使用 NONE 负载平衡策略,所有消息都将转到失败的策略。
19:26:38.005 [main] DEBUG org.springframework.integration.channel.DirectChannel - preSend on channel 'org.springframework.integration.channel.DirectChannel@7d9d1a19', message: GenericMessage [payload=foo, headers={id=6a69efe9-dbbd-c79b-41a9-6964fd4c8ccc, timestamp=1494199598004}]
org.springframework.messaging.MessageDeliveryException: failed to send Message to channel 'null'; nested exception is java.lang.RuntimeException: foo, failedMessage=GenericMessage [payload=foo, headers={id=6a69efe9-dbbd-c79b-41a9-6964fd4c8ccc, timestamp=1494199598004}]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:449)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:373)
at com.example.So43836561Application.main(So43836561Application.java:16)
Caused by: java.lang.RuntimeException: foo
at com.example.So43836561Application.lambda[=11=](So43836561Application.java:13)
at com.example.So43836561Application$$Lambda/2009787198.handleMessage(Unknown Source)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:160)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:423)
... 2 more
19:26:40.009 [main] DEBUG org.springframework.integration.channel.DirectChannel - preSend on channel 'org.springframework.integration.channel.DirectChannel@7d9d1a19', message: GenericMessage [payload=bar, headers={id=9428a10e-3a17-79d5-e4bd-731fc88ef0fe, timestamp=1494199600008}]
Exception in thread "main" org.springframework.messaging.MessageDeliveryException: failed to send Message to channel 'null'; nested exception is java.lang.RuntimeException: foo, failedMessage=GenericMessage [payload=bar, headers={id=9428a10e-3a17-79d5-e4bd-731fc88ef0fe, timestamp=1494199600008}]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:449)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:373)
at com.example.So43836561Application.main(So43836561Application.java:22)
Caused by: java.lang.RuntimeException: foo
at com.example.So43836561Application.lambda[=11=](So43836561Application.java:13)
at com.example.So43836561Application$$Lambda/2009787198.handleMessage(Unknown Source)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:160)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:423)
... 2 more
如果这不是问题,也许您有第二个通道 bean,具有相同的 id 但配置不同?
无论如何,打开 org.springframework.integration
的 DEBUG 日志记录将告诉您发生了什么。
编辑
由于您使用的是异步网关 (returns Future<?>
),因此您需要检查结果以获取异常...
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
List<Future<Message<String>>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Message<String> message = MessageBuilder.withPayload("Some payload that created for message id: " + i)
.build();
log.info("Sending message " + i);
futures.add(gateway.print(message));
}
futures.forEach(f -> {
try {
System.out.println(f.get());
}
catch (ExecutionException e) {
System.out.println(e.getCause().getMessage());
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
和
public String printUppercase(Message<String> message) {
log.info(message.getPayload().toUpperCase());
return message.getPayload().toUpperCase();
}
结果:
This is error
GenericMessage [payload=SOME PAYLOAD THAT CREATED FOR MESSAGE ID: 1, headers={id=229ad2ee-f424-61da-a9bc-a631de9bd5d0, timestamp=1494360966556}]
GenericMessage [payload=SOME PAYLOAD THAT CREATED FOR MESSAGE ID: 2, headers={id=7e2c45c4-2c7b-f3f3-243d-56d9de33375f, timestamp=1494360966556}]
This is error
This is error
This is error
GenericMessage [payload=SOME PAYLOAD THAT CREATED FOR MESSAGE ID: 6, headers={id=79f4ef60-9dea-60f3-3972-a9eefde67ebf, timestamp=1494360966556}]
GenericMessage [payload=SOME PAYLOAD THAT CREATED FOR MESSAGE ID: 7, headers={id=626d1347-e5bd-ec4c-b153-71174cc7f18d, timestamp=1494360966556}]
This is error
我对 Spring 集成调度程序的故障转移有一些问题,如果我的消息处理程序失败,它应该向我显示异常。
我有简单的 Spring 集成上下文:
<int:gateway default-request-channel="inboundChannel"
service-interface="com.some.gateway.PrinterGateway"/>
<int:channel id="inboundChannel">
<int:dispatcher failover="false"/>
</int:channel>
<!--first Message Handler (broken)-->
<bean id="printService" class="com.some.service.PrinterService"/>
<int:service-activator input-channel="inboundChannel"
method="print"
ref="printService"/>
<!--second Message Handler-->
<bean id="uppercasePrintService"
class="com.some.service.UppercasePrinterService"/>
<int:service-activator input-channel="inboundChannel"
method="printUppercase"
ref="uppercasePrintService"/>
还有我坏掉的消息处理程序class:
public class PrinterService {
public void print(Message<String> message) {
throw new RuntimeException("This is error");
}
}
- 你能解释一下为什么我的故障转移不起作用吗?
- 为什么跳过 RuntimeException 并将消息传递给下一个处理程序?
对我来说效果很好。
不清楚您要实现的目标;或许你对负载均衡有误解?
默认情况下,负载平衡策略是循环的,这意味着第一条消息将转到失败的端点;第二个将到达好的终点。 消息将交替出现。
19:23:16.867 [main] DEBUG org.springframework.integration.channel.DirectChannel - preSend on channel 'org.springframework.integration.channel.DirectChannel@1794d431', message: GenericMessage [payload=foo, headers={id=9c3b1493-0a9a-e324-6da3-262079677ed0, timestamp=1494199396867}]
org.springframework.messaging.MessageDeliveryException: failed to send Message to channel 'null'; nested exception is java.lang.RuntimeException: foo, failedMessage=GenericMessage [payload=foo, headers={id=9c3b1493-0a9a-e324-6da3-262079677ed0, timestamp=1494199396867}]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:449)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:373)
at com.example.So43836561Application.main(So43836561Application.java:16)
Caused by: java.lang.RuntimeException: foo
at com.example.So43836561Application.lambda[=10=](So43836561Application.java:13)
at com.example.So43836561Application$$Lambda/1121454968.handleMessage(Unknown Source)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:160)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:423)
... 2 more
19:23:18.875 [main] DEBUG org.springframework.integration.channel.DirectChannel - preSend on channel 'org.springframework.integration.channel.DirectChannel@1794d431', message: GenericMessage [payload=bar, headers={id=90aaa16c-a8c1-9162-ba8f-532fa3201c7f, timestamp=1494199398875}]
Second Service: GenericMessage [payload=bar, headers={id=90aaa16c-a8c1-9162-ba8f-532fa3201c7f, timestamp=1494199398875}]
19:23:18.876 [main] DEBUG org.springframework.integration.channel.DirectChannel - postSend (sent=true) on channel 'org.springframework.integration.channel.DirectChannel@1794d431', message: GenericMessage [payload=bar, headers={id=90aaa16c-a8c1-9162-ba8f-532fa3201c7f, timestamp=1494199398875}]
如果您使用 NONE 负载平衡策略,所有消息都将转到失败的策略。
19:26:38.005 [main] DEBUG org.springframework.integration.channel.DirectChannel - preSend on channel 'org.springframework.integration.channel.DirectChannel@7d9d1a19', message: GenericMessage [payload=foo, headers={id=6a69efe9-dbbd-c79b-41a9-6964fd4c8ccc, timestamp=1494199598004}]
org.springframework.messaging.MessageDeliveryException: failed to send Message to channel 'null'; nested exception is java.lang.RuntimeException: foo, failedMessage=GenericMessage [payload=foo, headers={id=6a69efe9-dbbd-c79b-41a9-6964fd4c8ccc, timestamp=1494199598004}]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:449)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:373)
at com.example.So43836561Application.main(So43836561Application.java:16)
Caused by: java.lang.RuntimeException: foo
at com.example.So43836561Application.lambda[=11=](So43836561Application.java:13)
at com.example.So43836561Application$$Lambda/2009787198.handleMessage(Unknown Source)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:160)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:423)
... 2 more
19:26:40.009 [main] DEBUG org.springframework.integration.channel.DirectChannel - preSend on channel 'org.springframework.integration.channel.DirectChannel@7d9d1a19', message: GenericMessage [payload=bar, headers={id=9428a10e-3a17-79d5-e4bd-731fc88ef0fe, timestamp=1494199600008}]
Exception in thread "main" org.springframework.messaging.MessageDeliveryException: failed to send Message to channel 'null'; nested exception is java.lang.RuntimeException: foo, failedMessage=GenericMessage [payload=bar, headers={id=9428a10e-3a17-79d5-e4bd-731fc88ef0fe, timestamp=1494199600008}]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:449)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:373)
at com.example.So43836561Application.main(So43836561Application.java:22)
Caused by: java.lang.RuntimeException: foo
at com.example.So43836561Application.lambda[=11=](So43836561Application.java:13)
at com.example.So43836561Application$$Lambda/2009787198.handleMessage(Unknown Source)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:160)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:423)
... 2 more
如果这不是问题,也许您有第二个通道 bean,具有相同的 id 但配置不同?
无论如何,打开 org.springframework.integration
的 DEBUG 日志记录将告诉您发生了什么。
编辑
由于您使用的是异步网关 (returns Future<?>
),因此您需要检查结果以获取异常...
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
List<Future<Message<String>>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Message<String> message = MessageBuilder.withPayload("Some payload that created for message id: " + i)
.build();
log.info("Sending message " + i);
futures.add(gateway.print(message));
}
futures.forEach(f -> {
try {
System.out.println(f.get());
}
catch (ExecutionException e) {
System.out.println(e.getCause().getMessage());
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
和
public String printUppercase(Message<String> message) {
log.info(message.getPayload().toUpperCase());
return message.getPayload().toUpperCase();
}
结果:
This is error
GenericMessage [payload=SOME PAYLOAD THAT CREATED FOR MESSAGE ID: 1, headers={id=229ad2ee-f424-61da-a9bc-a631de9bd5d0, timestamp=1494360966556}]
GenericMessage [payload=SOME PAYLOAD THAT CREATED FOR MESSAGE ID: 2, headers={id=7e2c45c4-2c7b-f3f3-243d-56d9de33375f, timestamp=1494360966556}]
This is error
This is error
This is error
GenericMessage [payload=SOME PAYLOAD THAT CREATED FOR MESSAGE ID: 6, headers={id=79f4ef60-9dea-60f3-3972-a9eefde67ebf, timestamp=1494360966556}]
GenericMessage [payload=SOME PAYLOAD THAT CREATED FOR MESSAGE ID: 7, headers={id=626d1347-e5bd-ec4c-b153-71174cc7f18d, timestamp=1494360966556}]
This is error