翻譯:呂嘉偉
生產者(producer):發送消息的應用;
消息隊列(queue):保存隊列的緩衝區;
消費者(consumer):接收消息的應用。
廣播模式(fanout)
Rabbitmq的核心思想是生產者不會直接向隊列發送消息,事實上,生產者不需要關心消息最終發送到了哪個隊列中。
相反地,生產者只會將消息發送給exchange,exchange從生產者接受消息,然後轉發給隊列。Exchange知道如何處理收到的消息,要麼將它插入到某個特殊的隊列中,或是添加到多個隊列中,或是丟棄。這一切取決於的exchange的類型。
Exchange的類型主要有direct、topic、headers和fanout。可通過如下方式構造一個廣播的exchange:
channel.exchange_declare(exchange='logs',
type='fanout')
無名的exchange
在上面的代碼中我們聲明瞭一個“log”exchange,在應用中還存在默認的exchange,示例如下:
channel.basic_publish(exchange='',
routing_key='hello',
body=message)
該exchange爲一個空字符,這表明消息會發往hello隊列。
現在將生產者發送的消息傳遞給logexchange:
channel.basic_publish(exchange='logs',
routing_key='',
body=message)
對於廣播類型的消息,可能只會關心當前的消息,而不關心歷史消息。因此可以創建一個臨時的隊列,並且在消費者與隊列斷連時將隊列清除,示例如下:
# 聲明一個任意名稱的臨時隊列
result = channel.queue_declare(exclusive=True)
現在已經創建一個廣播類型exchange及一個臨時的隊列,此時由消費者將監聽的隊列與exchange進行綁定,示例如下:
channel.queue_bind(exchange='logs',
queue=result.method.queue)
生產者 emit_log.py
#!/usr/bin/env python
import pika
import sys
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='logs',
type='fanout')
message = ' '.join(sys.argv[1:]) or "info: Hello World!"
channel.basic_publish(exchange='logs',
routing_key='',
body=message)
print(" [x] Sent %r" % message)
connection.close()
如代碼中所示,在建立連接之後,我們聲明瞭exchange。這一步是必要的,因爲禁止將消息發給一個不存在的exchange。如果沒有隊列綁定到exchange上,消息會被丟棄。
消費者 receive_logs.py
#!/usr/bin/env python
import pika
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='localhost'))
channel = connection.channel()
channel.exchange_declare(exchange='logs',
type='fanout')
result = channel.queue_declare(exclusive=True)
queue_name = result.method.queue
channel.queue_bind(exchange='logs',
queue=queue_name)
print(' [*] Waiting for logs. To exit press CTRL+C')
def callback(ch, method, properties, body):
print(" [x] %r" % body)
channel.basic_consume(callback,
queue=queue_name,
no_ack=True)
channel.start_consuming()