python异步消费kafka_Kafka(八)Python生产者和消费者API使用

单线程生产者#!/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()

执行效果

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值