设为首页 收藏本站
查看: 1096|回复: 0

[经验分享] Kafka(八)Python生产者和消费者API使用

[复制链接]

尚未签到

发表于 2019-1-31 09:45:36 | 显示全部楼层 |阅读模式
  单线程生产者
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import random
import sys
from kafka import KafkaProducer
from kafka.client import log
import time
import json
__metaclass__ = type

class Producer:
    def __init__(self, KafkaServer='127.0.0.1', KafkaPort='9092', ClientId="Procucer01", Topic='Test'):
        """
        用于设置生产者配置信息,这些配置项可以从源码中找到,下面为必要参数。
        :param KafkaServer: kafka服务器IP
        :param KafkaPort: kafka工作端口
        :param ClientId: 生产者名称
        :param Topic: 主题
        """
        self._bootstrap_server = '{host}:{port}'.format(host=KafkaServer, port=KafkaPort)
        self._topic = Topic
        self._clientId = ClientId
        """
        初始化一个生产者实例,生产者是线程安全的,多个线程共享一个生产者实例效率比每个线程都使用一个生产者实例要高
        acks: 消费者只能消费被提交的,而只有消息在所有副本中都有了才算提交,生产者发送了消息是否要等待所有副本都同步了该消息呢?这个值就是控制这个的。默认是1,表示只要该分区的Leader副本成功写入日志就返回。
              0表示生产者无需等待,发送完就返回;all是所有副本都写入该消息才返回。 all可靠性最高但是效率最低,0效率最高但是可靠性最低,所以一般用1。
        retries: 表示请求重试次数,默认是0,上面的acks配置请求完成的标准,如果请求失败,生产者将会自动重试,如果配置为0则不重试。但是如果重试则有可能发生重复发送消息。
        key_serializer: 键的序列化器,默认不设置,采用字节码
        value_serializer: 值得序列化器,默认不设置,采用字节码,因为可以发送单一字符,也可以发送键值型消息
        """
        try:
            self._producer = KafkaProducer(bootstrap_servers=self._bootstrap_server, client_id=self._clientId, acks=1,
                                           value_serializer=lambda m: json.dumps(m).encode('utf-8'))
        except Exception as err:
            print err.message
    def _TIMESTAMP(self):
        t = time.time()
        return int((round(t * 1000)))
    # 时间戳转换为普通时间
    def getNormalTime(self, temp_timeStamp, timeSize=10):
        timeStamp = temp_timeStamp
        if timeSize == 13:
            timeStamp = int(temp_timeStamp / 1000)
        timeArray = time.localtime(timeStamp)
        otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
        return otherStyleTime
    # 发送成功的回调函数
    def _on_send_success(self, record_metadata):
        print "Topic: %s Partition: %d Offset: %s" % (record_metadata.topic, record_metadata.partition, record_metadata.offset)
    # 发送失败的回调函数
    def _on_send_error(self, excp):
        log.error('I am an errback', exc_info=excp)
    def sendMsg(self, msg, partition=None):
        """
        发送消息
        :param msg: 消息
        :param partition: 分区也可以不指定
        :return:
        """
        if not msg:
            print "消息不能为空。"
            return None
        # 发送的消息必须是序列化后的,或者是字节
        message = json.dumps(msg, encoding='utf-8', ensure_ascii=False)
        try:
            TIMESTAMP = self._TIMESTAMP()
            # 发送数据,异步方式,调用之后立即返回,因为这里其实是发送到缓冲区,所以你可以多次调用,然后一起flush出去。
            self._producer.send(self._topic, partition=partition, key=self._clientId, value=message, timestamp_ms=TIMESTAMP).add_callback(self._on_send_success).add_errback(self._on_send_error)
            # 下面的 flush是阻塞的,只有flush才会真正通过网络把缓冲区的数据发送到对端,如果不调用flush,则等到时间或者缓冲区满了就会发送。
            self._producer.flush()
            print self.getNormalTime(TIMESTAMP, timeSize=13) + " send msg: " + message
        except Exception as err:
            print err

def main():
    p = Producer(KafkaServer="172.16.48.171", KafkaPort="9092", Topic='AAA')
    for i in range(10):
        time.sleep(1)
        closePrice = random.randint(1, 500)
        msg = {
            "股票代码": 60000 + i,
            "昨日收盘价": closePrice,
            "今日开盘价": 0,
            "今日收盘价": 0,
        }
        p.sendMsg(msg)

if __name__ == "__main__":
    try:
        main()
    finally:
        sys.exit()  消费者
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from kafka import KafkaConsumer
import json
__metaclass__ = type

class Consumer:
    def __init__(self, KafkaServer='127.0.0.1', KafkaPort='9092', GroupID='TestGroup', ClientId="Test", Topic='Test'):
        """
        用于设置消费者配置信息,这些配置项可以从源码中找到,下面为必要参数。
        :param KafkaServer: kafka服务器IP
        :param KafkaPort: kafka工作端口
        :param GroupID: 消费者组ID
        :param ClientId: 消费者名称
        :param Topic: 主题
        """
        self._bootstrap_server = '{host}:{port}'.format(host=KafkaServer, port=KafkaPort)
        self._groupId = GroupID
        self._topic = Topic
        self._clientId = ClientId
    def consumeMsg(self):
        try:
            """
            初始化一个消费者实例,消费者不是线程安全的,所以建议一个线程实现一个消费者,而不是一个消费者让多个线程共享
            下面这些是可选参数,可以在初始化KafkaConsumer实例的时候传递进去
            enable_auto_commit 是否自动提交,默认是true
            auto_commit_interval_ms 自动提交间隔毫秒数
            """
            consumer = KafkaConsumer(self._topic, bootstrap_servers=self._bootstrap_server,
                                     group_id=self._groupId, client_id=self._clientId, enable_auto_commit=True,
                                     auto_commit_interval_ms=5000, value_deserializer=lambda m: json.loads(m.decode('utf-8')))
            """
            这里不需要显示的调用订阅函数,在初始化KafkaConsumer对象的时候已经指定了主题,如果主题字段不为空则会自动调用订阅函数,至于
            这个线程消费哪个分区则是自动分配的。如果你希望手动指定分区则就需要使用 assign() 函数,并且在初始的时候不输入主题。
            """
            # consumer.subscribe(self._topicList)
            # 返回一个集合
            print "当前消费的分区为:", consumer.partitions_for_topic(self._topic)
            print "当前订阅的主题为:", consumer.subscription()
            while True:
                for msg in consumer:
                    if msg:
                        print "Topic: %s Partition: %d Offset: %s Key: %s Message: %s " % (msg.topic, msg.partition, msg.offset, msg.key, msg.value)
        except Exception as err:
            print err

def main():
    try:
        c = Consumer(KafkaServer='172.16.48.171', Topic='AAA')
        c.consumeMsg()
    except Exception as err:
        print err.message

if __name__ == "__main__":
    try:
        main()
    finally:
        sys.exit()  执行效果






运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-669903-1-1.html 上篇帖子: Kafka设计解析(三):Kafka High Availability (下) 下篇帖子: kafka 基本原理二
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表