我想让我的Apache Camel应用程序更具弹性,即使无法访问MQTT代理也可以启动。我们在可能不稳定的互联网连接的物联网设备上使用Camel,我希望我们的应用程序即使没有互联网访问也能启动。
示例性路线如下所示:
from("timer:heartbeat?period=5000")
.routeId("send heartbeat")
.setBody(simple("Hello World!"))
.to("paho:myhostnome/heartbeat?brokerUrl={{broker.url}}")
只要MQTT服务器可用,这就可以正常工作。但是,当服务器无法访问时,上下文会在预热PahoEndpoint时失败。
Caused by: org.apache.camel.FailedToCreateRouteException: Failed to create route send heartbeat: Route(send heartbeat)[[From[timer:heartbeat?period={{heartbe... because of Unable to connect to server
at org.apache.camel.impl.RouteService.warmUp(RouteService.java:147) ~[camel-core-2.19.3.jar:2.19.3]
at org.apache.camel.impl.DefaultCamelContext.doWarmUpRoutes(DefaultCamelContext.java:3758) ~[camel-core-2.19.3.jar:2.19.3]
at org.apache.camel.impl.DefaultCamelContext.safelyStartRouteServices(DefaultCamelContext.java:3665) ~[camel-core-2.19.3.jar:2.19.3]
at org.apache.camel.impl.DefaultCamelContext.doStartOrResumeRoutes(DefaultCamelContext.java:3451) ~[camel-core-2.19.3.jar:2.19.3]
at org.apache.camel.impl.DefaultCamelContext.doStartCamel(DefaultCamelContext.java:3305) ~[camel-core-2.19.3.jar:2.19.3]
at org.apache.camel.impl.DefaultCamelContext.access$000(DefaultCamelContext.java:202) ~[camel-core-2.19.3.jar:2.19.3]
at org.apache.camel.impl.DefaultCamelContext$2.call(DefaultCamelContext.java:3089) ~[camel-core-2.19.3.jar:2.19.3]
at org.apache.camel.impl.DefaultCamelContext$2.call(DefaultCamelContext.java:3085) ~[camel-core-2.19.3.jar:2.19.3]
at org.apache.camel.impl.DefaultCamelContext.doWithDefinedClassLoader(DefaultCamelContext.java:3108) ~[camel-core-2.19.3.jar:2.19.3]
at org.apache.camel.impl.DefaultCamelContext.doStart(DefaultCamelContext.java:3085) ~[camel-core-2.19.3.jar:2.19.3]
at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61) ~[camel-core-2.19.3.jar:2.19.3]
at org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:3022) ~[camel-core-2.19.3.jar:2.19.3]
at org.apache.camel.spring.boot.RoutesCollector.maybeStart(RoutesCollector.java:242) ~[camel-spring-boot-2.19.3.jar:2.19.3]
at org.apache.camel.spring.boot.RoutesCollector.onApplicationEvent(RoutesCollector.java:217) ~[camel-spring-boot-2.19.3.jar:2.19.3]
... 13 common frames omitted
Caused by: org.eclipse.paho.client.mqttv3.MqttException: Unable to connect to server
at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:79) ~[org.eclipse.paho.client.mqttv3-1.1.0.jar:na]
at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:650) ~[org.eclipse.paho.client.mqttv3-1.1.0.jar:na]
at java.lang.Thread.run(Thread.java:745) ~[na:1.8.0_121]
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:1.8.0_121]
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[na:1.8.0_121]
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[na:1.8.0_121]
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[na:1.8.0_121]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[na:1.8.0_121]
at java.net.Socket.connect(Socket.java:589) ~[na:1.8.0_121]
at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:70) ~[org.eclipse.paho.client.mqttv3-1.1.0.jar:na]
我的第一个想法是在涉及Paho的所有路线上禁用自动启动并手动启动它们。即使路径本身未启动,PahoEndpoint也会启动,这不起作用。
我现在正在寻找另一种方法来解决这个问题。
答案 0 :(得分:3)
Apache Camel 2.20以后提供了一项新功能,让启动程序使用主管控制器运行,从<{1}}本身开始接管。这允许设置更高级的配置以让控制器处理错误,并尝试重试启动失败的路由等。
有一个例子可以通过Spring Boot进行配置,但你也可以从Java API配置它:https://github.com/apache/camel/tree/master/examples/camel-example-spring-boot-supervising-route-controller
在即将发布的版本中,我们将改进这项新功能。 对于旧版本的Camel,它通常是可能提供或不提供任何类型的重试机制的组件本身,您需要配置,而不是快速失败。
答案 1 :(得分:1)
Camel有一个try()catch()功能。
为什么不在调用to()之前添加try()并捕获异常然后只记录它?类似的东西:
from("timer:heartbeat?period=5000")
.routeId("send heartbeat")
.setBody(simple("Hello World!"))
.doTry()
.to("paho:myhostnome/heartbeat?brokerUrl={{broker.url}}")
.doCatch( java.net.ConnectException.class).log("failed")
.end()