簡體   English   中英

將數據從一個 Kafka 主題移動到另一個主題在 Kafka Python 中不起作用

[英]Moving data from one Kafka topic to other is not working in Kafka Python

我是卡夫卡的新手。 我目前正在嘗試與 Kafka 合作,我想從一個名為“input-topic”的 Kafka 主題中獲取數據,該主題有 5 個分區,每個分區都有一些隨機整數,並將其移動到另一個名為“輸出主題”的主題中,該主題只有一個分區。

下面是我正在使用的代碼

卡夫卡制作人

producer = KafkaProducer(bootstrap_servers=['localhost:9092'], value_serializer=lambda x: bytes(x))

topic_name = "input-topic"

num_partitions = 3

def send_data_to_topics():
    print("sending...")
    for i in range(num_partitions):
        for j in range(5):
            producer.send(topic_name, value=j, partition=i)
    producer.flush()
    

if __name__ == "__main__":
    send_data_to_topics()

卡夫卡消費者

topic_name_input  = "input-topic"
topic_name_output = "output-topic"

data = []

def bytes_to_int(bytes):
    result = 0
    for b in bytes:
        result = result * 256 + int(b)
    return result

consumer = KafkaConsumer(
     topic_name_input,
     bootstrap_servers=['localhost:9092'],
     group_id='my-group',
     value_deserializer=lambda x: bytes_to_int(x)
    )

producer1 = KafkaProducer(bootstrap_servers=['localhost:9092'], value_serializer=lambda x: bytes(x))

def read_topic_data():
    print("received")
    for message in consumer:
        print(message)
        data.append(message.value)

def send_data_to_topic():
    data = sorted(data) 
    for d in data:
        producer1.send(topic_name_output, value=d)
    producer1.flush()
        
        


if __name__ == "__main__":
    read_topic_data()
    send_data_to_topic()


另一個卡夫卡消費者

topic_name_input  = "input-topic"
topic_name_output = "output-topic"

def bytes_to_int(bytes):
    result = 0
    for b in bytes:
        result = result * 256 + int(b)
    return result

consumer2 = KafkaConsumer(
     topic_name_output,
     bootstrap_servers=['localhost:9092'],
     group_id='my-group_new',
     value_deserializer=lambda x: bytes_to_int(x)
    )

def read_topic_data():
    print("received")
    for message in consumer2:
        print(message)
        

if __name__ == "__main__":
    read_topic_data()

但是,我沒有收到“輸出主題”主題中的任何消息。 我在這里錯過了什么嗎? 我怎樣才能有效地實現它? 我需要使用 Kafka Streams 嗎? 任何幫助,將不勝感激。 謝謝!!

我建議使用KafkaStreams ,這對這個用例很有效。

KafkaConsumer 調用本質上是阻塞調用。 當 KafkaConsumer 啟動時,它開始處理主題中已經可用的消息並等待新消息進入。當新消息進入主題時,它將處理新消息,然后將繼續等待更多消息。

如果沒有新消息,可以將參數consumer_timeout_ms傳遞給 KafkaConsumer 構造函數以在 X 時間后停止處理。

從共享的示例代碼中,

if __name__ == "__main__":
    read_topic_data()
    send_data_to_topic()

由於 KafkaConsumer 的性質,會調用 read_topic_data() 函數,但控制權不會返回給 main。 所以 send_data_to_topic() 永遠不會被調用。

為了避免這個問題,從一個主題讀取數據和向另一個主題發送數據應該同時工作。 這里可以使用線程。

if __name__ == "__main__":
    read_thread = Thread(target=read_topic_data)
    read_thread.start()
    write_thread = Thread(target=send_data_to_topic)
    write_thread.start()

同樣需要注意的是,KafkaProducer 將發送data列表中的所有消息並退出。 退出后不等待/處理新消息。 所以用戶必須實現等待以保持它運行。

def send_data_to_topic():
    while True:
        print("starting write thread")
        sorted_data = sorted(data)
        for d in sorted_data:
            producer1.send(topic_name_output, value=d)
        producer1.flush()
        print("finishing write thread")
        time.sleep(10) # wait for 10 seconds before starting next iteration

代碼的另一個問題是消息重復。 read_topic_data() 從 Kafka 輸入主題讀取消息並將它們附加到列表data send_data_to_topic() 從此列表中讀取消息並將其發送到輸出主題。 但是,不會從列表中刪除已處理的消息。 隊列可用於解決此問題。

from threading import Thread
from queue import Queue

from kafka import KafkaProducer
from kafka import KafkaConsumer

topic_name_input = "input-topic"
topic_name_output = "output-topic"

data = Queue()


def bytes_to_int(bytes):
    result = 0
    for b in bytes:
        result = result * 256 + int(b)
    return result


consumer = KafkaConsumer(
     topic_name_input,
     bootstrap_servers=['avelusamy-mbp15:9092'],
     group_id='my-group',
     value_deserializer=lambda x: bytes_to_int(x)
    )

producer1 = KafkaProducer(
    bootstrap_servers=['avelusamy-mbp15:9092'], value_serializer=lambda x: bytes(x))


def read_topic_data():
    print("received")
    for message in consumer:
        print(message)
        data.put(message.value)


def send_data_to_topic():
    while True:
        producer1.send(topic_name_output, value=data.get())
        producer1.flush()


if __name__ == "__main__":
    read_thread = Thread(target=read_topic_data)
    read_thread.start()
    write_thread = Thread(target=send_data_to_topic)
    write_thread.start()

暫無
暫無

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

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