簡體   English   中英

Apache Kafka Consumer未按順序接收消息

[英]Apache Kafka Consumer not receiving messages in Order

我正在我的項目中嘗試Kafka的POC,並使用Confluent.kafka庫在.net core 2.1中創建了兩個控制台應用程序。 我已經在Ubuntu盒子上安裝了Kafka,它運行正常。 當我使用Producer控制台應用程序將數千條消息推入Kafka並在消息中附加序列號時。 當我在客戶控制台應用程序中使用這些消息時,消息順序不正確。 生產者和消費者只有一個,它們都與一個主題相關。 以下是我的生產者的代碼

public class Kafta
{
    private Dictionary<string, object> config;
    private string topicName;

    public Kafta(string topic)
    {
        config = new Dictionary<string, object>
        {
            {"bootstrap.servers","192.168.60.173:9092" }
        };
        topicName = topic;
    }
    public async void SendMessageAsync(string message)
    {
        using (var producer = new Producer<string, string>(config, new StringSerializer(Encoding.UTF8), new StringSerializer(Encoding.UTF8)))
        {
            var msg = await producer.ProduceAsync(topicName, "userid", message);

            //producer.ProduceAsync("console", null, message);
            producer.Flush(500);
        }
    }
}

生產者的Program.cs靜態void main

static void Main(string[] args)
    {
        string topic = "tester2";
        long count = 1;
        Console.WriteLine("Starting to send message");
        Console.WriteLine("Write the message here: ");

        if(args.Length == 2)
        {
            topic = args[0];
            count = long.Parse(args[1]);
        }
        try
        {
            Console.WriteLine("Topic name " + topic);
            var message = Console.ReadLine();            
            var service = new Kafta(topic);

            for(var i = 0; i<count;i++)
            {
                var msg = message + " number " + i.ToString();
                Console.WriteLine("Message to Kafta: " + msg);
                service.SendMessageAsync(msg);
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception occured " + ex.Message);
        }
        finally
        {
            Console.WriteLine("Press any key to exit");
            Console.Read();
        }
    }

消費者代碼

static void Main(string[] args)
    {
        var config = new Dictionary<string, object>
        {
          { "group.id", "sample-consumer" },
          { "bootstrap.servers", "192.168.60.173:9092" },
          { "enable.auto.commit", "false"}
        };
        string topic = "tester2";
        if (args.Length == 1)
            topic = args[0];
        using (var consumer = new Consumer<string, string>(config, new StringDeserializer(Encoding.UTF8), new StringDeserializer(Encoding.UTF8)))
        {
            consumer.Subscribe(new string[] { topic });                
            consumer.OnMessage += (_, msg) =>
            {
                Console.WriteLine($"Topic: {msg.Topic} Partition: {msg.Partition} Offset: {msg.Offset} {msg.Value}");
                consumer.CommitAsync(msg);

            };

            while (true)
            {
                consumer.Poll(100);
            }
        }
    }

生產者的輸出

Message to Kafta: message number 0
Message to Kafta: message number 1
Message to Kafta: message number 2
Message to Kafta: message number 3
Message to Kafta: message number 4
Message to Kafta: message number 5
Message to Kafta: message number 6
Message to Kafta: message number 7
Message to Kafta: message number 8
Message to Kafta: message number 9

消費者的輸出:

message number 4
message number 7
message number 0
message number 1
message number 2
message number 3
message number 5
message number 6
message number 8
message number 9

我是Kafka的新手,不確定要使它正常工作我所缺少的東西。 根據Kafka文檔,對於我的用例,可以保證消息的排序,因此我在做某些愚蠢的錯誤,無法弄清楚。

我可以使用Kafka以外的其他替代方法嗎?

謝謝

根據Kafka文檔,消息的訂購得到保證

每個分區 關於您的問題,您沒有提到主題有多少個分區。 您正在打印Topic: {msg.Topic} Partition: {msg.Partition} ,但這不是帖子的輸出。

在生產者中,您正在使用SendMessageAsync進行“射擊后遺忘”,而不是驗證代理是否實際接收到具有該方法返回值的消息。 因此,這是一種可能性-您的打印報表會井然有序,但是消息不一定以這種方式到達代理。

如果代碼中顯示的使用者輸出中的分區號始終相同,而我對C#API並不熟悉,則好像您正在使用非阻塞的使用者消息偵聽器。 OnMessage函數很可能在單獨的線程中被調用,該線程不一定以保證的順序寫入標准輸出。 更好的測試可能是在每條消息中插入時間戳,而不是僅添加計數器

我可以使用Kafka以外的其他替代方法嗎?

存在大量其他MQ技術,例如RabbitMQ,因此,如果您不關心Kafka的持久性功能和其他API(Streams和Connect),請隨時使用這些技術。

如@ cricket_007所述,具有一個主題和多個分區意味着僅對從一個分區接收的數據進行排序。

創建使用者(僅一個)時,它將使用所有分區來讀取消息。 然后,來自分區的數據會同步顯示為紅色(是),但是您收到消息的分區隨時間變化。

假設您針對4個分區產生了100條主題消息。 為了簡潔起見,請說每個分區存儲25條消息。 當啟動使用者時,它會收到以下消息(示例):

  • 來自分區#1的5條消息
  • 來自分區2的4條消息
  • 來自分區#3的6條消息
  • 來自分區4的2條消息
  • 來自分區#1的3條消息
  • ...

這是因為使用者嘗試均勻讀取所有分區。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM