Camel:检测到jdbc连接丢失时停止路由

时间:2013-07-17 16:28:49

标签: java tcp error-handling routing apache-camel

我的应用程序有以下路径:

from("netty:tcp://localhost:5150?sync=false&keepAlive=true")
.routeId("tcp.input")
.transform()
.simple("insert into tamponems (AVIS) values (\"${in.body}\");")
.to("jdbc:mydb");

此路线每59毫秒接收一条新消息。我想在与数据库的连接丢失时停止路由在第二条消息到达之前 。主要是,我想永远不会丢失消息

我继续这样做:

我添加了errorHandler

errorHandler(deadLetterChannel("direct:backup")
.redeliveryDelay(5L)
.maximumRedeliveries(1)
.retryAttemptedLogLevel(LoggingLevel.WARN)
.logExhausted(false));

我的errorHandler尝试重新发送邮件,如果再次失败,则会将邮件重定向到deadLetterChannel

以下deadLetterChannel将停止tcp.input路由,并尝试将邮件重新发送到数据库:

RoutePolicy policy = new StopRoutePolicy();
from("direct:backup")
.routePolicy(policy)
.errorHandler(
  defaultErrorHandler()
  .redeliveryDelay(1000L)
  .maximumRedeliveries(-1)
  .retryAttemptedLogLevel(LoggingLevel.ERROR)
)
.to("jdbc:mydb");

以下是routePolicy的代码:

public class StopRoutePolicy extends RoutePolicySupport {

  private static final Logger LOG = LoggerFactory.getLogger(String.class);

  @Override
  public void onExchangeDone(Route route, Exchange exchange) {
    String stop = "tcp.input";
    CamelContext context = exchange.getContext();
    if (context.getRouteStatus(stop) != null && context.getRouteStatus(stop).isStarted()) {
      try {
        exchange.getContext().getInflightRepository().remove(exchange);
        LOG.info("STOP ROUTE: {}", stop);
        context.stopRoute(stop);
      } catch (Exception e) {
        getExceptionHandler().handleException(e);
      }
    }
  }

}

我对这种方法的问题是:

  • 在我的"direct:backup"路线中,如果我将maximumRedeliveries设置为-1,则路线tcp.input将永不停止
  • 我在停止期间丢失了消息
  • 这种检测连接丢失和停止路由的方法太长

请问,是否有人想知道加快速度,或者为了不会丢失消息而做出不同的建议?

1 个答案:

答案 0 :(得分:3)

我终于找到了解决问题的方法。为了加快应用程序的速度,我在seda中添加了异步进程多线程

from("netty:tcp://localhost:5150?sync=false&keepAlive=true").to("seda:break");


from("seda:break").threads(5)
.routeId("tcp.input")
.transform()
.simple("insert into tamponems (AVIS) values (\"${in.body}\");")
.to("jdbc:mydb");

我对备份路线做了同样的事情。

from("seda:backup")
.routePolicy(policy)
.errorHandler(
  defaultErrorHandler()
  .redeliveryDelay(1000L)
  .maximumRedeliveries(-1)
  .retryAttemptedLogLevel(LoggingLevel.ERROR)
).threads(2).to("jdbc:mydb");

我修改了routePolicy:

public class StopRoutePolicy extends RoutePolicySupport {

  private static final Logger LOG = LoggerFactory.getLogger(String.class);

  @Override
  public void onExchangeBegin(Route route, Exchange exchange) {
    String stop = "tcp.input";
    CamelContext context = exchange.getContext();
    if (context.getRouteStatus(stop) != null && context.getRouteStatus(stop).isStarted()) {
      try {
        exchange.getContext().getInflightRepository().remove(exchange);
        LOG.info("STOP ROUTE: {}", stop);
        context.stopRoute(stop);
      } catch (Exception e) {
        getExceptionHandler().handleException(e);
      }
    }
  }

  @Override
  public void onExchangeDone(Route route, Exchange exchange) {
    String stop = "tcp.input";
    CamelContext context = exchange.getContext();
    if (context.getRouteStatus(stop) != null && context.getRouteStatus(stop).isStopped()) {
      try {
        LOG.info("RESTART ROUTE: {}", stop);
        context.startRoute(stop);
      } catch (Exception e) {
        getExceptionHandler().handleException(e);
      }
    }
  }
}

通过这些更新,TCP路由在处理备份路由之前停止。当jdbc连接回来时,路由重新启动

现在,感谢Camel,应用程序能够处理数据库故障而不会丢失消息,也无需人工干预。

我希望这可以帮到你。