1. 程式人生 > >RabbitMQ監控(1)——RabbitMQ簡介

RabbitMQ監控(1)——RabbitMQ簡介

        最近公司想要開發一套針對RabbitMQ的監控系統,和簡訊及郵件介面整合,對效能做到實時的監控,表示這個真的很及時,這樣我們就能“24小時不離崗”只要手機開著,就對網站效能有較好的把控,下面將分幾部介紹如何實現。

本篇為科普階段,已經是mq大牛的你,請直接檢視其他文章!

1. 由來

        對於一個大型的軟體系統來說,它會有很多的元件或者說模組或者說子系統或者(subsystem or Component or submodule)。那麼這些模組的如何通訊?這和傳統的IPC有很大的區別。傳統的IPC很多都是在單一系統上的,模組耦合性很大,不適合擴充套件(Scalability);如果使用socket那麼不同的模組的確可以部署到不同的機器上,但是還是有很多問題需要解決。比如:


         1)資訊的傳送者和接收者如何維持這個連線,如果一方的連線中斷,這期間的資料如何方式丟失?
         2)如何降低傳送者和接收者的耦合度?
         3)如何讓Priority高的接收者先接到資料?
         4)如何做到load balance?有效均衡接收者的負載?
         5)如何有效的將資料傳送到相關的接收者?也就是說將接收者subscribe 不同的資料,如何做有效的filter。
         6)如何做到可擴充套件,甚至將這個通訊模組發到cluster上?
         7)如何保證接收者接收到了完整,正確的資料?


        AMDQ協議解決了以上的問題,而RabbitMQ實現了AMQP。

        RabbitMQ是一個由erlang開發的AMQP(Advanced Message Queue )的開源實現。雖然在同步訊息通訊的世界裡有很多公開標準(如 COBAR的 IIOP ,或者是 SOAP 等),但是在非同步訊息處理中卻不是這樣,只有大企業有一些商業實現(如微軟的 MSMQ ,IBM 的 Websphere MQ 等),因此,在 2006 年的 6 月,Cisco 、Redhat、iMatix 等聯合制定了 AMQP 的公開標準。
        RabbitMQ是由RabbitMQ Technologies Ltd開發並且提供商業支援的。該公司在2010年4月被SpringSource(VMWare的一個部門)收購。在2013年5月被併入Pivotal。其實VMWare,Pivotal和EMC本質上是一家的。不同的是VMWare是獨立上市子公司,而Pivotal是整合了EMC的某些資源,現在並沒有上市。

        RabbitMQ的官網是http://www.rabbitmq.com

2. 系統架構

紅線為其中一次通訊通道
      

    


        RabbitMQ Server: 也叫broker server,它不是運送食物的卡車,而是一種傳輸服務。原話是RabbitMQisn’t a food truck, it’s a delivery service. 他的角色就是維護一條從Producer到Consumer的路線,保證資料能夠按照指定的方式進行傳輸。但是這個保證也不是100%的保證,但是對於普通的應用來說這已經足夠了。當然對於商業系統來說,可以再做一層資料一致性的guard,就可以徹底保證系統的一致性了。

這一點和flume和像,他們都是做了訊息的載體!

        Client A: 也叫Producer,資料的傳送方。createmessages and publish (send) them to a broker server (RabbitMQ).一個Message有兩個部分:payload(有效載荷)和label(標籤)。payload顧名思義就是傳輸的資料。label是exchange的名字或者說是一個tag,它描述了payload,而且RabbitMQ也是通過這個label來決定把這個Message發給哪個Consumer。AMQP僅僅描述了label,而RabbitMQ決定了如何使用這個label的規則。

        Client C:也叫Consumer,資料的接收方。Consumersattach to a broker server (RabbitMQ) and subscribe to a queue。把queue比作是一個有名字的郵箱。當有Message到達某個郵箱後,RabbitMQ把它傳送給它的某個訂閱者即Consumer。當然可能會把同一個Message傳送給很多的Consumer。在這個Message中,只有payload,label已經被刪掉了。對於Consumer來說,它是不知道誰傳送的這個資訊的。就是協議本身不支援。但是當然瞭如果Producer傳送的payload包含了Producer的資訊就另當別論了。

        這些定義,其實和kafka的定義是一樣的,在flume中,對應的就是sink,chanel,source等概念,沒有什麼變化,只是服務方式不同,mq是儲存,等待消費,flume是推送,等待接收結果,一個是推,一個是拉!

        對於一個數據從Producer到Consumer的正確傳遞,還有三個概念需要明確:exchanges, queues and bindings。
                Exchanges :生產者送到哪去
                Queuesare :消費這消費哪些訊息
                Bindings :繫結雙方管道(Exchanges 和 Queuesare )

        還有幾個概念是上述圖中沒有標明的,那就是Connection(連線),Channel(通道,頻道)。 

        Connection: 就是一個TCP的連線。Producer和Consumer都是通過TCP連線到RabbitMQ Server的。以後我們可以看到,程式的起始處就是建立這個TCP連線。

        Channels: 虛擬連線。它建立在上述的TCP連線中。資料流動都是在Channel中進行的。也就是說,一般情況是程式起始建立TCP連線,第二步就是建立這個Channel。
        那麼,為什麼使用Channel,而不是直接使用TCP連線?
        對於OS來說,建立和關閉TCP連線是有代價的,頻繁的建立關閉TCP連線對於系統的效能有很大的影響,而且TCP的連線數也有限制,這也限制了系統處理高併發的能力。但是,在TCP連線中建立Channel是沒有上述代價的。對於Producer或者Consumer來說,可以併發的使用多個Channel進行Publish或者Receive。有實驗表明,1s的資料可以Publish10K的資料包。當然對於不同的硬體環境,不同的資料包大小這個資料肯定不一樣,但是我只想說明,對於普通的Consumer或者Producer來說,這已經足夠了。如果不夠用,你考慮的應該是如何細化split你的設計。

3. 細節

(1)使用ack確認Message的正確傳遞 
        預設情況下,如果Message 已經被某個Consumer正確的接收到了,那麼該Message就會被從queue中移除。當然也可以讓同一個Message傳送到很多的Consumer。
如果一個queue沒被任何的Consumer Subscribe(訂閱),那麼,如果這個queue有資料到達,那麼這個資料會被cache,不會被丟棄。當有Consumer時,這個資料會被立即傳送到這個Consumer,這個資料被Consumer正確收到時,這個資料就被從queue中刪除。
        那麼什麼是正確收到呢?通過ack。每個Message都要被acknowledged(確認,ack)。我們可以顯示的在程式中去ack,也可以自動的ack。如果有資料沒有被ack,那麼:RabbitMQ Server會把這個資訊傳送到下一個Consumer。如果這個app有bug,忘記了ack,那麼RabbitMQ Server不會再發送資料給它,因為Server認為這個Consumer處理能力有限。
        而且ack的機制可以起到限流的作用(Benefitto throttling):在Consumer處理完成資料後傳送ack,甚至在額外的延時後傳送ack,將有效的balance Consumer的load。
當然對於實際的例子,比如我們可能會對某些資料進行merge,比如merge 4s內的資料,然後sleep 4s後再獲取資料。特別是在監聽系統的state,我們不希望所有的state實時的傳遞上去,而是希望有一定的延時。這樣可以減少某些IO,而且終端使用者也不會感覺到。


(2) Reject a message
        有兩種方式,第一種的Reject可以讓RabbitMQ Server將該Message 傳送到下一個Consumer。第二種是從queue中立即刪除該Message。


(3)Creating a queue
        Consumer和Procuder都可以通過 queue.declare 建立queue。對於某個Channel來說,Consumer不能declare一個queue,卻訂閱其他的queue。當然也可以建立私有的queue。這樣只有app本身才可以使用這個queue。queue也可以自動刪除,被標為auto-delete的queue在最後一個Consumer unsubscribe後就會被自動刪除。那麼如果是建立一個已經存在的queue呢?那麼不會有任何的影響。需要注意的是沒有任何的影響,也就是說第二次建立如果引數和第一次不一樣,那麼該操作雖然成功,但是queue的屬性並不會被修改。
        那麼誰應該負責建立這個queue呢?是Consumer,還是Producer?
如果queue不存在,當然Consumer不會得到任何的Message。但是如果queue不存在,那麼Producer Publish的Message會被丟棄。所以,還是為了資料不丟失,Consumer和Producer都try to create the queue!反正不管怎麼樣,這個介面都不會出問題。
queue對load balance的處理是完美的。對於多個Consumer來說,RabbitMQ 使用迴圈的方式(round-robin)的方式均衡的傳送給不同的Consumer。


(4)Exchanges   
         從架構圖可以看出,Procuder Publish的Message進入了Exchange。接著通過“routing keys”, RabbitMQ會找到應該把這個Message放到哪個queue裡。queue也是通過這個routing keys來做的繫結。
        有三種類型的Exchanges:direct, fanout,topic。 每個實現了不同的路由演算法(routing algorithm)。
Direct exchange: 如果 routing key 匹配, 那麼Message就會被傳遞到相應的queue中。其實在queue建立時,它會自動的以queue的名字作為routing key來繫結那個exchange。
        Fanout exchange: 會向響應的queue廣播。
         Topic exchange: 對key進行模式匹配,比如ab*可以傳遞到所有ab*的queue。


(5) Virtual hosts
        每個virtual host本質上都是一個RabbitMQ Server,擁有它自己的queue,exchagne,和bings rule等等。這保證了你可以在多個不同的application中使用RabbitMQ。
接下來我會使用Python來說明RabbitMQ的使用方法。

總結:

        有些概念,在最頂層的設計時,都是一致的,這是個知識減少的過程,隨著接觸的中介軟體越多,越來越多能找到他們一致的方向,就是配置化,多啟動這樣的概念,做成一個零件,哪裡需要哪裡插入,作為鋼鐵,可以焊接擴充套件!這樣的設計理念,使我們需要學習和效仿的!