我想用Kafka(多种编程语言)为一个主题创建负载平衡。所以我做了以下。
我在C#中使用了confluent.kafka,在NodeJ中使用了kafkajs。
我打开生产者并保持运行。
Inconsistent group protocol
错误我们不能为同一个消费群体使用两种编程语言吗?
C#的生产者-Windows形式
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Confluent.Kafka;
namespace KafkaProducer
{
public partial class frmProducer : Form
{
const string TOPIC = "testTopic";
private IProducer<Null, string> pBuilder;
public frmProducer()
{
InitializeComponent();
}
private async void timer1_Tick(object sender, EventArgs e)
{
try
{
// instead of sending some value, we send current DateTime as value
var dr = await pBuilder.ProduceAsync(TOPIC, new Message<Null, string> { Value = DateTime.Now.ToLongTimeString() });
// once done, add the value into list box
listBox1.Items.Add($"{dr.Value} - Sent to Partition: {dr.Partition.Value}");
listBox1.TopIndex = listBox1.Items.Count - 1;
}
catch (ProduceException<Null, string> err)
{
MessageBox.Show($"Failed to deliver msg: {err.Error.Reason}");
}
}
private void frmProducer_Load(object sender, EventArgs e)
{
ProducerConfig config = new ProducerConfig { BootstrapServers = "localhost:9092" };
pBuilder = new ProducerBuilder<Null, string>(config).Build();
timer1.Enabled = true;
}
private void frmProducer_FormClosing(object sender, FormClosingEventArgs e)
{
timer1.Enabled = false;
pBuilder.Dispose();
}
}
}
使用C#的用户-Windows窗体
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Confluent.Kafka;
namespace KafkaConsumer
{
public partial class frmConsumer : Form
{
CancellationTokenSource cts = new CancellationTokenSource();
public frmConsumer()
{
InitializeComponent();
}
private void StartListen()
{
var conf = new ConsumerConfig
{
GroupId = "test-consumer-group",
BootstrapServers = "localhost:9092",
AutoOffsetReset = AutoOffsetReset.Earliest
};
using (var c = new ConsumerBuilder<Ignore, string>(conf).Build())
{
c.Subscribe("testTopic");
//TopicPartitionTimestamp tpts = new TopicPartitionTimestamp("testTopic", new Partition(), Timestamp. )
//c.OffsetsForTimes()
try
{
while (true)
{
try
{
var cr = c.Consume(cts.Token);
// Adding the consumed values into the UI
listBox1.Invoke(new Action(() =>
{
listBox1.Items.Add($"{cr.Value} - from Partition: {cr.Partition.Value}" );
listBox1.TopIndex = listBox1.Items.Count - 1;
}));
}
catch (ConsumeException err)
{
MessageBox.Show($"Error occured: {err.Error.Reason}");
}
}
}
catch (OperationCanceledException)
{
// Ensure the consumer leaves the group cleanly and final offsets are committed.
c.Close();
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
cts.Cancel();
}
private async void frmConsumer_Load(object sender, EventArgs e)
{
await Task.Run(() => StartListen());
}
}
}
NodeJ中的消费者
const { Kafka } = require("kafkajs");
const kafka = new Kafka({
clientId: 'my-app',
brokers: ["localhost:9092"]
});
const consumer = kafka.consumer({ groupId: "test-consumer-group" });
const run = async () => {
// Consuming
await consumer.connect();
await consumer.subscribe({ topic: "testTopic", fromBeginning: false });
await consumer.run({
eachMessage: async ({ topic, partition, message }) => {
console.log(message.value.toString() + " - from Partition " + partition);
}
});
};
run().catch(console.error);
如果我同时运行C#和NodeJs使用者,则会出现Inconsistent group protocol
错误。
如何在Kafka中使用来自不同编程语言的多个使用者?
答案 0 :(得分:0)
简短答案:
这可能与您想像的不同语言无关。发生这种情况的原因是两个消费者客户端(及其库)的协议不同。
尝试在两个消费者客户端中设置以下属性:
partition.assignment.strategy = round-robin
注意:我刚刚提供了常规属性,因此您需要查看针对客户的语言特定版本。您甚至可以将其设置为range
,但保持一致。
说明如下:
通读Kafka's wiki上的协议以找出Inconsistent group protocol
的根本原因-结果是在以下情况下返回此结果:
现在,ConsumerGroupProtocolMetadata
中可能有各个方面,但是partition.assignment.strategy
似乎在您使用的客户端库中确实有所不同。
dotnet client是librdkafka的包装,将上述属性的值默认为range
。这是reference。
其中
根据{{3}}的 kafkajs将其默认设置为round-robin
-从而导致不一致。
希望这会有所帮助。
答案 1 :(得分:0)
我知道这来得太晚了,但这是因为同一个组命名
当您启动 C# 客户端时,它会为其使用者创建一个组。
例如group-1(group-1-consumer-1、group-1-consumer-2 等) - 这些名称是自动分配的,所以不要打扰。我认为您可以手动设置这些,但不建议这样做以避免潜在的名称冲突。
现在,当您启动它时,您无法从不同的组运行器(来自另一个微服务)添加相同的组。 看看 Lalit 从 Kafka wiki 引用的内容:
<块引用>有一个活跃的消费者组,有活跃/正在运行的消费者
现在,当您启动 nodeJs 时,您应该使用不同的组名,因为很可能会使用该数据执行其他任务。
是的,您可以为两个组订阅相同的主题,因为 Kafka 会为每个组以及他们离开的位置保留一个偏移量。