Python使用RocketMQ(訊息佇列)

Circle_Wang發表於2024-03-14

  訊息佇列在日常開發中比較常用的開發中介軟體,每家大廠一般都會具有自己的訊息佇列伺服器。本文主要講述Python中如何使用RocketMQ的相關SDK。希望大家在閱讀本文前可以先了解一下RocketMQ的基本知識

  使用 pip install rocketmq -i https://pypi.tuna.tsinghua.edu.cn/simple 可以下載到rocketmq所需要的包(需要注意到的是RocketMQ是基於java寫的C/S架構服務,因此我們這安裝的僅僅是客戶端,也就是能夠連線到遠端的RocketMQ伺服器)。

1、消費者

  看了前面“基本知識”之後,我們知道消費者消費資料的方式有兩種:1、主動呼叫從Broker伺服器拉訊息(pull)來使用,主動權在於程式。2、被動接收Broker伺服器推送(push)的訊息,主動權在Broker伺服器,一般是Brocker接收到了訊息就會可以傳導給消費者(也就是我們應用)。使用pull模式時,需要自己編寫邏輯來迴圈呼叫pull方法,並且處理可能出現的異常情況,例如網路問題或者佇列暫時沒有訊息可供消費的情況。因此我們一般是使用push模式,被動的接受Borker的資料並這是回撥函式(接受訊息後對訊息的處理函式)返回給Borker這條訊息消費情況。

  消費資料我們需要明確,我們能夠接收到資料,需要有幾個必要的步驟:

  1. 建立消費者物件,建立時需要指明 消費組名稱
  2. 與RocketMQ的伺服器建立連線。
  3. 連線後需要進行身份驗證,可以選擇賬戶密碼驗證
  4. 指定消費者訂閱哪個Topic的訊息,並且指定訊息的回撥函式(回撥函式需要返回消費狀態:CONSUME_SUCCESS,RECONSUME_LATER)

  完成上述操作之後,我們就可以使用消費者進行消費了,下面給出了兩種不同消費型別的消費者程式碼模板。

1.1、Push消費者

import time
from rocketmq.client import PushConsumer, ConsumeStatus


# 設定回撥函式來處理訊息
def call_back(msg):
    # 需要使用msg.body來獲取內容
    print(f"Received message: {msg.body.decode('utf-8')}")
    
    # 在這裡編寫您的訊息處理邏輯
    # ...
    # 如果訊息處理成功,返回CONSUME_SUCCESS
    # 如果訊息處理失敗,返回RECONSUME_LATER
    return ConsumeStatus.CONSUME_SUCCESS


# 初始化消費者
consumer = PushConsumer('your_consumer_group')
# 使用 IP 和埠名稱設定伺服器地址
consumer.set_name_server_address("127.0.0.1:9887")
consumer.set_session_credentials("access_key", "secret_key", 'authChannel')  # 完成設定驗證
# 訂閱Topic和過濾資訊
consumer.subscribe('topic名稱', call_back, '*')

# 啟動消費者, 此時會啟動新的現成, 消費者將一直執行, 直到主程序被停止
consumer.start()

# 在實際應用中,您可能需要新增邏輯來優雅地關閉消費者
try:
    while True:
        time.sleep(1000)
except KeyboardInterrupt:
    pass
# 停止消費者
consumer.shutdown()

  我們需要注意到的是consumer.start()會開啟新的執行緒持續監聽Brocker是否推送了新的訊息,這個消費執行緒需要一直被進行,因此這裡使用了while True迴圈保證主程序不結束(消費執行緒也就不會被kill,就算消費資料時出現了異常也會繼續監聽)。

1.2、Pull消費者

  pull消費者與push消費者不同的是,不需要一直開啟一個執行緒去監聽,而是由程式作為主動方主動去獲取未消費資料

from rocketmq.client import PullConsumer

# 初始化消費者(需要傳入消費組名稱)
consumer = PullConsumer('your_consumer_group')

# 使用 IP 和埠名稱設定伺服器地址
consumer.set_name_server_address("127.0.0.1:9887")
consumer.set_session_credentials("access_key", "secret_key", 'authChannel')  # 完成設定驗證
# 啟動消費者
consumer.start()
# 從topic中拉取還未被消費的資料(consumer.pull返回的是可迭代物件)
for msg in consumer.pull('YOUR-TOPIC'):
  # 消費資料的邏輯在這裡 print(msg.id, msg.body) # 停止消費者 consumer.shutdown()

  對於消費者需要注意的是:一個同名消費組只能監聽一個topic,因此如果想要使用多個topic的訊息,需要建立不同名的消費者。

2、生產者

  對於生產者,其實與消費者類似也需要那四步必需步驟。只不過傳送的資訊需要使用Message物件來指定對應的topic,還需要注意的是傳遞的資料必須是字串,因此我們傳遞物件資料時需要用json.dumps轉換一下。

import json
from rocketmq.client import Producer
from rocketmq.client import Message

# 初始化生產者
producer = Producer('your_producer_group')
# 設定NameServer地址
producer.set_namesrv_addr('nameserver的address')
producer.set_session_credentials("access_key", "secret_key", 'authChannel')  # 完成設定驗證
# 啟動生產者
producer.start()

# 構建訊息(需要將訊息傳送到指定Topic)
message = Message('your_topic')
# 設定訊息內容(注意訊息只能是字串)
msg_body = {"id":"test_id","name":"test_name","message":"test_message"}
message.set_body(json.dumps(msg_body).encode('utf-8'))
# 可以設定其他屬性,如Tags、Keys等
# message.set_tags('your_tag')
# message.set_keys('your_key')

try:
    # 傳送訊息(此處就會傳送訊息到RocketMQ伺服器)
    ret = producer.send(message)
    # 列印傳送結果
    if ret.status == Message.SendStatus.OK:
        print("傳送成功")
    else:
        print(f"傳送失敗, 訊息狀態: {ret.status}")
except Exception as e:
    # 處理傳送過程中可能出現的異常
    print(f"Send message failed, exception: {e}")
finally:
    # 停止生產者
    producer.shutdown()

  同一個生產者物件可以傳送多個Message物件,也就是說同一個生產者物件可以向多個topic傳送資訊。需要注意的是Message物件被髮送後,它通常不會被重新使用來傳送其他訊息,如果你想對同一個topic傳送多個資料需要建立新的Message物件。

  

相關文章