![](/img/trans.png)
[英]Kafka message key is null using Confluent.Kafka consumer library
[英]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.