RabbitMQ 三種Exchange

RabbitMQ是一個消息代理,核心原理:發送消息,接收消息。html

RabbitMQ主要用於組件之間的解耦,消息發送者無需知道消息使用者的存在,反之亦然。python

 RabbitMQ基本概念和使用  RabbitMQ基本概念和使用

                                單向解耦                                        雙向解耦(如:RPC)服務器

例如一個日誌系統,很容易使用RabbitMQ簡化工做量,一個Consumer進行消息的正常處理,另外一個Consumer複製對消息進行日誌記錄,只要在程序中指定兩個Consumer所監聽的queue以相同的方式綁定到同一個exchange便可,剩下的消息分發工做由RabbitMQ完成。網絡

安裝rabbitmq,請參考官網函數

首先經過一個很是簡單的」hello world「例子介紹如何使用RabbitMQ,而後再介紹其涉及的基本概念並對交換機和隊列多作點介紹。this

1、helloworld例子

本例很是簡單——發送一個消息」hello world「,而後獲取它並輸出到屏幕。spa

總共須要兩個程序,一個發送消息叫send.py,一個接受消息並打印消息內容叫receive.py。代理

該圖爲helloworld例子的原理圖:生產者send.py(Productor)把消息(」hello world「)發送到一個名爲」queue「的隊列中,消費者receive.py從這個隊列中獲取消息。接下來看代碼:日誌

send.py(發送消息)server

#!/usr/bin/env python
import pika
#第一步,鏈接RabbitMq服務器
rabbit_username='xxx' 
rabbit_password='xxx'
credentials = pika.PlainCredentials(rabbit_username, rabbit_password) 
connection = pika.BlockingConnection(pika.ConnectionParameters( host='x.x.x.x',credentials=credentials))
#channel是進行消息讀寫的通道
channel = connection.channel()

#第二步,建立一個名爲queue的隊列,而後把消息發送到這個隊列

channel.queue_declare(queue='queue')

#第三步,如今能夠發送消息,可是RabbitMQ不能把消息直接發送到隊列,要發送到交換器,這個稍後介紹,這裏使用默認交換器(exchange),它使用一個空字符串標
#識,routing_key參數必須指定爲隊列名稱,這裏爲queue

channel.basic_publish(exchange='',
                      routing_key='queue',
                      body='hello world')
print "send.py:send message 'hello world',wait for receive.py deal with this message"

#退出程序前,經過關閉鏈接保證消息已經投遞到RabbitMq                                                                                               
connection.close()

 

 

receive.py(獲取數據)

 

print ' [*] Waiting for messages. To exit press CTRL+C'

#!/usr/bin/env python
import pika

#第一步,一樣鏈接RabbitMq服務器
rabbit_username='xxx'
rabbit_password='xxx'
credentials = pika.PlainCredentials(rabbit_username, rabbit_password)
connection = pika.BlockingConnection(pika.ConnectionParameters( host='x.x.x.x',credentials=credentials))
channel = connection.channel()

#爲確保隊列存在,再次執行queue_declare建立一個隊列,咱們能夠屢次運行該命令,可是隻要一個隊列會建立
#由於不能保證send.py先執行仍是receive.py先執行,因此重複聲明隊列來確保其存在
channel.queue_declare(queue='hellolxy')


#第三步,定義一個回調函數,當得到消息時,Pika庫調用這個回調函數來處理消息,該回調函數將消息內容打印到屏幕
def callback(ch, method, properties, body):
    print "receive.py: Received message %r" % (body,)

#第四步,告訴rabbbitMq回調函數將從queue隊列接收消息
channel.basic_consume(callback,
                      queue='queue',
                      no_ack=True)

#第五步,輸入一個無限循環來等待消息數據並運行回調函數
print ' [*] Waiting for messages. To exit press CTRL+C'
channel.start_consuming()

 

如今在終端運行程序。首先,用send.py發送一條消息:

$ python send.py 
send.py:send message 'hello world',wait for receive.py deal with this message

生產者(producer)程序send.py每次運行後就會中止。如今運行receive.py來接收消息:

$ python receive.py 
receive.py: Received message 'hello world'  [*] Waiting for messages. To exit press CTRL+C

成功了!如今已經經過RabbitMQ發送了第一條消息。可是receive.py程序並無退出,它一直在準備獲取消息,能夠經過ctrl-c來中斷它。

2、RabbitMQ基本概念

總結一下發送接收消息的過程:

經過上面例子對RabbitMQ有一個感性認識後,如今來介紹RabbitMQ中的基本概念。

Broker:消息隊列服務器實體

消息:每一個消息都有一個路由鍵(routing key)的屬性。就是一個簡單的字符串。

connection:應用程序與broker的網絡鏈接。

channel:幾乎全部的操做都在channel中進行,channel是進行消息讀寫的通道。客戶端可創建多個channel,每一個channel表明一個會話任務。

交換機:接收消息,根據路由鍵轉發消息到綁定的隊列

綁定:一個綁定就是基於路由鍵將交換機和隊列鏈接起來的路由規則,因此交換機不過就是一個由綁定構成的路由表。

舉例:一個具備路由鍵「key1」的消息要發送到兩個隊列,queueA和queueB。要作到這點就要創建兩個綁定,每一個綁定鏈接一個交換機和一個隊列。二者都是由路由鍵「key1」觸發,這種狀況,交換機會複製一份消息並把它們分別發送到兩個隊列中。

隊列:消息的容器,也是消息的終點。一個消息可投入一個或多個隊列。消息一直在隊列裏面,等待消費者鏈接到這個隊列將其取走。

3、交換機

交換機用來接收消息,轉發消息到綁定的隊列,是rabbitMq中的核心。

交換機共有4種類型:direct,topic,headers和fanout。

爲何不建立一種交換機來處理全部類型的路由規則?由於每種規則匹配時的CPU開銷是不一樣的,因此根據不一樣需求選擇合適交換機。

舉例:一個"topic"類型的交換機會將消息的路由鍵與相似「dog.*」的模式進行匹配。一個「direct」類型的交換機會將路由鍵與 「dogs」進行比較。匹配末端通配符比直接比較消耗更多的cpu,因此若是用不到「topic」類型交換機帶來的靈活性,就經過「direct」類型交 換機得到更高的處理效率。

一、Direct交換機:轉發消息到routingKey指定隊列(徹底匹配,單播)。

routingKey與隊列名徹底匹配,若是一個隊列綁定到交換機要求路由鍵爲「dog」,則只轉發routingkey標記爲dog的消息,不會轉發dog.puppy,也不會轉發dog.guard等。

二、Topic交換機:按規則轉發消息(最靈活,組播)

 Topic類型交換機經過模式匹配分配消息的routing-key屬性。將路由鍵和某個模式進行匹配,此時隊列須要綁定到一個模式上。

它將routing-key和binding-key的字符串切分紅單詞。這些單詞之間用點隔開。它一樣也會識別兩個通配符:符號「#」和符號「*」。#匹配0個或多個單詞,*匹配很少很多一個單詞。

例如,binding key:*.stock.#匹配routing key: usd.stock和eur.stock.db,可是不匹配stock.nana。

例如,「audit.#」可以匹配到「audit.irs.corporate」,可是「audit.*」只會匹配到「audit.irs」。

三、Fanout交換機:轉發消息到全部綁定隊列(最快,廣播)

fanout交換機不處理路由鍵,簡單的將隊列綁定到交換機上,每一個發送到交換機的消息都會被轉發到與該交換機綁定的全部隊列上。

很像子網廣播,每臺子網內的主機都得到了一份複製的消息。Fanout交換機轉發消息是最快的。

四、Note

  • 若是沒有隊列綁定在交換機上,則發送到該交換機上的消息會丟失。
  • 一個交換機能夠綁定多個隊列,一個隊列能夠被多個交換機綁定。
  • 還有一些其餘類型的交換機類型,如header、failover、system等,如今在當前的RabbitMQ版本中均未實現。
  • 由於交換機是命名實體,聲明一個已經存在的交換機,可是試圖賦予不一樣類型是會致使錯誤。客戶端須要刪除這個已經存在的交換機,而後從新聲明而且賦予新的類型。
  • 交換機的屬性:
    • 持久性:若是啓用,交換機將會在server重啓前都有效。
    • 自動刪除:若是啓用,那麼交換機將會在其綁定的隊列都被刪掉以後刪除自身。
    • 惰性:若是沒有聲明交換機,那麼在執行到使用的時候會致使異常,並不會主動聲明。

4、隊列

  • 隊列的屬性:
    • 持久性:若是啓用,隊列將在Server服務重啓前都有效。
    • 自動刪除:若是啓用,那麼隊列將會在全部的消費者中止使用以後自動刪除自身。
    • 惰性:若是沒有聲明隊列,那麼在執行到使用的時候會致使異常,並不會主動聲明。
    • 排他性:若是啓用,隊列只能被聲明它的消費者使用。        

 深刻了解可參考:

相關文章
相關標籤/搜索