簡體   English   中英

Kafka Consumer如何以及何時使用Apache Camel之類的EIP框架在Kafka中提交偏移量?我們如何使用camel-kakfa異步處理重試?

[英]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";
}

關於上述代碼,我有兩個查詢:

  1. 在整個路由的哪一點,kafka使用者是提交偏移量還是它是一項獨立的任務,因為我尚未修改autoCommitIntervalMs字段的默認值5秒,因此這意味着它將每隔5秒鍾獨立提交一次。

  2. 我想在出現亂序異常的情況下處理請求場景,而我這樣做的方式是通過創建另一個具有延遲模式邏輯的端點,該端點將在最大請求時間后將錯誤消息發送到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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM