如果您是駱駝的新手,並且真的想深入瞭解它,我會推薦Camel in Action, a book by Claus Ibsen。有a second edition in the works,19個章節中有14個已經完成了,所以你也可以給出一個答案。
如果這有點太多,在線文檔是非常好的,你可以從中找到基本的東西。對於錯誤處理,我建議從general error handling page開始,然後移動到error handler docs和exception policy documentation。
一般來說,dead letter channel是要走的路 - 在重試完畢後駱駝會自動發送給DLC,您只需自己定義DLC。它的名字暗示,這是一個渠道,並不需要成爲一個隊列 - 您可以寫入文件,調用Web服務,將消息提交給消息隊列或僅寫入日誌,這完全取決於您。
// error-handler DLC, will send to HTTP endpoint when retries are exhausted
errorHandler(deadLetterChannel("http4://my.webservice.hos/path")
.useOriginalMessage()
.maximumRedeliveries(3)
.redeliveryDelay(5000))
// exception-clause DLC, will send to HTTP endpoint when retries are exhausted
onException(NetworkException.class)
.handled(true)
.maximumRedeliveries(5)
.backOffMultiplier(3)
.redeliveryDelay(15000)
.to("http4://my.webservice.hos/otherpath");
我自己一直喜歡有一個消息隊列,然後從那裏消耗任何其他恢復或報告。我通常包括交換ID和路由ID,消息頭,錯誤消息,有時甚至是堆棧跟蹤等故障細節。正如您可以想象的那樣,生成的消息會增長很多,但它極大地簡化了故障排除和調試工作,特別是在您擁有大量組件和服務的環境中。下面是一個我的樣板項目DLC消息:
public class DeadLetterChannelMessage {
private String timestamp = Times.nowInUtc().toString();
private String exchangeId;
private String originalMessageBody;
private Map<String, Object> headers;
private String fromRouteId;
private String errorMessage;
private String stackTrace;
@RequiredByThirdPartyFramework("jackson")
private DeadLetterChannelMessage() {
}
@SuppressWarnings("ThrowableResultOfMethodCallIgnored")
public DeadLetterChannelMessage(Exchange e) {
exchangeId = e.getExchangeId();
originalMessageBody = e.getIn().getBody(String.class);
headers = Collections.unmodifiableMap(e.getIn().getHeaders());
fromRouteId = e.getFromRouteId();
Optional.ofNullable(e.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class))
.ifPresent(throwable -> {
errorMessage = throwable.getMessage();
stackTrace = ExceptionUtils.getStackTrace(throwable);
});
}
// getters
}
當從死信隊列消耗,路由標識可以告訴你的失敗源於這樣你就可以實現了特定於從那裏傳來遞錯誤路線:
// general DLC handling route
from("{{your.dlc.uri}}")
.routeId(ID_REPROCESSABLE_DLC_ROUTE)
.removeHeaders(Headers.ALL)
.unmarshal().json(JsonLibrary.Jackson, DeadLetterChannelMessage.class)
.toD("direct:reprocess_${body.fromRouteId}"); // error handling route
// handle errors from `myRouteId`
from("direct:reprocess_myRouteId")
.log("Error: ${body.errorMessage} for ${body.originalMessageBody}");
// you'll probably do something better here, e.g.
// .convertBodyTo(WebServiceErrorReport.class) // requires a converter
// .process(e -> { //do some pre-processing, like setting headers/properties })
// .toD("http4://web-service-uri/path"); // send to web-service
// for routes that have no DLC handling supplied
onException(DirectConsumerNotAvailableException.class)
.handled(true)
.useOriginalMessage()
.removeHeaders(Headers.ALL)
.to({{my.unreprocessable.dlc}}); // errors that cannot be recovered from