繁体   English   中英

如何在程序中停止 Python Kafka Consumer?

[英]How to stop Python Kafka Consumer in program?

我正在做 Python Kafka 消费者(尝试在http://kafka-python.readthedocs.org/en/latest/apidoc/kafka.consumer.html 中使用 kafka.consumer.SimpleConsumer 或 kafka.consumer.simple.SimpleConsumer )。 当我运行以下代码时,它会一直运行,即使所有消息都被消耗了。 我希望消费者在消费完所有消息后会停止。 怎么做? 我也不知道如何使用 stop() 函数(它在基类 kafka.consumer.base.Consumer 中)。

更新

我使用信号处理程序来调用consumer.stop()。 一些错误信息被打印到屏幕上。 但是程序仍然卡在 for 循环中。 当新消息进来时,消费者消费它们并打印它们。 我也试过 client.close()。 但同样的结果。

我需要一些方法来优雅地停止 for 循环。

        client = KafkaClient("localhost:9092")
        consumer = SimpleConsumer(client, "test-group", "test")

        consumer.seek(0, 2)# (0,2) and (0,0)

        for message in consumer:
            print "Offset:", message.offset
            print "Value:", message.message.value

欢迎任何帮助。 谢谢。

我们可以首先检查主题中最后一条消息的偏移量。 然后,在达到该偏移量时停止循环。

    client = "localhost:9092"
    consumer = KafkaConsumer(client)
    topic = 'test'
    tp = TopicPartition(topic,0)
    #register to the topic
    consumer.assign([tp])

    # obtain the last offset value
    consumer.seek_to_end(tp)
    lastOffset = consumer.position(tp)

    consumer.seek_to_beginning(tp)        

    for message in consumer:
        print "Offset:", message.offset
        print "Value:", message.message.value
        if message.offset == lastOffset - 1:
            break

使用iter_timeout参数设置等待时间。 如果将其设置为10,就像下面的代码一样,如果在10秒内没有新消息出现,它将退出。 默认值为“无”,这意味着即使没有新消息进入,使用者也将在此处阻止。

        self.consumer = SimpleConsumer(self.client, "test-group", "test",
                iter_timeout=10)

更新资料

以上不是一个好的方法。 当有大量消息进入时,很难设置足够小的iter_timeout以保证停止。 因此,现在,我正在使用get_message()函数,该函数尝试消耗一条消息并停止。 没有新消息时不返回任何内容。

与Mohit的答案类似的解决方案,但使用了end_offsets函数。

from kafka import KafkaConsumer, TopicPartition

# settings
client = "localhost:9092"
topic = 'test'

# prepare consumer
tp = TopicPartition(topic,0)
consumer = KafkaConsumer(client)
consumer.assign([tp])
consumer.seek_to_beginning(tp)  

# obtain the last offset value
lastOffset = consumer.end_offsets([tp])[tp]

for message in consumer:
    print "Offset:", message.offset
    print "Value:", message.message.value
    if message.offset == lastOffset - 1:
        break

更简单的解决方案:

改用poll()poll_timeout_ms poll()是非阻塞调用。

  • 在 while 循环之外创建一个计数器变量。
  • 每次 poll() 从 Kafka Brokers 获取 0 条记录时增加计数器。
  • 如果poll()提取记录,则将计数器重置为 0
  • 如果 counter == 某个阈值(比如 10),则跳出循环并关闭使用者。

在这个逻辑中,我们依赖于这样一个事实:如果poll()在 10 次后续调用中没有获取任何记录,这意味着我们已经读取了所有数据。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM