python kafka 多线程消费者&手动提交实例


Posted in Python onDecember 21, 2019

官方文档:https://kafka-python.readthedocs.io/en/master/apidoc/KafkaConsumer.html

import threading
 
import os
import sys
from kafka import KafkaConsumer, TopicPartition, OffsetAndMetadata
 
from consumers.db_util import *
from consumers.json_dispose import *
from collections import OrderedDict
 
 
threads = []
# col_dic, sql_dic = get()
 
 
class MyThread(threading.Thread):
  def __init__(self, thread_name, topic, partition):
    threading.Thread.__init__(self)
    self.thread_name = thread_name
    # self.keyName = keyName
    self.partition = partition
    self.topic = topic
 
  def run(self):
    print("Starting " + self.name)
    Consumer(self.thread_name, self.topic, self.partition)
 
  def stop(self):
    sys.exit()
 
 
def Consumer(thread_name, topic, partition):
  broker_list = '172.16.90.63:6667, 172.16.90.58:6667, 172.16.90.59:6667'
  '''
  fetch_min_bytes(int) - 服务器为获取请求而返回的最小数据量,否则请等待
  fetch_max_wait_ms(int) - 如果没有足够的数据立即满足fetch_min_bytes给出的要求,服务器在回应提取请求之前将阻塞的最大时间量(以毫秒为单位)
  fetch_max_bytes(int) - 服务器应为获取请求返回的最大数据量。这不是绝对最大值,如果获取的第一个非空分区中的第一条消息大于此值,
              则仍将返回消息以确保消费者可以取得进展。注意:使用者并行执行对多个代理的提取,因此内存使用将取决于包含该主题分区的代理的数量。
              支持的Kafka版本> = 0.10.1.0。默认值:52428800(50 MB)。
  enable_auto_commit(bool) - 如果为True,则消费者的偏移量将在后台定期提交。默认值:True。
  max_poll_records(int) - 单次调用中返回的最大记录数poll()。默认值:500
  max_poll_interval_ms(int) - poll()使用使用者组管理时的调用之间的最大延迟 。这为消费者在获取更多记录之前可以闲置的时间量设置了上限。
                如果 poll()在此超时到期之前未调用,则认为使用者失败,并且该组将重新平衡以便将分区重新分配给另一个成员。默认300000
  '''
  consumer = KafkaConsumer(bootstrap_servers=broker_list,
               group_id="xiaofesi",
               client_id=thread_name,
               enable_auto_commit=False,
               fetch_min_bytes=1024*1024,#1M
               # fetch_max_bytes=1024 * 1024 * 1024 * 10,
               fetch_max_wait_ms=60000,#30s
               request_timeout_ms=305000,
               # consumer_timeout_ms=1,
               # max_poll_records=5000,
               # max_poll_interval_ms=60000 无该参数
               )
  #查出数据库上次保存的offset,此offset已经是上次消费最后一条的offset的offset+1,也就是这次消费的起始位
  dic = get_kafka(topic, partition)
  tp = TopicPartition(topic, partition)
  print(thread_name, tp, dic['offset'])
  #分配该消费者的TopicPartition,也就是topic和partition,根据参数,我是三个消费者,三个线程,每个线程消费者消费一个分区
  consumer.assign([tp])
  #重置此消费者消费的起始位
  consumer.seek(tp, dic['offset'])
  print("程序首次运行\t线程:", thread_name, "分区:", partition, "偏移量:", dic['offset'], "\t开始消费...")
  num=0 #记录该消费者消费次数
  # end_offset = consumer.end_offsets([tp])[tp]
  # print(end_offset)
  while True:
    args = OrderedDict()
    msg = consumer.poll(timeout_ms=60000)
    end_offset = consumer.end_offsets([tp])[tp]
    print('已保存的偏移量', consumer.committed(tp),'最新偏移量,',end_offset)
    if len(msg) > 0:
      print("线程:", thread_name, "分区:", partition, "最大偏移量:", end_offset, "有无数据,", len(msg))
      lines=0
      for data in msg.values():
        for line in data:
          lines+=1
          line = eval(line.value.decode('utf-8'))
          '''
          do something
          '''
      # 线程此批次消息条数
      print(thread_name,"lines",lines)
      #数据保存至数据库
      is_succeed = save_to_db(args, thread_name)
      if is_succeed:
        #更新自己保存在数据库中的各topic, partition的偏移量
        is_succeed1 = update_offset(topic, partition, end_offset)
        #手动提交偏移量 offsets格式:{TopicPartition:OffsetAndMetadata(offset_num,None)}
        consumer.commit(offsets={tp:(OffsetAndMetadata(end_offset,None))})
        print(thread_name,"to db suss",num+1)
        if is_succeed1 == 0:
          #系统退出?这个还没试
          os.exit()
          '''
          sys.exit()  只能退出该线程,也就是说其它两个线程正常运行,主程序不退出
          '''
      else:
        os.exit()
    else:
      print(thread_name,'没有数据')
    num+=1
    print(thread_name,"第",num,"次")
 
 
if __name__ == '__main__':
  try:
    t1 = MyThread("Thread-0", "test", 0)
    threads.append(t1)
    t2 = MyThread("Thread-1", "test", 1)
    threads.append(t2)
    t3 = MyThread("Thread-2", "test", 2)
    threads.append(t3)
 
    for t in threads:
      t.start()
 
    for t in threads:
      t.join()
 
    print("exit program with 0")
  except:
    print("Error: failed to run consumer program")

以上这篇python kafka 多线程消费者&手动提交实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python类的用法实例浅析
May 27 Python
Python中unittest模块做UT(单元测试)使用实例
Jun 12 Python
Linux 发邮件磁盘空间监控(python)
Apr 23 Python
Windows下Python2与Python3两个版本共存的方法详解
Feb 12 Python
python print 按逗号或空格分隔的方法
May 02 Python
PyQt5 pyqt多线程操作入门
May 05 Python
python实现批量解析邮件并下载附件
Jun 19 Python
vue.js实现输入框输入值内容实时响应变化示例
Jul 07 Python
spark dataframe 将一列展开,把该列所有值都变成新列的方法
Jan 29 Python
详解python读取image
Apr 03 Python
python实现坦克大战游戏 附详细注释
Mar 27 Python
python FTP编程基础入门
Feb 27 Python
Python序列类型的打包和解包实例
Dec 21 #Python
Python 使用threading+Queue实现线程池示例
Dec 21 #Python
Python CSV文件模块的使用案例分析
Dec 21 #Python
python实现的分析并统计nginx日志数据功能示例
Dec 21 #Python
Python数据持久化存储实现方法分析
Dec 21 #Python
python cv2截取不规则区域图片实例
Dec 21 #Python
Python lxml模块的基本使用方法分析
Dec 21 #Python
You might like
跟我学小偷程序之成功偷取首页(第三天)
2006/10/09 PHP
PHP输出当前进程所有变量/常量/模块/函数/类的示例
2013/11/07 PHP
C#静态方法与非静态方法实例分析
2014/09/22 PHP
JQuery最佳实践之精妙的自定义事件
2010/08/11 Javascript
jquery判断checkbox(复选框)是否被选中的代码
2010/10/20 Javascript
jquery星级插件、支持页面中多次使用
2012/03/25 Javascript
jquery showModelDialog的使用方法示例详解
2013/11/19 Javascript
js右下角弹出提示框示例代码
2016/01/12 Javascript
js仿百度音乐全选操作
2017/01/13 Javascript
Node.JS利用PhantomJs抓取网页入门教程
2017/05/19 Javascript
Vue.js结合Ueditor富文本编辑器的实例代码
2017/07/11 Javascript
JQuery选中select组件被选中的值方法
2018/03/08 jQuery
深入理解JS中Number(),parseInt(),parseFloat()三者比较
2018/08/24 Javascript
JavaScript常见事件处理程序实例总结
2019/01/05 Javascript
小程序getLocation需要在app.json中声明permission字段
2019/04/04 Javascript
vue路由对不同界面进行传参及跳转的总结
2019/04/20 Javascript
Vue.js项目实战之多语种网站的功能实现(租车)
2019/08/07 Javascript
微信小程序自定义tabBar的踩坑实践记录
2020/11/06 Javascript
JS相册图片抖动放大展示效果的示例代码
2021/01/29 Javascript
详解Vite的新体验
2021/02/22 Javascript
[44:10]2018DOTA2亚洲邀请赛 4.5 淘汰赛 EG vs VP 第一场
2018/04/06 DOTA
python 类详解及简单实例
2017/03/24 Python
详解python中的文件与目录操作
2017/07/11 Python
Python 20行简单实现有道在线翻译的详解
2019/05/15 Python
Python3批量移动指定文件到指定文件夹方法示例
2019/09/02 Python
如何创建一个Flask项目并进行简单配置
2020/11/18 Python
如何启动时不需输入用户名与密码
2014/05/09 面试题
给定一个时间点,希望得到其他时间点
2013/11/07 面试题
党员剖析材料范文
2014/09/30 职场文书
安全隐患整改报告
2014/11/06 职场文书
2014年妇产科工作总结
2014/12/08 职场文书
保研专家推荐信范文
2015/03/25 职场文书
中标通知书格式
2015/04/17 职场文书
幼儿园万圣节活动总结
2015/05/05 职场文书
最美乡村教师观后感
2015/06/11 职场文书
Goland使用Go Modules创建/管理项目的操作
2021/05/06 Golang