[英]How and when Kafka Consumer commits offsets in Kafka with EIP frameworks like Apache Camel?How can we handle retry asynchronously with camel-kakfa?
路由構建器的示例代碼如下:
// For out of seq event state (reque)
onException(OutOfSeqStateException.class)
.logStackTrace(false).logExhaustedMessageHistory(false)
.setHeader("eventSource", constant(EventConstants.BACKEND))
.delay(30000)/*.method(DelayerBean.class , "computeDelayInMillis")*/.asyncDelayed().// delay should be asynchronously
.setBody().header(EventConstants.BE_STATE_EVENT)// send original event
.to("direct:requeue");// toendpoint: requeroute
// For handling other exceptions
onException(Exception.class)
.log("EXCEPTION OCCURED..... -> \"${exception.message}\"")
.setExchangePattern(ExchangePattern.InOnly)
.bean(KafkaErrorHandlerBean.class, "handle")
.handled(true);
// Backend Events Route
from(commonCamelConfig.getKafkaConsumerEndpoint())
.routeId("BackendStateIncomingRoute")
.id(routeId)
.to("log:" + fqClassName + "?showAll=true&level=" + logLevel)
.unmarshal(jdf)
.bean(MandatoryFieldCheckerBean.class, "performNullCheck")
// all context info must be present,if not, throw exception
.bean(ValidateEventHandlerBean.class, "validateIncomingEvents")
.choice()
.when().simple("${in.header.isValidEvent} == true",Boolean.class)//enter if valid event(backendstate/backenddata)
.choice()
.when(header("BEStateEvent").isNotNull())
.bean(EventTransformer.class, "getBackendTransformedEvent")
.bean(PaymentsService.class, "processMessage")
.bean(TransitionalStateHandlerBean.class,"handle")
.bean(AMQPProducer.class, "sendEventToMQ")
.setExchangePattern(ExchangePattern.InOnly)
.otherwise()
.bean(EventTransformer.class, "getBackendTransformedEvent")
.bean(PaymentsService.class, "processMessage")
.endChoice()
.setExchangePattern(ExchangePattern.InOnly)//acknowledge only valid events, doesnt expect a reply
.endChoice()
.end();
//Reque the original event in case of Retryable Exceptions
from("direct:requeue").routeId("BackendDirectRequeRoute")
.bean(RequestRetryHandlerBean.class, "doRetry")
.to(commonCamelConfig.getKafkaConsumerEndpoint())
.end();
使用者端點的Kafka配置如下:
public String getKafkaConsumerEndpoint() {
return properties.getJmsKafkaBroker()
+ ":" + properties.getKafkaPaymentsOtpTopic()
+ "?brokers="+ properties.getBootstrapServers()
+ "&groupId="+ properties.getGroupId()
+ "&autoOffsetReset="+ properties.getAutoOffsetReset()
+ "&autoCommitEnable=true"
+ "&keyDeserializer=org.apache.kafka.common.serialization.StringDeserializer"
+ "&valueDeserializer=org.apache.kafka.common.serialization.StringDeserializer";
}
關於上述代碼,我有兩個查詢:
在整個路由的哪一點,kafka使用者是提交偏移量還是它是一項獨立的任務,因為我尚未修改autoCommitIntervalMs字段的默認值5秒,因此這意味着它將每隔5秒鍾獨立提交一次。
我想在出現亂序異常的情況下處理請求場景,而我這樣做的方式是通過創建另一個具有延遲模式邏輯的端點,該端點將在最大請求時間后將錯誤消息發送到DLQ。 上述邏輯中有哪些漏洞,有沒有更好的方法來處理? 如果此邏輯看起來不錯,那么請查看我已使用asyncdelayed()進行異步延遲,但它似乎無法正常工作並阻止新消息,直到被請求為止。 也請幫助我實現異步延遲。
1)如果使用的駱駝版本<2.22,則無法控制偏移提交,它發生在默認值為5秒且可以更改的另一個線程中。 如果您使用的駱駝版本> = 2.22,則只有您可以控制消息的手動提交。 要使用手動提交,請設置以下屬性:
autoCommitEnable = false:關閉自動提交偏移量,以便我們可以使用手動提交。 allowManualCommit = true:打開手動提交,使我們能夠使用KafkaManualCommit功能。 下面是代碼片段:
KafkaManualCommit manual =
exchange.getIn().getHeader(KafkaConstants.MANUAL_COMMIT, KafkaManualCommit.class);
if (manual != null) {
LOGGER.info("committing the offset manually");
manual.commitSync();
}
2)在第二個問題中,您似乎希望將消息再次放回kafka上進行處理。 但是從您的代碼看來,您正在為消費者和生產者使用相同的終結點。 當您想在kafka中生成消息時,需要指定消息中未顯示的消息的“主題”,“分區”和“鍵”。 討論漏洞,因為您將消息再次放入kafka中,如果消息已損壞怎么辦,因此您將繼續獲取相同的異常並將相同的消息再次放入kafka中。 我建議以相同的路徑重試該消息。 下面是代碼片段:
onException(YourException.class)
.maximumRedeliveries(3) // You can call some method too
.redeliveryDelay(100) // You can call some method too
.onRedelivery(exchange -> {
int retryCount = exchange.getIn().getHeader(Exchange.REDELIVERY_COUNTER, Integer.class);
log.debug("Recoverable exception occurred. Retried {} time " , retryCount);
})
.retryAttemptedLogLevel(LoggingLevel.DEBUG)
.to("someOtherRoute // Probably to error-topic
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.