1. 程式人生 > >RabbitMQ學習小結(五)—— Topics[Python]

RabbitMQ學習小結(五)—— Topics[Python]

1. 簡介

上節我們提到直連交換機,並基於我們的日誌系統使用直連交換機,而本節我們使用rabbitmq內建的另外一種交換機——主題交換機。
所謂主題交換機是什麼呢?通俗點來講就是直連交換機的升級版,我們可以認為直連交換機就是她其中的一種形式。
直連交換機需要通過繫結(bindings)和佇列建立起關係,而其主要通過的就是routing_key,並且routing_key是要與生產者提供的routing_key完全匹配才能得到訊息。主題交換機對其進行了升級,升級的方式就是通過兩個符號"#""*"以及對routing_key的長度限制和格式限制,完成了模糊匹配,從而達到消費者可以更靈活的匹配要處理的訊息,下面再具體針對例項來進行主題交換機的學習。

2. 主題交換機

傳送到主題交換機(topic exchange)的訊息攜帶的路由鍵(routing_key)必須是一個由.分隔開的詞語列表。這些單詞隨便是什麼都可以,但是最好是跟攜帶它們的訊息有關係的詞彙。以下是幾個推薦的例子:"stock.usd.nyse", "nyse.vmw", "quick.orange.rabbit"。詞語的個數可以隨意,但是不要超過255位元組。
繫結鍵也必須擁有同樣的格式。主題交換機背後的邏輯跟直連交換機很相似 —— 一個攜帶著特定路由鍵的訊息會被主題交換機投遞給繫結鍵與之想匹配的佇列。但是它的繫結鍵和路由鍵有兩個特殊應用方式:

"*" (星號) 用來表示一個單詞。
"#"

(井號) 用來表示任意數量(零個或多個)單詞。

大家可以根據下圖,猜測哪些路由鍵會被髮送到相應的佇列,就是類似於正則的匹配,但是比正則簡單太多了,有興趣的可以到官網檢視完整內容,我就不再闡述了。


主題交換機

當一個佇列的繫結鍵為 "#"(井號) 的時候,這個佇列將會無視訊息的路由鍵,接收所有的訊息。
當 * (星號) 和 # (井號) 這兩個特殊字元都未在繫結鍵中出現的時候,此時主題交換機就擁有的直連交換機的行為。

所以主題交換機也就實現了扇形交換機的功能,和直連交換機的功能

總結

我們基於整個流程進行一下總結

生產者

建立連線
建立交換機(主題交換機)
傳送訊息到指定交換機,並將訊息中指定routing_key(注意key的規則)

消費者

建立連線
建立交換機(主題交換機)
建立匿名佇列(每個消費者都要建立的獨立的佇列,用於接收路由後訊息)
建立繫結(通過路由鍵繫結交換機佇列關係,確定佇列處理交換機中的哪些訊息,注意路由鍵的正則規則)
在指定交換機處理訊息

程式碼整合

emit_logs_topic.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2016-02-28 21:28:17
# @Author  : mx ([email protected])
# @Link    : http://www.shujutiyu.com/
# @Version : $Id$

import os
import pika
import sys

conn = None

routing_key = sys.argv[1] if len(sys.argv) > 1 else 'anonymous.info'
message = ' '.join(sys.argv[2:]) or 'Hello World!'

try:
    # 獲取連線
    conn = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
    # 獲取通道
    channel = conn.channel()

    # 建立直連交換機
    channel.exchange_declare(exchange='topic_logs',
                             type='topic')

    # 在RabbitMQ中傳送訊息,指定交換機(exchange),指定routing
    ret = channel.basic_publish(exchange='topic_logs',
                                routing_key=routing_key,
                                body=message,)
    print " [x] Sent '{0}'".format(message)
    print ret
except Exception, e:
    raise e
finally:
    if conn:
        conn.close()
recv_logs_topic.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2016-02-29 16:30:21
# @Author  : mx ([email protected])
# @Link    : http://www.shujutiyu.com/
# @Version : $Id$

import pika
import sys

conn = None

binding_keys = sys.argv[1:]
if not binding_keys:
    print >> sys.stderr, "Usage: %s [binding_key]..." % (sys.argv[0],)
    sys.exit(1)

def callback(ch, method, properties, body):
    """
        @ch: channel 通道,是由外部呼叫時上送
        out body
        讀取佇列內容做不同的操作
    """
    print " [x] method.routing_key {0}".format(method.routing_key)
    print " [x] Done %r" % (body, )

try:
    # get connection
    conn = pika.BlockingConnection(pika.ConnectionParameters(
        'localhost')
    )

    # get channel
    channel = conn.channel()

    # 宣告直連交換機
    channel.exchange_declare(exchange='topic_logs', 
                             type='topic')

    # 宣告臨時佇列 , param exclusive 互斥
    tmp_queue = channel.queue_declare(exclusive=True)
    queue_name = tmp_queue.method.queue

    # 根據輸入routing_key繫結交換機與佇列
    for binding_key in binding_keys:
        channel.queue_bind( exchange='topic_logs', 
                            queue=queue_name,
                            routing_key=binding_key )

    # 在佇列中讀取資訊
    channel.basic_consume(callback, queue=queue_name, no_ack=True)

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

    channel.start_consuming()
except Exception, e:
    raise e
finally:
    if conn:
        conn.close()

疑問

  • 繫結鍵為 * 的佇列會取到一個路由鍵為空的訊息嗎?
  • 繫結鍵為 #.* 的佇列會獲取到一個名為..的路由鍵的訊息嗎?它會取到一個路由鍵為單個單詞的訊息嗎?
  • a.*.# 和 a.#的區別在哪兒?
  • 之前提到了佇列、訊息、交換機可以持久化,有興趣的不妨試一下

3. 參考資料

相關推薦

RabbitMQ學習小結—— Topics[Python]

1. 簡介 上節我們提到直連交換機,並基於我們的日誌系統使用直連交換機,而本節我們使用rabbitmq內建的另外一種交換機——主題交換機。 所謂主題交換機是什麼呢?通俗點來講就是直連交換機的升級版

Python學習筆記OOP

默認 tro acl 引入 支持 不同 post set 成像 模塊 使用模塊import 模塊名。有的僅僅導入了某個模塊的一個類或者函數,使用from 模塊名 import 函數或類名實現。為了避免模塊名沖突。Python引入了按文件夾來組織模塊的方

流暢的python和cookbook學習筆記

pytho col () 學習 util 學習筆記 取出 minute python 1.隨機選擇   python中生成隨機數使用random模塊。   1.從序列中隨機挑選元素,使用random.choice() >>> import random

python學習筆記數值類型和類型轉換

學習 系統 oat cal 關於 trac hide sed lin Python中的數值類型有:   整型,如2,520   浮點型,如3.14159,1.5e10   布爾類型 True和False e記法:   e記法即對應數學中的科學記數法 1 >>

python學習筆記

推導式 for mod cal pos [] 類名 left 開頭 38、繼承 子類繼承父類時,如果不寫init方法,表示繼承父類的init方法。如果寫了init方法,表示重寫父類的init方法。其他方法也是同理。對於變量也是同樣的道理。 class A: def __in

python學習記錄

特定 bar 打印字符 toolbar 元組 pytho www san 數字 20180829--https://www.cnblogs.com/fnng/archive/2013/04/20/3032563.html 字典 字典的使用 現實中的字段及在Python中

Python學習筆記變數的命名

一、識別符號 識別符號就是程式設計師定義的變數名、函式名 名字 需要有 見名知義的效果   識別符號可以由 字母、下劃線和數字組成 不能以數字開頭 不能與關鍵字重名   二、關鍵字 關鍵字就是pyt

Python 學習筆記[面向物件]

變數 類的變數 class A: num = 1 a = A() # 1 a.num # 1 A.num # 修改類的變數值 A.num = 2 # 2 a.num # 修改物件的變數值 a.num = 3 2 A.num # 給物件新增屬性 a.age

Python + OpenCV 學習筆記>>> 畫素運算

1. 算數運算 注意:兩幅影象的畫素大小要一致 進行影象畫素之間的算術運算,首先要匯入影象,讀取其中資訊: m1 = cv.imread("/home/pi/Desktop/m1.jpg") m2 = cv.imread("/home/pi/Desktop/m2.jpg")

python學習Python類中super()和__init__()的關係

1.單繼承時super()和__init__()實現的功能是類似的 class Base(object): def __init__(self): print 'Base create' class childA(Base): def __init__(sel

python學習日記

        不好意思,這次拖更了這麼久,實在是事情纏身,鍋從天上來emmm。好在現在緊急的事情沒有了,剩下的就慢慢做吧,學習依然得繼續了。         今天學的主要是迴圈和分支。老用while肯定是不行的,像

python學習小結

通常一個複雜的程式由多個檔案組成,main檔案是程式的入口,提示使用者資訊。 1.框架搭建 搭建框架結構,首先要準備檔案,確定檔名保證能夠在需要的位置編寫程式碼。其次,編寫主執行迴圈實現基本的使用者輸入和判斷。 可以將一個檔案儲存主程式程式碼,另一個檔案用於功能函式的儲存,在使用時將功能函式通過模組匯入

Python學習筆記猜數字遊戲while

今天寫的是一個猜數字遊戲,我記得好像大二還是大三的時候在日方課上用vb實現過,大體思想就是先生成一個隨機數,然後進行輸入,程式會判斷你輸入的值和隨機值相比較的結果,一直到你輸入正確才退出迴圈體。 關於隨機數的應用,首先要引入random類,程式中生成的是1到10的隨機

Python學習筆記-- 上下文管理器Context Manager

定義 如何使用 如何建立 1.定義 寫程式碼時,我們希望把一些操作放到一個程式碼塊中,這樣在程式碼塊中執行時就可以保持在某種執行狀態,而當離開該程式碼塊時就執行另一個操作,結束當前狀態;所以,簡單來說,上下文管理器的目的就是規定物件的

Spark (Python版) 零基礎學習筆記—— Spark RDDs程式設計

RDD基礎概念 建立RDD 建立RDD的方法: 1.載入外部資料集 2.分佈一個物件的集合 前邊幾次的筆記已經提到過多次了,因此,這裡只列出幾個注意事項: 1.利用sc.parallelize建立RDD一般只適用於在測試的時候使用,因為這需要我們將整

多分類例項:鳶尾花分類-基於keras的python學習筆記

版權宣告:本文為博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/weixin_44474718/article/details/86420803 資料集可以從UCI機器學習倉庫下載(http://archive.ics.uci.edu/ml/datasets

python基礎學習筆記裝飾器,高階函式

多程序程式設計import multiprocessing def process1(): return 1 def process2(): return 2 p1=multiprocessing.Process(target=process1) p2=m

《零基礎入門學習python學習過程

學習時間:2017/10/17 第18、19、20、21、22、23課:函式 18課知識點彙總: 建立和呼叫函式: >>> def Function_name(parameters): #函式建立 functio

python學習筆記集合(set)

set 擁有類似 dict 的特點:可以用{}花括號來定義;其中的元素沒有序列,也就是是非序列型別的資料;而且,set 中的元素不可重複,這就類似 dict 的鍵. set 也有一點 list 的特點:有一種集合可以原處修改. 下面通過實驗,進一步理解建立 set 的方法:

python學習筆記——輸入和輸出

第六章 輸入和輸出 #第六章 輸入和輸出 #6.1 輸入和輸出概述 #實現互動功能的方式:a命令列引數 b標準輸入和輸出函式 c檔案輸入和輸出 d圖形化使用者介面 #6.2 命令列引數 #6.2.1 sys.argv與命令列引數 # import sys,random