Python與RabbitMQ

Demo

消費者:

# 消費者
import pika

# 連接
# auth info
auth = pika.PlainCredentials('guest', 'guest')  # auth info
connection = pika.BlockingConnection(pika.ConnectionParameters(
    '127.0.0.1', 5672, '/', auth))  # connect to rabbit
channel = connection.channel()  # create channel

# 申明隊列
channel.queue_declare(queue='hello', durable=True, passive=True)


def callback(ch, method, properties, body):
# ack
    ch.basic_ack(delivery_tag=method.delivery_tag)
    print(body.decode())


# no_ack 設置成 False,在調用callback函數時,未收到確認標識,消息會重回隊列
# True,無論調用callback成功與否,消息都被消費掉
channel.basic_consume("hello", callback,
                      False)
channel.start_consuming()

生產者:

# 生產者
import pika

# 連接
# auth info
auth = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters(
    '127.0.0.1', 5672, '/', auth))  # connect to rabbit
channel = connection.channel()

"""
MQ默認建立的是臨時 queue 和 exchange,如果不聲明持久化,一旦 rabbitmq 掛掉,queue、exchange 將會全部丟失
所以一般在創建 queue 或者 exchange 的時候會聲明 持久化
"""
# 聲明消息隊列,消息將在這個隊列傳遞,如不存在,則創建,durable = True爲持久化
channel.queue_declare(queue='hello')
"""
雖然 exchange 和 queue 都申明瞭持久化,但如果消息只存在內存裏rabbitmq 重啓後
內存裏的東西還是會丟失。所以必須聲明消息也是持久化,從內存轉存到硬盤。
 properties=pika.BasicProperties(delivery_mode = 2))
"""
# 發送消息
channel.basic_publish(exchange='',
                      routing_key='hello',
                      body='Flash22',
                      properties=pika.BasicProperties(delivery_mode=2))  # body是msg內容
connection.close()

消息持久化

一條消息進行持久化具體可以分爲4步:

  • queue持久化
  • exchange 持久化
  • 消息持久化
  • ack機制

 代碼分別如下:

queue持久化

# durable = True 代表消息隊列持久化存儲,False 非持久化存儲
result = channel.queue_declare(queue = 'hello',durable = True)

exchange 持久化

# durable = True 代表exchange持久化存儲,False 非持久化存儲
channel.exchange_declare(exchange = 'hello', durable = True)

注意:如果已存在一個非持久化的 queue 或 exchange ,執行上述代碼會報錯,因爲當前狀態不能更改 queue 或 exchange 存儲屬性,需要刪除重建。如果 queue 和 exchange 中一個聲明瞭持久化,另一個沒有聲明持久化,則不允許綁定。 

消息持久化

# 向隊列插入數值 routing_key是隊列名。delivery_mode = 2 聲明消息在隊列中持久化,delivery_mod = 1 消息非持久化
    channel.basic_publish(exchange = '',routing_key = 'hello',body = message,
                          properties=pika.BasicProperties(delivery_mode = 2))

ack機制

    消費者(consumer)調用callback函數時,會存在處理消息失敗的風險,如果處理失敗,則消息丟失。但是也可以選擇消費者處理失敗時,將消息回退給 rabbitmq ,重新再被消費者消費,這個時候需要設置確認標識。

# 回調函數
def callback(ch, method, properties, body):
#ack確認
    ch.basic_ack(delivery_tag=method.delivery_tag)
    print(body.decode())


# no_ack 設置成 False,在調用callback函數時,未收到確認標識,消息會重回隊列
# True,無論調用callback成功與否,消息都被消費掉
channel.basic_consume("hello", callback,
                      auto_ack=False)

RabbitMQ基礎相關:https://blog.csdn.net/qq_37598011/article/details/87869792

fanout、direct具體實現

fanout:它會把所有發送到該交換器的消息路由到所有與該交換器綁定的隊列中。

消費者:

import pika

# 連接
# auth info
auth = pika.PlainCredentials('guest', 'guest')  # auth info
connection = pika.BlockingConnection(pika.ConnectionParameters(
    '127.0.0.1', 5672, '/', auth))  # connect to rabbit
channel = connection.channel()  # create channel

# 創建臨時隊列,consumer關閉後,隊列自動刪除
result = channel.queue_declare('', exclusive=True)
# 聲明exchange,由exchange指定消息在哪個隊列傳遞,如不存在,則創建。durable = True 代表exchange持久化存儲,False 非持久化存儲
channel.exchange_declare(exchange='hello_fanout', durable=True, exchange_type='fanout')
# 綁定exchange和隊列  exchange 使我們能夠確切地指定消息應該到哪個隊列去
channel.queue_bind(exchange='hello_fanout', queue=result.method.queue)


# 定義一個回調函數來處理消息隊列中的消息,這裏是打印出來
def callback(ch, method, properties, body):
    ch.basic_ack(delivery_tag=method.delivery_tag)
    print(body.decode())


channel.basic_consume(result.method.queue, callback,
                      # 設置成 False,在調用callback函數時,未收到確認標識,消息會重回隊列。True,無論調用callback成功與否,消息都被消費掉
                      False)
channel.start_consuming()

生產者:

import json

import pika

# auth info
auth = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters(
    '127.0.0.1', 5672, '/', auth))  # connect to rabbit
channel = connection.channel()

# 聲明exchange,由exchange指定消息在哪個隊列傳遞,如不存在,則創建。durable = True 代表exchange持久化存儲,False 非持久化存儲
channel.exchange_declare(exchange='hello_fanout', durable=True, exchange_type='fanout')
for i in range(10):
    message = json.dumps({'OrderId': i})
    # 向隊列插入數值 routing_key是隊列名。delivery_mode = 2 聲明消息在隊列中持久化,delivery_mod = 1 消息非持久化。routing_key 不需要配置
    channel.basic_publish(exchange='hello_fanout', routing_key='', body=message,
                          properties=pika.BasicProperties(delivery_mode=2))
    print(message)
connection.close()

direct:direct 類型的交換器它會把消息路由到那些 BindingKey 和 RoutingKey 完全匹配的隊列中。

生產者:

import json

import pika

# auth info
auth = pika.PlainCredentials('guest', 'guest')
connection = pika.BlockingConnection(pika.ConnectionParameters(
    '127.0.0.1', 5672, '/', auth))  # connect to rabbit
channel = connection.channel()

# 聲明exchange,由exchange指定消息在哪個隊列傳遞,如不存在,則創建
# durable = True 代表exchange持久化存儲,False 非持久化存儲
channel.exchange_declare(exchange='direct_producer', durable=True, exchange_type='direct')

for i in range(10):
    message = json.dumps({'ProducerId': i})
    # 指定 routing_key。delivery_mode = 2 聲明消息在隊列中持久化,delivery_mod = 1 消息非持久化
    channel.basic_publish(exchange='direct_producer', routing_key='routingKey1', body=message,
                          properties=pika.BasicProperties(delivery_mode=2))
    print(message)
connection.close()

消費者:

import pika

# 連接
# auth info
auth = pika.PlainCredentials('guest', 'guest')  # auth info
connection = pika.BlockingConnection(pika.ConnectionParameters(
    '127.0.0.1', 5672, '/', auth))  # connect to rabbit
channel = connection.channel()  # create channel

# 創建臨時隊列,consumer關閉後,隊列自動刪除
result = channel.queue_declare('', exclusive=True)
# 聲明exchange,由exchange指定消息在哪個隊列傳遞,如不存在,則創建。durable = True 代表exchange持久化存儲,False 非持久化存儲
channel.exchange_declare(exchange='direct_producer', durable=True, exchange_type='direct')
# 綁定exchange和隊列  exchange 使我們能夠確切地指定消息應該到哪個隊列去
channel.queue_bind(exchange='direct_producer', queue=result.method.queue, routing_key='routingKey1')


# 定義一個回調函數來處理消息隊列中的消息,這裏是打印出來
def callback(ch, method, properties, body):
    ch.basic_ack(delivery_tag=method.delivery_tag)
    print(body.decode())


# channel.basic_qos(prefetch_count=1)
channel.basic_consume(result.method.queue, callback,
                      # 設置成 False,在調用callback函數時,未收到確認標識,消息會重回隊列。True,無論調用callback成功與否,消息都被消費掉
                      False)
channel.start_consuming()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章