簡體   English   中英

如何使用 Confluent Kafka 處理消費者端的消息處理失敗?

[英]How to handle message processing failures on consumer end with Confluent Kafka?

我正在從基於 JMS 的系統轉向 Kafka,它負責同步新系統和舊系統之間的事務。 新系統發布的每條消息都必須由訂閱者/消費者成功處理。 我不必擔心消息的順序。 由於遺留系統中的一些設計問題(悲觀鎖定),有時消息到達時很少有事務可能會失敗,在這種情況下,我希望該消息在一些延遲后返回。 我想弄清楚如何用 Kafka 處理這種情況。

我的源和目標應用程序在 .NET 4.6.1 和 c# 中。 我正在使用 Confluent.Kafka v0.9.5 客戶端庫。 Kafka 是 0.10 版本。

對於消費者應用程序,我已禁用自動提交並顯式調用 commitAsync 方法以在成功處理消息后提交偏移量。 這是我創建消費者的方式。

var config = new Dictionary<string, object>()
                {
                    {"group.id", GroupId},
                    {"client.id", ClientId},
                    {"enable.auto.commit", false},
                    {"bootstrap.servers", _consumerConnectionConfig.BrokerUrl},
                    {
                        "default.topic.config", new Dictionary<string, object>()
                        {
                            {"auto.offset.reset", "latest"}
                        }
                    }
                };
var consumer = new Consumer<string, string>(config, new StringDeserializer(Encoding.UTF8), new StringDeserializer(Encoding.UTF8));

這就是輪詢的設置方式。

consumer.Subscribe(topics);

while (!SubscriberCancellationToken.IsCancellationRequested)
{
      consumer.Poll(TimeSpan.FromMilliseconds(1000));
}

這里是負責處理消息的 OnMessage 事件

consumer.OnMessage += (sender, message) => {
   try
   {
     var payload = GetPayload(message);
     if (_messageHandlerService.ProcessMessage(payload))
     {                 
      consumer.CommitAsync(message).Wait(SubscriberCancellationToken);   
     }
     else
     {
         //(case 1) Now what should I do?????
     }
   }
   catch(Exception ex)
   { 
        Log.Error("Unable to process xyz messages", ex);
        throw; //??? (Case 2) should I throw the exception or should I not?
   }
};

如果消息可以被成功處理,我會調用 commitAsync 並且這就像一個魅力。 現在我的問題是,當我無法處理消息(情況 1)或發生某些異常(情況 2)時,我該怎么辦。 我有什么選擇來處理這兩種情況?

在 JMS 世界中,對於(案例 1),我應用了延遲重新發布策略。 基本上我等待 1 分鍾,然后將消息重新發布到同一主題並提交當前消息,以便重新發布的消息將再次返回。 出於某種原因,如果我無法重新發布,我只會不斷重試,直到可以或直到進程重新啟動。 如果進程在我重新發布之前重新啟動,未提交的消息就會返回,並且循環又會重新開始。

一旦重新發布成功,如果主題上已經有其他消息在等待,它們現在將開始移動,火車會繞圈運行,直到所有內容都處理完畢。 每次我無法像情況 1 那樣處理消息時,我都會記錄一個錯誤,並根據它生成適當的警報,以便應用程序支持團隊可以采取一些措施,以防萬一他們必須修復遺留系統中的某些數據。 在此之前,消息一直失敗,然后重新發布。

對於案例 2,我正在記錄詳細信息並在 JMS 實現中拋出異常。 我現在想知道我是否應該像情況 1 一樣處理。

現在我的問題是我應該如何在 Kafka 的世界中處理這兩種情況? 有沒有更好的選擇?

選項很少

一種是將這些消息推送到另一個 Kafka 主題,並讓專門的消費者處理它,或者,

在您的消費者中重試,直到該特定消息得到處理或您達到某個閾值。 這可以通過在您的消費者上調用 pause 方法以暫時停止消息消費來完成(我是從 Java 消費者的角度說話,請與 C# 客戶端確認),運行您的重試邏輯。 請確保您也繼續調用 poll(否則消費者將被踢出組並重新平衡其分區)。 完成重試后,調用 resume 方法繼續處理 - 現在 poll 方法將從 Kafka 返回記錄

錯誤處理可以更直接,使用更高級別的庫,例如“我的” Silverback( https://github.com/BEagle1984/silverback ,可幫助您處理它們。

它實現了錯誤策略的概念,您可以使用該概念來配置消費者在發生錯誤時的行為方式(重試/跳過/將消息移動到另一個主題)。

...
.AddKafkaEndpoints(endpoints => endpoints
    .Configure(config => 
        {
            config.BootstrapServers = "PLAINTEXT://kafka:9092"; 
        })
    .AddInbound(endpoint => endpoint
        .ConsumeFrom("order-events")
        .Configure(config => 
            {
                config.GroupId = "my-consumer";
            })
        .OnError(policy => policy
            .Retry(3, TimeSpan.FromSeconds(1))
            .ThenSkip())));

請參閱https://silverback-messaging.net/concepts/broker/inbound.html#error-handling

(Silverback 建立在 Confluent.Kafka 之上。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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