背景
项目中有个需求就是采集数据通过算法分析后推送到平台,算法是独立的组件,采集也是独立的组件,平台是第三方平台,于是我选择采用消息中间件作为中间传输通信的工具,Rocketmq+python的方案。
踩坑记录
1、编写demo
生产者:
import json
from rocketmq.client import Producer, Message
producer = Producer('PID')
producer.set_namesrv_addr('localhost:9876')
producer.start()
msg = Message('test')
for count in range(1, 1000,1):
msg_body = {'id': count}
body = json.dumps(msg_body).encode('utf-8')
msg.set_body(body)
ret = producer.send_sync(msg)
print(f'status:{ret.status}') # 0表示OK
print(f'msg_id:{ret.msg_id}') # 消息id,同消费者获取到的消息id
print(f'offset:{ret.offset}') # 偏移量,默认从0开始,1,2。。。
producer.shutdown()
消费者:
import time
from rocketmq.client import PushConsumer,PullConsumer
def callback(msg):
print(msg.topic,msg.id,(msg.body).decode('utf-8'))
return PullConsumer
consumer = PushConsumer('CID')
consumer.set_namesrv_addr('localhost:9876')
consumer.subscribe('test',callback)
consumer.start()
while True:
time.sleep(3600)
consumer.shutdown()
分别启动生产者和消费者程序,验证成功,生产者生产消息后消费者会订阅test主题消费掉消息
2、编写业务代码
开始写业务代码,添加完业务代码后,再次启动生产者和消费者程序,出现了一个问题,由于算法分析的代码很耗GPU、CPU,而rocketmq貌似有一个机制,在设定的时间内某个消息没有消费掉就会启动重发机制,会出现重复消费的现象,于是乎现在的问题就变成解决rocketmq重复消费的问题
3、解决rocketmq重复消费的问题
由于这里rocke使用的是python语言的客户端,可以参考的例子很少,只能自己摸石头过河了。 根据rocketmq的设计原理,有一个组的概念,通俗一点讲,就是如果将消费者放到一个组里,那么这个组里的某条消息被组内一个消费者消费掉了,其他消费者就不会再去消费这个消息,这很符合我们的业务需求,通过并发处理消息提升算法处理的能力并消除重复消费。 于是乎,我在消费者程序中增加了组的概念,大致代码如下:
def callback(msg):
data = analysis(msg)
push_json = json.loads(data)
resultmsg = Message('result')
resultmsg.set_body(data)
producer.send_sync(resultmsg)
return 0
def messageThread():
consumer = PushConsumer('CID')
consumer.set_namesrv_addr('localhost:9876')
consumer.set_group('testGP')
consumer.set_thread_count(2)
consumer.subscribe('test', callback)
consumer.start()
while True:
time.sleep(2)
consumer.shutdown()
4、优化整个程序
为了提升吞吐量同时提升性能,我在三台虚拟机上同时跑了同样的消费者程序,测试了多次,发现没有重复消息,同时由于rocketmq自身配置了负载均衡的算法,三台虚机上同一个组testGP中消费消息基本上达到了均衡,至此,初次用python语言写rocketmq的消费程序完成踩坑携手。
总结
语言是想通的,要有一颗敢于尝试的勇敢的心,这次业务需求在技术选型上,我有两套方案,一个是Java方案一个就是这个python方案,很多人支持我用Java方案,由于时间紧要求高,python方案大家都不熟悉,是一种冒险,但是,我是偏向于选择python方案的,因为本身算法是python写的,结合起来比较容易,所以我选择了尝试,不过确实是有风险,还好最终顺利交付,还是小有成就感的。
我们要善于去理解组件的原理,就比如说rocketmq,它的底层设计原理是怎样的,他的重复消费是怎么处理的,将这些原理理解清楚后其实技术实现就不是一个太难的问题了。