RabbitMQ Python 入門教程之HelloWorld

你好,世界

介紹

RabbitMQ是消息代理: 它接收並轉發信息。舉個例子: 小明從淘寶買了商品,配送員將快遞投遞到了快遞櫃, 小明再根據取件碼去快遞櫃取快遞。快遞櫃就相當於消息隊列,快遞員是生產者,小明是消費者。

  • 生產者意味着發送, 所以發送信息的程序是生產者(Producer)。

    img

  • 儘管消息流經RabbitMQ和您的應用程序之中,但它們只能存儲在隊列之中, 甲隊列僅由主機的存儲器和磁盤限制和約束, 它本質上是一個大的消息緩衝器。許多生產者可以發送消息到同一個隊列中,許多消費者可以嘗試從一個隊列中接收數據, 表示隊列的方式。

    img

  • 消費與接收有相似的含義。消費者是一個程序,主要是等待接收信息。

    img

生產者,消費者,消息隊列不必位於同一主機上。一個應用程序既可以是消費者,也可以是生產者。

你好, 世界!

本部分內容中, 使用python編寫兩個小程序, 分別實現生產者和消費者。生產者進行數據發送,消費者進行數據接收並將其打印出來。

如圖, P是生產者, 紅色矩形相等於消息隊列, C是消費者。 生產者將hello 發送到隊列中, 消費者從隊列中接收hello

img

RabbitMQ庫

RabbitMQ使用多種協議。本教程使用AMQP 0-9-1,這是一種開放的通用消息傳遞協議。RabbitMQ有許多不同語言的客戶。在本教程系列中,我們將使用Pika 1.0.0,這是RabbitMQ團隊推薦的Python客戶端。要安裝它,您可以使用 pip包管理工具安裝:

python -m pip install pika --upgrade

發送

  • 我們第一個程序send.py需要向隊列發送一條消息。需要做的第一件事是與RabbitMQ服務器建立連接。前提你已經安裝了RabbitMQ, 如果沒有安裝的話,可以參考我這篇博客使用Docker安裝RabbitMQ
from pika import BlockingConnection, ConnectionParameters

# RabbitMQ連接參數,基本有默認值
parameters = ConnectionParameters(
    host='localhost',
    # port=_DEFAULT,
    # virtual_host=_DEFAULT,
    # credentials=_DEFAULT,
    # channel_max=_DEFAULT,
    # frame_max=_DEFAULT,
    # heartbeat=_DEFAULT,
    # ssl_options=_DEFAULT,
    # connection_attempts=_DEFAULT,
    # retry_delay=_DEFAULT,
    # socket_timeout=_DEFAULT,
    # stack_timeout=_DEFAULT,
    # locale=_DEFAULT,
    # blocked_connection_timeout=_DEFAULT,
    # client_properties=_DEFAULT,
    # tcp_options=_DEFAULT,
)
connection = BlockingConnection(parameters=parameters)

channel = connection.channel()
  • 接下來, 在發送之前, 我們需要確保收件人隊列存在, 如果將消息發送到不存在的位置,RabbitMQ只會刪除該消息。創建一個hello隊列來信息消息傳遞:

    channel.queue_declare(queue='hello')
    
  • 至此,準備發送消息了。第一個消息將字符串Hello World!發送到hello隊列中。

    在RabbitMQ中, 永遠無法將消息直接發送到隊列, 它始終需要進行交換,可以在本教程的發佈/訂閱部分中閱讀相關信息。現在我們需要知道如何使用空字符串表示默認交換, 這種特殊的交換使我們可以準確的指定將信息發送到哪個隊列。隊列名稱需要在routing_key參數中指定:

    channel.basic_publish(exchange='',
                          routing_key='hello',
                          body='Hello World!')
    
    print('已發送: Hello World!')
    
    
    
  • 通過關閉連接來刷新網絡緩存區:

    connection.close()
    

接收

img

  • 第二個程序receive.py 將接收來自隊列的消息並將其打印出來。

  • 同樣需要先連接RabbitMQ服務器, 負責連接RabbitMQ的代碼與之前代碼相同。

  • send.py一樣,需要確保隊列是否存在, 使用queue_declare創建隊列是冪等的, 可以根據需要多次使用該命令, 但是隻會創建一個。

    channel.queue_declare(queue='hello')
    

    send.py中已經聲明瞭該隊列且已經運行,這裏其實可以不用聲明,但是考慮到不確定哪個程序先執行, 所以最好在兩個程序中重複聲明。

  • 查看消息隊列中有多少消息,linux下可以通過:rabbitmqctl list_queues命令查看,windows通過rabbitmqctl.bat list_queues查看。如果安裝了web控制檯,登錄之後可以切換到Queues標籤下查看。

  • 接收消息比發生消息複雜一點, 通過回調函數來進行操作,當隊列收到消息時會回調我們制定的消息處理函數。

    def callback(ch, method, properties, body):
        """
        :param ch:
        :param method:
        :param properties:
        :param body:
        :return:
        """
        print("收到消息: {}".format(body))
    
  • 接下來, 需要告訴隊列指定回調函數和從哪個隊列接收消息。

channel.basic_consume(queue='hello',
                      auto_ack=True,
                      on_message_callback=callback)
  • 最後進入一個無限循環, 該循環等待數據並在必要的時候進行回調。

    print('等待接收消息, 按CTRL+C退出....')
    channel.start_consuming()
    

代碼整合

send.py

from pika import BlockingConnection, ConnectionParameters

# RabbitMQ連接參數,基本有默認值
parameters = ConnectionParameters(
    host='localhost',
    # port=_DEFAULT,
    # virtual_host=_DEFAULT,
    # credentials=_DEFAULT,
    # channel_max=_DEFAULT,
    # frame_max=_DEFAULT,
    # heartbeat=_DEFAULT,
    # ssl_options=_DEFAULT,
    # connection_attempts=_DEFAULT,
    # retry_delay=_DEFAULT,
    # socket_timeout=_DEFAULT,
    # stack_timeout=_DEFAULT,
    # locale=_DEFAULT,
    # blocked_connection_timeout=_DEFAULT,
    # client_properties=_DEFAULT,
    # tcp_options=_DEFAULT,
)
connection = BlockingConnection(parameters=parameters)

channel = connection.channel()


channel.queue_declare(queue='hello')

channel.basic_publish(exchange='',
                      routing_key='hello',
                      body='Hello World!')

print('已發送: Hello World!')

connection.close()

receive.py

from pika import BlockingConnection, ConnectionParameters

# RabbitMQ連接參數,基本有默認值
parameters = ConnectionParameters(
    host='localhost',
    # port=_DEFAULT,
    # virtual_host=_DEFAULT,
    # credentials=_DEFAULT,
    # channel_max=_DEFAULT,
    # frame_max=_DEFAULT,
    # heartbeat=_DEFAULT,
    # ssl_options=_DEFAULT,
    # connection_attempts=_DEFAULT,
    # retry_delay=_DEFAULT,
    # socket_timeout=_DEFAULT,
    # stack_timeout=_DEFAULT,
    # locale=_DEFAULT,
    # blocked_connection_timeout=_DEFAULT,
    # client_properties=_DEFAULT,
    # tcp_options=_DEFAULT,
)
connection = BlockingConnection(parameters=parameters)

channel = connection.channel()


channel.queue_declare(queue='hello')


def callback(ch, method, properties, body):
    """
    :param ch:
    :param method:
    :param properties:
    :param body:
    :return:
    """
    print("收到消息: {}".format(body))


channel.basic_consume(queue='hello',
                      auto_ack=True,
                      on_message_callback=callback)

print('等待接收消息, 按CTRL+C退出....')
channel.start_consuming()

  • python send.py 發送消息, 控制檯輸出:

    已發送: Hello World!
    
  • 然後python receive.py, 發現控制檯永遠不會退出:

    等待接收消息, 按CTRL+C退出....
    收到消息: b'Hello World!'
    
  • 再次python send.py, 會再次進行函調函數, 輸出b'Hello World!'


在Gitbook中閱讀

原文鏈接

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