![](/img/trans.png)
[英]Consume Data from Confluent Kafka Topic and Exit using 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.