【问题标题】:How to catch a seda queue full exception in Camel?如何在 Camel 中捕获 seda 队列完整异常?
【发布时间】:2014-02-07 20:14:28
【问题描述】:

我正在使用 Camel 读取 JMS 队列并放置在 SEDA 队列中,然后通过单独的路由读取并进行处理。有时,如果我的应用程序出现问题,我的 SEDA 队列会填满,我会得到:

java.lang.IllegalStateException: Queue full

这是有道理的。我想捕获这个异常,所以我可以停止订阅 JMS 的路由(阻止更多消息进入),但我似乎无法捕获它。

这是我的路线(简化):

from("{{jms.loader.in}}") 
.setExchangePattern(ExchangePattern.InOnly)
.routeId(this.getClass().getSimpleName())
.to("seda://JmsFetchRoute_incoming);

我试图将它包围在一个 doTry - doCatch 中,但没有捕获到异常:

from("{{jms.loader.in}}") 
.setExchangePattern(ExchangePattern.InOnly)
.routeId(this.getClass().getSimpleName())
.doTry()
    .to("seda://JmsFetchRoute_incoming)
.doCatch(Exception.class)
    .log(LoggingLevel.ERROR, "Your queue is full!")
.end();

似乎无论我在“doCatch”块中尝试做什么,它都不会达到这一点。那么如何将“调用”包装到 SEDA 队列,以便捕获 Queue Full 异常?

EDIT1

根据 hveiga 的回答,我还尝试使用“onException”创建一个 ErrorHandlingRoute 并将其添加到我的上下文中,但这也没有成功:

@Override
public void configure() throws Exception {
    onException(IllegalStateException.class)
        .handled(true)
        .log(LoggingLevel.ERROR, "Exception route stopping topic route, SEDA queue full")
        .to("controlbus:route?routeId=JmsFetchRoute&action=stop")
    .end();
}

我也将它添加到我的 fetch 路线中,但仍然没有拿起它:

from("{{jms.loader.in}}") 
.setExchangePattern(ExchangePattern.InOnly)
.routeId(this.getClass().getSimpleName())
    .onException(IllegalStateException.class)
      .handled(true)
      .log(LoggingLevel.ERROR, "Topic consumer stopping route, SEDA queue full : " + this.getClass().getSimpleName())
      .to("controlbus:route?routeId="+this.getClass().getSimpleName()+"&action=stop")
    .end()
.to("seda://JmsFetchRoute_incoming);

EDIT2

根据this post onException 不能在单独的RouteBuilder中定义...

EDIT3

仍然没有运气从同一个路由构建器中捕获异常,所以我给了我的“onException”路由一个名称,但是当在 JMX 中检查时这个名称不在 Camel 的“路由”部分中?我需要打开配置以启用“onException”路由吗?

【问题讨论】:

    标签: java apache-camel


    【解决方案1】:

    我认为您正在寻找onException()。 Camel 的这个特性将捕获您指定类型的任何异常,并让您以您喜欢的方式处理它。您似乎想捕获该异常并使用控制总线组件停止路由。

    应该是这样的:

    onException(IllegalStateException.class).
    handled(true).
    to("controlbus:route?routeId=yourRouteId&action=stop");
    

    欲了解更多信息,请查看:

    【讨论】:

    • 感谢 hveiga,这看起来很有希望。我曾假设 onException 与 doTry...doCatch 的工作方式相同,但似乎因为它适用于整个骆驼上下文(在全局范围内),所以无论它们在哪里抛出,它都应该拾取错误。我稍后会进行测试,并让您知道这是否解决了我的问题。我没有看到 controlbus 组件(看起来像是新的) - 非常好!
    • iirc,onException 可以应用于整个骆驼上下文,也可以在路由中定义以应用于该路由的其余部分。 Controlbus 是 2.12 中的新功能。在此之前,您可以通过 CamelContext 对 bean 执行相同的操作。
    • 它没有用:(我创建了一个新路由'ErrorHandlingRoute',上面基本上有你的代码,加上一些日志记录),将它添加到我的camelcontext(显然它必须是添加的第一条路由在任何其他人之前),但异常仍然作为具有完整堆栈跟踪的运行时异常出现在日志中,并且我的异常中的日志消息没有打印出来......有什么建议吗?我还将它添加到我的路线中(所以我有一条路线和一条全球路线,但他们都没有选择)
    【解决方案2】:

    这似乎已在 2.13.0 中修复。我找不到错误报告,但我在 2.12.3 中看到了与 hveiga 相同的问题。在 2.13.0 中,onException 和 doTry/doCatch 可用于处理队列已满错误。

    【讨论】:

    • 我记得调试过这个问题,并最终解决了它(抱歉,我才意识到我从来没有在这里发过帖子)。队列已满实际上从未抛出异常 - 它打印堆栈跟踪,这使它看起来像是抛出异常,但此异常永远不会传播回骆驼(因此,永远不会被 onException 代码捕获)。最终,我只是在一个计时器上编写了自己的单独路由,该计时器根据我设置的“最大队列大小”属性检查队列的大小
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-11
    • 1970-01-01
    相关资源
    最近更新 更多