我正在从基于JMS的系统转移到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那样处理。
现在我的问题是我应该如何处理卡夫卡世界的这两种情况?还有更好的选择吗?
答案 0 :(得分:1)
几个选项
一个是将这些消息推送到另一个Kafka主题,让专门的消费者处理它,或者,
在您的消费者中重试,直到处理完特定消息或达到某个阈值。这可以通过在您的使用者上调用pause方法来暂时停止消息消耗来完成(我从Java消费者的角度来看,请与C#客户端确认),运行您的重试逻辑。请确保您也继续调用轮询(否则消费者将被踢出组,其分区将被重新平衡)。一旦你重新尝试,请调用resume方法继续处理 - 现在poll方法将从Kafka返回记录
答案 1 :(得分:0)
错误处理可以更直接,使用更高级别的库,例如“我的”Silverback(https://github.com/BEagle1984/silverback 可以帮助您处理它们。
它实现了错误策略的概念,您可以使用该概念来配置消费者在出现错误时的行为方式(重试/跳过/将消息移动到另一个主题)。
text-overflow: ellipsis
见https://silverback-messaging.net/concepts/broker/inbound.html#error-handling。
(Silverback 建立在 Confluent.Kafka 之上。)