Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/41.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在Kafka中为同一组ID使用不同编程语言的多个使用者_C#_Node.js_Apache Kafka_Kafka Consumer Api - Fatal编程技术网

C# 如何在Kafka中为同一组ID使用不同编程语言的多个使用者

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,它工

我想用Kafka(多种编程语言)为一个主题创建一个负载平衡。所以我做了下面的事情

  • 创建了一个包含4个分区的主题
  • 在C#中创建了一个生产者(每秒生成消息)
  • 在C#中创建了一个消费者(消费者1)(消费者组:testConsumerGrp)
  • 在NodeJs中又创建了一个消费者(consumer2)(消费者组:testConsumerGrp)
  • 我用在C#和NodeJs中

    我打开producer并让它继续运行

  • 如果我只运行C#consumer,它工作得很好
  • 如果我只运行NodeJs consumer,它工作得很好
  • 如果我运行多个C#consumer(只有C#和少于4个实例),它就可以正常工作
  • 如果我运行多个NodeJs consumer(只有NodeJs和少于4个实例),它可以正常工作
  • 如果我运行一个C#和一个NodeJs消费者,那么我将得到
    不一致的组协议
    错误
  • 我们不能为同一消费群体使用两种编程语言吗

    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();
            }
        }
    }
    
    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);