C# 如何在Kafka中为同一组ID使用不同编程语言的多个使用者
我想用Kafka(多种编程语言)为一个主题创建一个负载平衡。所以我做了下面的事情C# 如何在Kafka中为同一组ID使用不同编程语言的多个使用者,c#,node.js,apache-kafka,kafka-consumer-api,C#,Node.js,Apache Kafka,Kafka Consumer Api,我想用Kafka(多种编程语言)为一个主题创建一个负载平衡。所以我做了下面的事情 创建了一个包含4个分区的主题 在C#中创建了一个生产者(每秒生成消息) 在C#中创建了一个消费者(消费者1)(消费者组:testConsumerGrp) 在NodeJs中又创建了一个消费者(consumer2)(消费者组:testConsumerGrp) 我用在C#和NodeJs中 我打开producer并让它继续运行 如果我只运行C#consumer,它工作得很好 如果我只运行NodeJs consumer,它工
不一致的组协议
错误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();
}
}
}
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());
}
}
}
如果我同时运行C#和NodeJs consumer,则得到不一致的组协议
错误
如何在卡夫卡中使用来自不同编程语言的多个使用者?简短回答: 这可能和您可能认为的不同语言并没有多大关系。这是由于两个客户机(及其库)的协议不同而导致的 尝试在两个使用者客户端中设置以下属性:
partition.assignment.strategy=round-robin
注意:我刚刚提供了general属性,因此您需要查看客户机的特定语言版本。您甚至可以将其设置为范围
,但要保持一致
解释如下:
通读上的协议以找出组协议不一致的根本原因-结果表明,当:
ConsumerGroupProtocolMetadata
中可能有许多方面,但是在您使用的客户机库中,有一个方面似乎有所不同,那就是分区.assignment.strategy
是一个包装器,默认将上述属性的值设置为范围
。这是我的建议
何处为
根据默认设置,它是循环的,因此导致不一致
希望这能有所帮助。我知道这来得太晚了一年,但这是因为同一组的名字 启动C#client时,它会为其消费者创建一个组 例如,group-1(group-1-consumer-1、group-1-consumer-2等)-这些名称是自动分配的,因此不必麻烦。我认为您可以手动设置这些,但不建议这样做以避免潜在的名称冲突 现在,当您将其设置为动态时,您无法从不同的组运行程序(从另一个微服务)添加相同的组。 请参阅Lalit从卡夫卡维基引用的内容: 存在一个活动消费者组,其中有活动/正在运行的消费者 现在,当您启动nodeJs one时,您应该使用不同的组名,因为最有可能使用该数据执行其他任务
是的,您可以为两组订阅相同的主题,因为卡夫卡将为每个组及其离开的位置保留一个偏移量。谢谢您的回答,但我仍然收到相同的错误。我将C#中的PartitionAssignmentStrategy更改为RoundRobin,并对NodeJs做了相同的更改,但没有起到帮助:(
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);