Apache Camel遇异常后停止轮询,如何配置使其继续处理下一个Exchange?
Apache Camel 异常后继续处理配置方案
核心思路
要解决单个数据库连接失败导致整个路由轮询阻塞、无法处理其他正常数据库消息的问题,关键是让Camel在捕获异常后不终止路由流程,继续处理下一条Exchange,同时隔离单个端点的异常影响。
具体配置方案
1. 全局/路由级异常捕获(推荐)
通过onException定义针对SQLException的处理规则,启用continued(true)确保异常后继续处理后续消息:
// 可定义在路由类的configure()方法开头(全局生效),或绑定到当前路由 onException(SQLException.class) .log("数据库写入失败,实体名称: ${body.name},错误详情: ${exception.message}") .handled(true) // 标记异常已处理,避免向上传播触发消费者重试 .continued(true); // 核心配置:让路由继续处理下一个Exchange // 原路由逻辑 var route = from("jpa://Data") .choice(); for (var dbConnection : dbConnections) { String name = dbConnection.getName(); route = route.when(simple("${body.name} == '" + name + "' ")) .to("jpa://Data" + name) .endChoice(); } route.otherwise() .process(ex -> { logger.info("Data.name={} not found in dbConnections", ex.getIn().getBody(Data.class).getName()); }) .endChoice() .end();
2. 单个端点异常隔离(更精细控制)
如果需要针对每个数据库端点单独处理异常,可使用doTry/doCatch包裹目标端点,确保单个端点的异常不会扩散到整个路由:
var route = from("jpa://Data") .choice(); for (var dbConnection : dbConnections) { String name = dbConnection.getName(); route = route.when(simple("${body.name} == '" + name + "' ")) .doTry() .to("jpa://Data" + name) .doCatch(SQLException.class) .log("写入数据库[" + name + "]失败,实体信息: ${body}") .handled(true) // 终止当前异常流程,不影响后续消息 .endDoTry() .endChoice(); } route.otherwise() .process(ex -> { logger.info("Data.name={} not found in dbConnections", ex.getIn().getBody(Data.class).getName()); }) .endChoice() .end();
关键配置说明
handled(true):标记异常已被处理,不会向上传递给消费者(比如JPA轮询器),避免触发消费者的重试阻塞逻辑。continued(true):仅在全局onException中生效,告诉Camel处理完当前异常Exchange后,继续处理队列中的下一条消息,彻底解决轮询卡住的问题。
内容的提问来源于stack exchange,提问作者Noel93
相关产品推荐
相关产品推荐

