Python Kafka客户端confluent-kafka学习总结
实践环境
Python 3.6.2
confluent-kafka 2.2.0
confluent-kafka简介
Confluent在GitHub上开发和维护的confluent-kafka-python,Apache Kafka的一个python客户端,提供了一个与所有brokers>=v0.8
的kafka 、Confluent Cloud和Confluent Platform兼容的高阶级生产者、消费者和AdminClient。
confluent-kafka安装
pip install confluent-kafka
代码实践
Kafka生产者
from confluent_kafka import Producer
import socket
def acked(err, msg):
if err is not None:
print("Failed to deliver message: %s: %s" % msg.value(), str(err))
else:
print("Message produced: %s" % msg.value())
if __name__ == '__main__':
topic_name = 'FREE_TOPIC_FOR_TEST'
### 初始化Producer (针对本地运行的Kafka,即不在Confluent云平台上运行的Kafka)
conf = {'bootstrap.servers': '100.81.xxx.xx:9092,100.81.xxx.xx:9092',
'client.id': socket.gethostname()}
producer = Producer(conf)
### 异步写 kafka
# 给kafka发送消息--异步请求
producer.produce(topic_name, key="key", value="value")
# 添加回调函数
producer.produce(topic_name, value="test value", callback=acked)
# 最多等待事件1秒钟。等待期间,如果消息被确认,即成功写入kafka中,将调用回调 callback指定方法 acked
producer.poll(1)
### 同步写kafka
producer.produce(topic_name, key="key", value="new msg")
producer.flush()
说明:
produce方法
producer.produce(topic, key="key", value="value", callback=None) # 给kafka发送消息
topic
kafka主题,如果主题不存在,则将自动创建key
可选value
需要发送的消息,可以为None
callback
回调函数。
product调用为异步请求,所以调用后立即完成,且不会返回值。如果由于librdkafka的本地生产队列已满而导致消息无法入队,则会引发KafkaException
。
如果要接收发送是否成功或失败的通知,可以传递callback
参数,该参数值可以是任何可调用的,例如lambda、函数、绑定方法或可调用对象。尽管produce()
方法会立即将消息加入队列以进行批处理、压缩并传输到代理,但在调用poll()
之前,不会传播任何传递通知事件。
flush方法
flush()
方法用于同步写kafka。这通常是个坏主意,因为它有效地将吞吐量限制在broker往返时间内,但在某些情况下可能是合理的。
通常,应该在关闭生产者之前调用flush(),以确保所有未完成的/排队的/in-flight的消息都被传递。
Kafka消费者
import time
from confluent_kafka import Consumer
from confluent_kafka import KafkaException, KafkaError
running = True
def msg_process(msg):
value = msg.value()
if value:
value = value.decode('utf-8') # 假设消息可采用 utf-8解码
return {
'topic': msg.topic(),
'partition': msg.partition(),
'offset': msg.offset(),
'value': value
}
def consume_loop(consumer, topics):
global running
try:
consumer.subscribe(topics) # 订阅主题
while running:
msg = consumer.poll(timeout=10.0)
if msg is None:
time.sleep(0.1)
continue
if msg.error():
if msg.error().code() == KafkaError._PARTITION_EOF:
# End of partition event
print('%% %s [%d] reached end at offset %d\n' %
(msg.topic(), msg.partition(), msg.offset()))
elif msg.error():
raise KafkaException(msg.error())
else:
res = msg_process(msg)
try:
result = '{' + '"topic": "{topic}", "partition": {partition}, "offset": {offset}, "value": {value}'.format(**res) + '}\n'
except Exception:
result = '{' + '"topic": "{topic}", "partition": {partition}, "offset": {offset}, "value": "{value}"'.format(**res) + '}\n'
print(result)
finally:
# 关闭消费者以提交最后的偏移量
consumer.close()
if __name__ == '__main__':
topic_name = 'FREE_TOPIC_FOR_TEST_1'
# 初始化消费者
conf = {'bootstrap.servers': '100.81.xxx.xx:9092,100.81.xxx.xx:9092',
'group.id': 'custom_consumer',
'enable.auto.commit': 'true',
'auto.offset.reset': 'smallest',
}
consumer = Consumer(conf)
consume_loop(consumer, [topic_name]) # 可以指定多个主题
说明:
初始化消费者配置字典说明
conf = {'bootstrap.servers': 'host1:9092,host2:9092',
'group.id': 'foo',
'enable.auto.commit': 'false',
'auto.offset.reset': 'smallest'}
说明:
group.id
属性是必需的,设置当前消费者归属的消费组,可以是事先不存在的消费组。auto.offset.reset
属性指定针对当前消费组,在分区没有提交偏移量或提交偏移量无效(可能是由于日志截断)的情况下,消费者应该从哪个偏移量开始读取。可选值:'smallest'
如果针对当前消费组,分区未提交offset
,则从头开始消费,否则从已提交的offset
开始消费(即读取上次提交offset
之后生产的数据)。'largest'
如果针对当前消费组,分区未提交offset
,则读取新生产的数据(在启动该消费者之后才生产的数据),不会读取之前的数据,否则从已提交的offset
开始消费,同smallest
'earliest'
同'smallest'
'latest'
同'largest'
kafka-0.10.1.X 版本之前:auto.offset.reset
的值为smallest
和largest
(offest
保存在zk中)
kafka-0.10.1.X版本之后:auto.offset.reset
的值更改为 earliest
, latest
(offest
保存在kafka的一个特殊的topic名为:__consumer_offsets
里面)
enable.auto.commit
设置是否允许自动提交偏移量,默认为'true'
,即允许。
一个典型的Kafka消费者应用程序以循环消费为中心,该循环重复调用poll
方法来逐条检索消费者在后台高效预取的记录。例中poll
超时被硬编码为1秒。如果在此期间没有收到任何记录,则Consumer.poll()
将返回一个空记录集。
注意,在使用完Consumer
之后,应该始终调用Consumer.close()
,以确保活动套接字处于关闭状态,并清理内部状态。此外,还将立即触发组再均衡(group rebalance),以确保消费者拥有的任何分区都被重新分配给组中的另一个成员。如果未正确关闭,broker将仅在会话超时到期后才触发再均衡。
同步提交
手动提交偏移量的最简单、最可靠的方法是为Consumer.commit()
调用设置asynchronous
参数,与此同时设置构建消费者对象参数配置'enable.auto.commit'
为'false'
。
MIN_COMMIT_COUNT = 10
def consume_loop(consumer, topics):
try:
consumer.subscribe(topics)
msg_count = 0
while running:
msg = consumer.poll(timeout=1.0)
if msg is None: continue
if msg.error():
if msg.error().code() == KafkaError._PARTITION_EOF:
# End of partition event
print('%% %s [%d] reached end at offset %d\n' %
(msg.topic(), msg.partition(), msg.offset()))
elif msg.error():
raise KafkaException(msg.error())
else:
msg_process(msg)
msg_count += 1
if msg_count % MIN_COMMIT_COUNT == 0:
consumer.commit(asynchronous=False)
finally:
# 关闭消费者以提交最后的偏移量
consumer.close()
在本例中,每消费MIN_COMMIT_COUNT
消息都会触发一次同步提交。asynchronous
标志控制此调用是否为异步调用,默认为False
,即同步 。您还可以在超时到期时触发提交,以确保定期更新提交的位置。
消息投递保证
在前面的示例中,由于提交在消息处理之后,所以获得了“至少一次(at least once
)”投递。然而,通过更改提交偏移和处理消息的顺序,可获得“最多一次(at most once
)”投递,但必须小心提交失败。
说明:
- 最多一次(
at most once
):消息可能丢失也可能被处理,但最多只会处理一次。因为当提交offset
后,处理消息过程中出错导致消息处理失败,或者消费者down掉,导致消息不被处理。 - 至少一次(
at least once
):消息不会丢失,但可能被处理多次。先获取消息,然后处理消息,最后提交offset
,提交offset
时,可能会因为网络超时,消费者down掉等,导致提交偏移量失败的情况,所以,会导致重复消费消息的情况,进而导致多次处理消息。
def consume_loop(consumer, topics):
try:
consumer.subscribe(topics)
while running:
msg = consumer.poll(timeout=1.0)
if msg is None: continue
if msg.error():
if msg.error().code() == KafkaError._PARTITION_EOF:
# End of partition event
print('%% %s [%d] reached end at offset %d\n' %
(msg.topic(), msg.partition(), msg.offset()))
elif msg.error():
raise KafkaException(msg.error())
else:
consumer.commit(asynchronous=False)
msg_process(msg)
finally:
# 关闭消费者以提交最后的偏移量
consumer.close()
简单起见,在本例中,在处理消息之前使用Consumer.commit()
。在实践中,对每条消息都进行提交会产生大量开销。更好的方法是收集一批消息,执行同步提交,然后只有在提交成功的情况下才处理消息。
异步提交
def consume_loop(consumer, topics):
try:
consumer.subscribe(topics)
msg_count = 0
while running:
msg = consumer.poll(timeout=1.0)
if msg is None: continue
if msg.error():
if msg.error().code() == KafkaError._PARTITION_EOF:
# End of partition event
print('%% %s [%d] reached end at offset %d\n' %
(msg.topic(), msg.partition(), msg.offset()))
elif msg.error():
raise KafkaException(msg.error())
else:
msg_process(msg)
msg_count += 1
if msg_count % MIN_COMMIT_COUNT == 0:
consumer.commit(asynchronous=True)
finally:
consumer.close()
本例在前面示例的基础上,将commit()
的asynchronous
参数改成True
,消费者将使用异步提交发送请求并立即返回
API提供了一个callback,当提交成功或失败时会调用该callback。 commit callback回调可以是任何可调用的,并且可以作为配置参数传递给消费者构造函数。
from confluent_kafka import Consumer
def commit_completed(err, partitions):
if err:
print(str(err))
else:
print("Committed partition offsets: " + str(partitions))
conf = {'bootstrap.servers': "host1:9092,host2:9092",
'group.id': "foo",
'auto.offset.reset': 'smallest',
'on_commit': commit_completed}
consumer = Consumer(conf)
参考连接
https://docs.confluent.io/kafka-clients/python/current/overview.html#initialization
https://docs.confluent.io/platform/current/clients/confluent-kafka-python/html/index.html
Python Kafka客户端confluent-kafka学习总结的更多相关文章
- 基于Confluent.Kafka实现的Kafka客户端操作类使用详解
一.引言 有段时间没有写东西了,当然不是没得写,还有MongoDB的系列没有写完呢,那个系列还要继续.今天正好是周末,有点时间,来写新东西吧.最近公司用了Kafka做为消息的中间件,最开始写的那个版本 ...
- kafka - Confluent.Kafka
上个章节我们讲了kafka的环境安装(这里),现在主要来了解下Kafka使用,基于.net实现kafka的消息队列应用,本文用的是Confluent.Kafka,版本0.11.6 1.安装: 在NuG ...
- python confluent kafka客户端配置kerberos认证
kafka的认证方式一般有如下3种: 1. SASL/GSSAPI 从版本0.9.0.0开始支持 2. SASL/PLAIN 从版本0.10.0.0开始支持 3. SASL/SCRAM-SHA- ...
- 使用kafka-python客户端进行kafka kerberos认证
之前说过python confluent kafka客户端做kerberos认证的过程,如果使用kafka python客户端的话同样也可以进行kerberos的认证,具体的认证机制这里不再描述,主要 ...
- 4 kafka集群部署及kafka生产者java客户端编程 + kafka消费者java客户端编程
本博文的主要内容有 kafka的单机模式部署 kafka的分布式模式部署 生产者java客户端编程 消费者java客户端编程 运行kafka ,需要依赖 zookeeper,你可以使用已有的 zo ...
- 如何创建Kafka客户端:Avro Producer和Consumer Client
1.目标 - Kafka客户端 在本文的Kafka客户端中,我们将学习如何使用Kafka API 创建Apache Kafka客户端.有几种方法可以创建Kafka客户端,例如最多一次,至少一次,以及一 ...
- 从0开始搭建kafka客户端
上一节,我们实现了搭建kafka集群.本节我们将从0开始,使用Java,搭建kafka客户端生产消费模型. 1.创建maven项目2.kafka producer3.kafka consumer4.结 ...
- Kafka中非常值得学习的优秀设计
一.Kafka基础 消息系统的作用 应该大部份小伙伴都清楚,用机油装箱举个例子 所以消息系统就是如上图我们所说的仓库,能在中间过程作为缓存,并且实现解耦合的作用. 引入一个场景,我们知道中国移动,中国 ...
- Kafka 客户端实现逻辑分析
这里主要分析kafka 客户端实现 (代码分析以perl kafka实现为准) kafka客户端分为生产者和消费者,生产者发送消息,消费者获取消息. 在kafka协议里客户端通信中用到的最多的四个协议 ...
- 转:Kafka 客户端TimeoutException问题之坑
原文出自:http://www.jianshu.com/p/2db7abddb9e6 各种TimeoutException问题 会抛出org.apache.kafka.common.errors.Ti ...
随机推荐
- Django中模型类的定义
1.模型文件以及继承的类 2.ORM对应关系 一个class类,对应数据库一个表 一个class属性,对应一个字段 一个实例对象,对应一条数据记录 3.主键 可以自己定义主键列,如果自己不定义主键的话 ...
- golang sync.once done 热路径
sync.once 为什么会将done放在结构体第一个字段,就能够提升性能了? 我们先来看看sync.once的结构体: // Once is an object that will perform ...
- RTMP推流与B帧的关系
一.H264数据结构 一个原始的H.264 NALU 由一个接一个的 NALU 组成的,而它的功能分为两层,VCL(视频编码层)和 NAL(网络提取层). VCL:包括核心压缩引擎和块,宏块和片的语法 ...
- pandas基础--基本功能
pandas含有是数据分析工作变得更快更简单的高级数据结构和操作工具,是基于numpy构建的. 本章节的代码引入pandas约定为:import pandas as pd,另外import numpy ...
- set数据类型
SET 数据类型 是一个类似于 数组 的数据类型 特点 : 不接受重复的相同的数据 同样的 ...
- kettle从入门到精通 第五十八课 ETL之kettle HTTP post使用教程
1.今天群里有位朋友问我有没有关于调用http接口的kettle 示例,我下意识的去翻我的公众号推文,愣是没找到.果断开始撸. 2.本次演示流程通过调用接口[网易云音乐随机歌曲],然后解析返回的数据, ...
- kettle从入门到精通 第六十七课 ETL之kettle 再谈kettle阻塞,阻塞多个分支的多个步骤
场景:ETL沟通交流群内有小伙伴反馈,如何多个分支处理完毕之后记录下同步结果呢?或者是调用后续步骤.存储过程.三方接口等. 解决:使用步骤Blocking step进行阻塞处理即可. 1. 如下流程图 ...
- 如何解决Win10删除文件慢的办法
问题:最近使用KMS激活了一些工具,今天删除不需要的文件时发现删除文件很慢很慢,删除一个几百k的文件都很慢. 解决办法通过控制面板→管理工具→服务→找到该进程并设为禁用就OK了.
- mysql删除主键索引,删除索引语法
mysql删除主键索引,删除索引语法 ### Incorrect table definition; there can be only one auto column and it must be ...
- firewall-cmd设置NAT转换
配置ipv4转发 修改servera配置文件/etc/sysctl.conf ,修改参数为1 net.ipv4.ip_forward = 1 配置生效: sysctl -p 修改网卡的zone [ro ...