使用python連接rabbitmq

使用python連接rabbitmq的時候,需要第三方庫 pika

pika 的安裝

......@ubunut: ~$ sudo pip3 install pika

此處,創建兩個py文件

  • send.py
#!/usr/bin/python3
# send.py

import pika

# 創建連接
con = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = con.channel()
# 聲明消息隊列 隊列名稱爲‘hello’
channel.queue_declare(queue='hello')
# 消息的生產者,exchange指定交換器, routing_key指定消息隊列, body要發送的消息
channel.basic_publish(exchange='', routing_key='hello', body='Hello World')

print(" [x] sent 'Hello World'")
# 關閉連接
con.close()
  • receive.py
#!/usr/bin/python3
# receive.py

import pika

con = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = con.channel()

# 多次使用queue_declare創建消息隊列的時候,如果消息隊列已經存在,則不創建新的
channel.queue_declare(queue='hello')

print("[*] Wating for messages To exit press Ctrl+C")


def callback(ch, method, properties, body):
    print('[x] Received {}'.format(body))
# 參數一: 消息隊列的名稱
# 參數二: 消息處理的回調函數
channel.basic_consume('hello', callback, auto_ack = True)
# 開始消費
channel.start_consuming()

如何保證消息隊列消息不丟失

  • 如果消費者在處理的時候出現異常,我們希望消息會自動轉發給其他消費者,在rabbitmq中有效確認機制,auto_ack參數(最近版本的pika,以前的版本是no_ack),默認是False。表示消息需要確認,這樣其中有消費者當機了,那就可以把這個消息,轉發給其他消費者.
    消費者收到消息,正常處理後,此時才通知隊列可以將消息從隊列裏面刪除;如果消費者掛掉,與server的鏈接通道會關閉或者tcp連接丟失,這時候server知道了這個情況,就會自動重發消息
#!/usr/bin/python3
# receive.py

import pika

con = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = con.channel()

# 多次使用queue_declare創建消息隊列的時候,如果消息隊列已經存在,則不創建新的
channel.queue_declare(queue='hello')

print("[*] Wating for messages To exit press Ctrl+C")


def callback(ch, method, properties, body):
    print('[x] Received {}'.format(body))
# 參數一: 消息隊列的名稱
# 參數二: 消息處理的回調函數
channel.basic_consume('hello', callback)
# 開始消費
channel.start_consuming()
  • 防止Server掛掉了: 1、將隊列保存;2、將消息持久化

在聲明隊列的時候,durable = True,這樣Server掛掉,隊列還在

# 要保證生產者和消費者生命的隊列一樣,都爲True或者同時爲False。durable(耐用)
channel.queue_declare(queue=‘hello‘,durable=True)   

在聲明交換機的時候,將消息進行持久化:delivery_mode = 2 (發送模式),這樣Server掛掉,消息還在
properties(屬性)

channel.basic_publish(exchange=‘‘,routing_key=‘hello‘,body=‘Hello World!‘,properties=pika.BasicProperties(delivery_mode=2,))

exchange 交換機的選擇

  • fanout 這種模式下,傳遞到 exchange 的消息將會轉發到所有與其綁定的 queue 上
  • direct 這種工作模式的原理是 消息發送至 exchange,exchange 根據 路由鍵(routing_key)轉發到相對應的 queue 上
  • topic 前面提到的direct規則是嚴格意義上的匹配,換言之Routing Key必須與Binding Key相匹配的時候纔將消息傳送給Queue,那麼topic這個規則就是模糊匹配,可以通過通配符滿足一部分規則就可以傳送

fanout 模式

  • 不需要指定 routing_key ,即使指定了也是無效。
  • 需要提前將 exchange 和 queue 綁定,一個 exchange 可以綁定多個 queue,一個queue可以綁定多個exchange。
  • 需要先啓動 訂閱者,此模式下的隊列是 consumer 隨機生成的,發佈者 僅僅發佈消息到 exchange ,由 exchange 轉發消息至 queue。
#!/usr/bin/python3
# send.py

import pika
import json
con = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = con.channel()
# 聲明exchange,由exchange指定消息在哪個隊列傳遞,如不存在,則創建。durable = True 代表exchange持久化存儲,False 非持久化存儲
channel.exchange_declare(exchange='python-test', durable=True, exchange_type='fanout')

for i in range(20):
    message = json.dumps({'OrdersId': '1000{}'.format(i)})
    # 向隊列插入數值 routing_key是隊列名。delivery_mode = 2 聲明消息在隊列中持久化,delivery_mod = 1 消息非持久化。routing_key 不需要配置
    channel.basic_publish(exchange='python-test', routing_key='', body=message, properties=pika.BasicProperties(delivery_mode = 2))
    print(message)
con.close()
#!/usr/bin/python3
# receive.py

import pika

con = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))

channel = con.channel()
# 創建臨時隊列,consumer關閉後,隊列自動刪除
result = channel.queue_declare(exclusive=True, queue='')

channel.exchange_declare(exchange='python-test', durable=True, exchange_type='fanout')
# 綁定exchange和隊列  exchange 使我們能夠確切地指定消息應該到哪個隊列去
channel.queue_bind(exchange = 'python-test', queue=result.method.queue)

print("[*] Wating for messages To exit press Ctrl+C")

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

direct 模式

  • 可以使用默認 exchange =’ ’ ,也可以自定義 exchange
  • 這種模式下不需要將 exchange 和 任何進行綁定,當然綁定也是可以的。可以將 exchange 和 queue ,routing_key 和 queue 進行綁定
  • 傳遞或接受消息時 需要 指定 routing_key
  • 需要先啓動 訂閱者,此模式下的隊列是 consumer 隨機生成的,發佈者 僅僅發佈消息到 exchange ,由 exchange 轉發消息至 queue。
#!/usr/bin/python3
# send.py

import pika
import json

con = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = con.channel()
channel.exchange_declare(exchange='python-test-2', durable=True, exchange_type='direct')
for i in range(20):
    message = json.dumps({'OrdersId': '1000{}'.format(i)})
    # 指定 routing_key。delivery_mode = 2 聲明消息在隊列中持久化,delivery_mod = 1 消息非持久化
    channel.basic_publish(exchange='python-test-2', routing_key='OrderId', body=message)
    print(message)
con.close()
#!/usr/bin/python3
# receive.py

import pika
con = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = con.channel()

result = channel.queue_declare(exclusive=True, queue='')

channel.exchange_declare(exchange='python-test-2', durable=True, exchange_type='direct')
channel.queue_bind(exchange = 'python-test-2', queue=result.method.queue, routing_key='OrderId')

print("[*] Wating for messages To exit press Ctrl+C")
def callback(ch, method, properties, body):
    ch.basic_ack(delivery_tag = method.delivery_tag)
    print(body.decode())
channel.basic_consume(result.method.queue, callback, auto_ack=False)
channel.start_consuming()

topic
python3 receive.py OrdersId OrderIds
python3 send.py

  • 這種模式和第二種模式差不多,exchange 也是通過 路由鍵 routing_key 來轉發消息到指定的 queue 。 不同點是 routing_key 使用正則表達式支持模糊匹配,但匹配規則又與常規的正則表達式不同,比如‘’#‘’是匹配全部,“*”是匹配一個詞。

  • 舉例:routing_key =“#orderid#”,意思是將消息轉發至所有 routing_key 包含 “orderid” 字符的隊列中

# !/usr/bin/python3
# send.py
import pika
import json

con = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = con.channel()

channel.exchange_declare(exchange='python-test-3', durable=True, exchange_type='topic')
for i in range(20):
    message = json.dumps({'OrdersId': '1000{}'.format(i)})
    channel.basic_publish(exchange='python-test-3', routing_key='OrdersId', body=message)
    print(message)

con.close()
# !/usr/bin/python3
# receive.py

import pika
import sys

con = pika.BlockingConnection(pika.ConnectionParameters(host='localhost'))
channel = con.channel()

result = channel.queue_declare(exclusive=True, queue='')
channel.exchange_declare(exchange='python-test-3', durable=True, exchange_type='topic')
binding_keys = sys.argv[1:]
print('-->',binding_keys)
if not binding_keys:
    print('------>')
    sys.exit(1)
for i in binding_keys:
    channel.queue_bind(exchange = 'python-test-3', queue=result.method.queue, routing_key=i)
print("[*] Wating for messages To exit press Ctrl+C")
def callback(ch, method, properties, body):
    ch.basic_ack(delivery_tag = method.delivery_tag)
    print(body.decode())

channel.basic_consume(result.method.queue, callback, auto_ack=False)
channel.start_consuming()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章