![山本美月](http://static.javashuo.com/static/loading.gif)
初識rabbitMQ
RabbitMQ 是一個由 Erlang 語言開發的 AMQP 的開源實現。html
AMQP :Advanced Message Queue,高級消息隊列協議。它是應用層協議的一個開放標準,爲面向消息的中間件設計,基於此協議的客戶端與消息中間件可傳遞消息,並不受產品、開發語言等條件的限制。linux
RabbitMQ 最初起源於金融系統,用於在分佈式系統中存儲轉發消息,在易用性、擴展性、高可用性等方面表現不俗。具體特色包括:緩存
RabbitMQ 特色
可靠性(Reliability)安全
RabbitMQ 使用一些機制來保證可靠性,如持久化、傳輸確認、發佈確認。服務器
靈活的路由(Flexible Routing)多線程
在消息進入隊列以前,經過 Exchange 來路由消息的。對於典型的路由功能,RabbitMQ 已經提供了一些內置的 Exchange 來實現。針對更復雜的路由功能,能夠將多個 Exchange 綁定在一塊兒,也經過插件機制實現本身的 Exchange 。負載均衡
消息集羣(Clustering)tcp
多個 RabbitMQ 服務器能夠組成一個集羣,造成一個邏輯 Broker 。分佈式
高可用(Highly Available Queues)ide
隊列能夠在集羣中的機器上進行鏡像,使得在部分節點出問題的狀況下隊列仍然可用。
多種協議(Multi-protocol)
RabbitMQ 支持多種消息隊列協議,好比 STOMP、MQTT 等等。
多語言客戶端(Many Clients)
RabbitMQ 幾乎支持全部經常使用語言,好比 Java、.NET、Ruby 等等。
管理界面(Management UI)
RabbitMQ 提供了一個易用的用戶界面,使得用戶能夠監控和管理消息 Broker 的許多方面。
跟蹤機制(Tracing)
若是消息異常,RabbitMQ 提供了消息跟蹤機制,使用者能夠找出發生了什麼。
插件機制(Plugin System)
RabbitMQ 提供了許多插件,來從多方面進行擴展,也能夠編寫本身的插件。
Rabbitmq使用流程
rabbitmq做爲消息隊列,一條消息從發佈到訂閱消費的完整流程爲:
消息 --> 交換機exchange ---> 隊列queue ---> 消費者
rabbitmq的核心就在交換機和隊列
發佈者(推送消息的一端):
- 建立一個tcp長鏈接connection,鏈接rabbitmq的監聽端口5672;
- 在TCP長鏈接下建立一個信道channel,信道能夠理解爲connection的一個分支;
- 經過信道向rabbitmq聲明一個交換機exchange,設置交換機的類型,名稱,是否持久化等屬性;
- 經過信道向rabbitmq聲明一個隊列queue,設置隊列的名稱,是否持久化等參數;
- 經過信道向rabbitmq聲明一個綁定binding,設置綁定的交換機名稱,隊列名稱,綁定的路由鍵;
- 經過信道向rabbitmq推送一條消息,指定交換機和路由;
消費者(接收消息的一端):
- 從第一步到第四步和發佈者作的事情是如出一轍的;
- 經過信道向rabbitmq聲明一個訂閱,訂閱特定的queue,而且設置回調函數及是否確認等;
- 經過信道監聽rabbitmq推送過來的消息;
- 消費的時候能夠設置是否自動確認,若是是手動的話須要手動ack來確認消費完成才最終結束消費流程
深刻理解
建立鏈接connection
- rabbitmq實現的是AMQP通訊協議,其所容許的最大AMQP鏈接數,本質上是TCP鏈接數;
- 採用TCP長鏈接,自帶SSL認證機制,相似https,保證數據的傳輸安全;
- 其TCP鏈接的上限能夠經過調整操做系統的限制來變動,詳情linux修改TCP最大鏈接數
建立信道channel
- 信道channel能夠理解成是connection下的分支,也就是說多個channel共享一個connection,爲何要這麼作呢?
- 建立TCP鏈接是一個很是耗時的操做,若是一個應用須要多個connection的話,每次的建立和關閉會性能下降,而建立多個channel共享一個connection提升性能,節約系統資源;
- 多個channel是相互獨立隔離的,這致使了一個問題就是,因爲主機只能識別不一樣的TCP鏈接,但不能識別不一樣的信道發送過來的消息,所以rabbitmq爲每一個建立的信道分配了一個信道ID用來識別不一樣信道發送的消息;
- 每一個信道都是爲獨立的進程或線程準備的,所以多線程或多進程共享信道是不被容許的;
- 在一個TCP下可建立的chnnel的數量理論上是沒有上限的,只取決於系統資源,但能夠經過配置channel_max參數設置上限;
聲明交換機exchange
注意
每一個交換機的名字是惟一的,若是重複聲明交換機而且聲明的參數徹底同樣,那麼mq會忽略該聲明;
若是聲明交換機已經存在,但修改了它的屬性,好比類型或持久化等,那麼會報錯;因此修改的方法是先刪除原來的交換機再建立一個新的交換機;
隊列queue
- queue用來緩存消息,並向消費者推送消息;
- 聲明隊列的名稱最多255個字節,能夠是任意字符串;
- 若是聲明時名字爲空,mq會隨機生成一個名字;
- 聲明隊列不能夠用amq.開頭,不然報錯;
- 若是多個消費者訂閱同一個隊列的消息,那麼隊列會用輪詢的方式推送消息,這種方式能夠實現負載均衡;
注意:
- 每一個隊列的名字是惟一的,若是重複聲明交換機而且聲明的參數徹底同樣,那麼mq會忽略該聲明;
- 若是聲明的該隊列已經存在,但修改了它的屬性,好比類型或持久化等,那麼會報錯;因此修改的方法是先刪除原來的隊列再建立一個新的隊列;
消息訂閱
- 消費者能夠向隊列訂閱消息,每一個消費者都會被分配一個標誌符;
- 訂閱時能夠設置消費回執,告訴mq何時能夠將消息刪除了,默認是自動刪除的;
- 消費者也能夠向mq發送 拒絕消息 ,這時消息會被放回隊列等待投遞到其餘的消費者;
- 消費者訂閱的時候能夠設置預取計數,當存在多個消費者共同訂閱一個隊列的時候,因爲是輪詢機制,但每一個消費者的消費能力多是不同的,這可能形成有的消費者閒的要死,有的忙的要死,設置預取數量,在沒有收到回執確認前,該隊列推送的消息是有限的,能夠提升總體的吞吐量;
消息,交換機,隊列的持久化
- 消息持久化是在消息投遞前定義的,設置了持久化後,消息會被保存在磁盤,當被消費後會從磁盤中刪除,可是也不能保證100%持久化成功,由於消息是先放到內存中的,若是此時主機崩潰,仍是會有一部分來不及寫入磁盤;
- 交換機持久化是在聲明該交換機的時候設置的,當主機崩潰或重啓後,mq一從新上線會自動從新聲明一個和原來徹底同樣的交換機;
- 隊列持久化是在隊列被聲明的時候設置的,mq從新上線會自動從新聲明一個和原來徹底同樣的queue,可是隊列裏的消息會所有丟失;
參考連接
消息隊列之 RabbitMQ
RabbitMQ進程結構分析與性能調優
https://www.rabbitmq.com/admin-guide.html
原博
RabbitMQ的構架