可以在控制台中使用Kafka消息但不能使用Python库吗?

时间:2017-06-06 09:37:30

标签: python linux apache-kafka message-queue kafka-consumer-api

我在笔记本电脑上做本地操作,并尝试阅读一个主题“测试”'来自远程服务器' xxxxx'。 使用控制台时,我启动zookeeper,Kafka,然后是消费者:

bin/zookeeper-server-start.sh config/zookeeper.properties
bin/kafka-server-start.sh config/server.properties
bin/kafka-console-consumer.sh --bootstrap-server xxxxx:9092 --topic test --from-beginning

消息将显示在控制台中。 但是当使用Python库时,我什么也看不见:

from kafka import KafkaConsumer

server = {'server': 'xxxxx:9092', 'topic': 'test'}

# To consume latest messages and auto-commit offsets
consumer = KafkaConsumer(server['topic'],
                         group_id='my-group',
                         bootstrap_servers=server['server'])

for message in consumer:
    # message value and key are raw bytes -- decode if necessary!
    # e.g., for unicode: `message.value.decode('utf-8')`
    print("%s:%d:%d: key=%s value=%s" % (message.topic, message.partition,
                                         message.offset, message.key,
                                         message.value))

我也可以成功地将Kafka本地消息从控制台发送到Python Kafka使用者,只有在尝试使用远程消息时才会出现问题。 此外,连接似乎已经建立到远程服务器(它可以看到我),但遗憾的是没有收到任何内容。

1 个答案:

答案 0 :(得分:1)

我找到的解决方案是使用另一个库,Confluent Kafka Python,这个库只需配置服务器IP和要收听的主题名称即可开箱即用

编辑:这是我实施的解决方案:

我认为Avro库只是为了阅读Avro文件,但它实际上解决了解码Kafka消息的问题,如下所示:我首先导入库并将模式文件作为参数提供,然后创建一个函数来解码消息进入字典,我可以在消费者循环中使用。

from confluent_kafka import Consumer, KafkaError
from avro.io import DatumReader, BinaryDecoder
import avro.schema

schema = avro.schema.Parse(open("data_sources/EventRecord.avsc").read())
reader = DatumReader(schema)

def decode(msg_value):
    message_bytes = io.BytesIO(msg_value)
    decoder = BinaryDecoder(message_bytes)
    event_dict = reader.read(decoder)
    return event_dict

c = Consumer()
c.subscribe(topic)
running = True
while running:
    msg = c.poll()
    if not msg.error():
        msg_value = msg.value()
        event_dict = decode(msg_value)
        print(event_dict)
    elif msg.error().code() != KafkaError._PARTITION_EOF:
        print(msg.error())
        running = False