深刻理解消息中間件技術之RabbitMQ服務

               



什麼叫消息隊列?
html

消息(Message)是指在應用間傳送的數據。消息能夠很是簡單,好比只包含文本字符串,也能夠更復雜,可能包含嵌入對象。消息隊列(Message Queue)是一種應用間的通訊方式,消息發送後能夠當即返回,由消息系統來確保消息的可靠傳遞。消息發佈者只管把消息發佈到 MQ 中而不用管誰來取,消息使用者只管從 MQ 中取消息而不論是誰發佈的。這樣發佈者和使用者都不用知道對方的存在。node

爲什麼用消息隊列?

消息隊列是一種應用間的異步協做機制,那何時須要使用消息隊列呢?像用戶下單以後、生成訂單、結算,定時給系統註冊用戶推送活動消息,一些常見的流程類的業務都會用到消息隊列服務。linux

1、RabbitMQ簡介

RabbitMQ是一個消息的代理器,用於接收和發送消息,你能夠這樣想,他就是一個郵局,當您把須要寄送的郵件投遞到郵筒之時,你能夠肯定的是郵遞員先生確定會把郵件發送到須要接收郵件的人的手裏,不會送錯的。在這個比喻中,RabbitMQ就是一個郵箱,也能夠理解爲郵局和郵遞員,他們負責把消息發送出去和用於接收信息。
RabbitMQ和郵局這二者之間的主要區別是它不會處理紙質郵件,取而代之的是接收、存儲和發送二進制數據塊,也就是咱們一般所說的消息。git

二 、RabbitMQ基本概念

下圖是RabbitMQ服務的內部結構github

圖片

  • 1)Message
    消息,它由消息頭和消息體兩部分組成。消息體是不透明的,但消息頭是由一些屬性組成的,其中包括:routing-key(路由鍵)、priority(優先權)、delivery-mode(持久存儲)。面試

  • 2)Publisher
    生產者,也是消息的生產者,它是向交換器發佈消息的應用程序sql

  • 3)Exchange
    交換器,用來接收生產者傳遞過來的消息,而後將這些消息路由至服務器中的隊列shell

  • 4)Binding
    綁定,用於消息隊列與交換器之間的溝通。也是消息路由的規則,至關於一個路由表。數據庫

  • 5)Queue
    消息隊列,用來保存消息直到發送給消費者。一個消息能夠進入一個或多個隊列,除消費者取走消息,不然它一直在消息隊列裏。json

  • 6)Connection
    網絡鏈接,如:一個TCP鏈接

  • 7)Channel
    信道,多路複用鏈接中一個獨立的雙向數據傳輸通道。不管是發佈消息、訂閱隊列、接收消息都是經過信道來完成。複用信道是爲了下降系統資源的消耗。

  • 8)Consumer
    消費者,也就是接收生產者發來的消息的客戶端應用。

  • 9)Virtual Host
    虛擬主機,交換器、消息隊列相關的對象。一個VHOST其實能夠當作一個rabbitmp服務器,它擁有本身的隊列、交換器、綁定與權限機制等。Rabbitmq默認vhost是/。

3、RabbitMQ 特色

RabbitMQ 是一個由 Erlang 語言開發的 AMQP 的開源實現。AMQP :Advanced Message Queue,高級消息隊列協議。它是應用層協議的一個開放標準,爲面向消息的中間件設計,基於此協議的客戶端與消息中間件可傳遞消息,並不受產品、開發語言等條件的限制。
RabbitMQ 最初起源於金融系統,用於在分佈式系統中存儲轉發消息,在易用性、擴展性、高可用性等方面表現不俗。

具體特色包括:

1)可靠性(Reliability
RabbitMQ 使用一些機制來保證可靠性,如持久化、傳輸確認、發佈確認。
2)靈活的路由(Flexible Routing)
在消息進入隊列以前,經過Exchange 來路由消息的。對於典型的路由功能,RabbitMQ 已經提供了一些內置的Exchange 來實現。針對更復雜的路由功能,能夠將多個Exchange綁定在一塊兒,也經過插件機制實現本身的 Exchange 。
3)消息集羣(Clustering)
多個 RabbitMQ 服務器能夠組成一個集羣,造成一個邏輯 Broker 。
4)高可用(Highly Available Queues)
隊列能夠在集羣中的機器上進行鏡像,使得在部分節點出問題的狀況下隊列仍然可用。
5)多種協議(Multi-protocol)
RabbitMQ 支持多種消息隊列協議,好比 STOMP、MQTT 等等。
6)多語言客戶端(Many Clients)
RabbitMQ 幾乎支持全部經常使用語言,好比 Java、.NET、Ruby 等等。
7)管理界面(Management UI)
RabbitMQ 提供了一個易用的用戶界面,使得用戶能夠監控和管理消息 Broker 的許多方面。
8)跟蹤機制(Tracing)
若是消息異常,RabbitMQ 提供了消息跟蹤機制,使用者能夠找出發生了什麼。
9)插件機制(Plugin System)
RabbitMQ 提供了許多插件,來從多方面進行擴展,也能夠編寫本身的插件。

參考文章 http://www.rabbitmq.com/

4、Rabbitmq的工做過程

  • 1)客戶端鏈接到消息隊列服務器,開啓一個channel

  • 2)客戶端聲明一個exchange、queue,並配置相關屬性

  • 3)客戶端使用routing key,在exchange與queue之間創建好綁定關係

  • 4)客戶端傳遞消息到交換器

  • 5)交換器接收到消息後,根據預約的KEY與綁定關係,對消息進行路由至消息隊列


  • 圖片

5、Rabbitmq服務安裝佈署

1)首先須要安裝Erlang環境

https://bintray.com/rabbitmq/rpm/erlang
[root@master ~]# rpm -ivh erlang-20.3.8-1.el7.centos.x86_64.rpm
準備中...                         ################################# [100%]
正在升級/安裝...
   1:erlang-20.3.8-1.el7.centos   ###
############################## [100%]
[root@master ~]# erl
Erlang/OTP 20 [erts-9.3.3] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:10] [hipe] [kernel-poll:false]

Eshell V9.3.3  (abort with ^G)
1

2)下載安裝Rabbitmq

https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.7.6/rabbitmq-server-3.7.6-1.el7.noarch.rpm
[root@master ~]# ll rabbitmq-server-3.7.6-1.el7.noarch.rpm
-rw-r--r-- 1 root root 9511623 6月  27 14:00 rabbitmq-server-3.7.6-1.el7.noarch.rpm
[root@master ~]# rpm --import https://dl.bintray.com/rabbitmq/Keys/rabbitmq-release-signing-key.asc
[root@master ~]# yum install rabbitmq-server-3.7.6-1.el7.noarch.rpm
[root@master ~]# chkconfig rabbitmq-server on
注意:正在將請求轉發到「systemctl enable rabbitmq-server.service」。
Created symlink from /etc/systemd/system/multi-user.target.wants/rabbitmq-server.service to /usr/lib/systemd/system/rabbitmq-server.service.
[root@master ~]# /sbin/service rabbitmq-server start
Redirecting to /bin/systemctl start rabbitmq-server.service
[root@master ~]# ps -ef|grep rabbitmq
rabbitmq  5609     1 23 14:22 ?        00:00:02 /usr/lib64/erlang/erts-9.3.3/bin/beam.smp -W w -A 64 -MBas ageffcbf -MHas ageffcbf -MBlmbcs 512 -MHlmbcs 512 -MMmcs 30 -P 1048576 -t 5000000 -stbt db -zdbbl 1280000 -K true -- -root /usr/lib64/erlang -progname erl -- -home /var/lib/rabbitmq -- -pa /usr/lib/rabbitmq/lib/rabbitmq_server-3.7.6/ebin -noshell -noinput -s rabbit boot -sname rabbit@master -boot start_sasl -kernel inet_default_connect_options [{nodelay,true}] -sasl errlog_type error -sasl sasl_error_logger false -rabbit lager_log_root "/var/log/rabbitmq" -rabbit lager_default_file "/var/log/rabbitmq/rabbit@master.log" -rabbit lager_upgrade_file "/var/log/rabbitmq/rabbit@master_upgrade.log" -rabbit enabled_plugins_file "/etc/rabbitmq/enabled_plugins" -rabbit plugins_dir "/usr/lib/rabbitmq/plugins:/usr/lib/rabbitmq/lib/rabbitmq_server-3.7.6/plugins" -rabbit plugins_expand_dir "/var/lib/rabbitmq/mnesia/rabbit@master-plugins-expand" -os_mon start_cpu_sup false -os_mon start_disksup false -os_mon start_memsup false -mnesia dir "/var/lib/rabbitmq/mnesia/rabbit@master" -kernel inet_dist_listen_min 25672 -kernel inet_dist_listen_max 25672
rabbitmq  5752     1  0 14:22 ?        00:00:00 /usr/lib64/erlang/erts-9.3.3/bin/epmd -daemon
rabbitmq  5921  5609  0 14:22 ?        00:00:00 erl_child_setup 1024
rabbitmq  5937  5921  0 14:22 ?        00:00:00 inet_gethost 4
rabbitmq  5938  5937  0 14:22 ?        00:00:00 inet_gethost 4
root      5951  5300  0 14:23 pts/0    00:00:00 grep --color=auto rabbitmq
[root@master ~]
# netstat -lntup |grep 5672
-bash: netstat: 未找到命令
[root@master ~]# netstat -lntup |grep 5672
tcp        0      0 0.0.0.0:25672           0.0.0.0:*               LISTEN      5609/beam.smp       
tcp6       0      0 :::5672                 :::*                    LISTEN      5609/beam.smp      

3)查看狀態信息

[root@master ~]# rabbitmqctl status
Status of node rabbit@master ...
[{pid,5609},
 {running_applications,
     [{rabbit,"RabbitMQ","3.7.6"},
      {mnesia,"MNESIA  CXC 138 12","4.15.3"},
      {rabbit_common,
          "Modules shared by rabbitmq-server and rabbitmq-erlang-client",
          "3.7.6"},
      {ranch_proxy_protocol,"Ranch Proxy Protocol Transport","1.5.0"},
      {ranch,"Socket acceptor pool for TCP protocols.","1.5.0"},
      {ssl,"Erlang/OTP SSL application","8.2.6"},
      {public_key,"Public key infrastructure","1.5.2"},
      {asn1,"The Erlang ASN1 compiler version 5.0.5","5.0.5"},
      {inets,"INETS  CXC 138 49","6.5.2"},
      {jsx,"a streaming, evented json parsing toolkit","2.8.2"},
      {os_mon,"CPO  CXC 138 46","2.4.4"},
      {xmerl,"XML parser","1.3.16"},
      {crypto,"CRYPTO","4.2.2"},
      {recon,"Diagnostic tools for production use","2.3.2"},
      {lager,"Erlang logging framework","3.5.1"},
      {goldrush,"Erlang event stream processor","0.1.9"},
      {compiler,"ERTS  CXC 138 10","7.1.5"},
      {syntax_tools,"Syntax tools","2.1.4"},
      {syslog,"An RFC 3164 and RFC 5424 compliant logging framework.","3.4.2"},
      {sasl,"SASL  CXC 138 11","3.1.2"},
      {stdlib,"ERTS  CXC 138 10","3.4.5"},
      {kernel,"ERTS  CXC 138 10","5.4.3"}
]},
 {os,{unix,linux}},
 {erlang_version,
     "Erlang/OTP 20 [erts-9.3.3] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:64] [hipe] [kernel-poll:true]\n"},
 {memory,
     [{connection_readers,0},
      {connection_writers,0},
      {connection_channels,0},
      {connection_other,0},
      {queue_procs,0},
      {queue_slave_procs,0},
      {plugins,5936},
      {other_proc,20754544},
      {metrics,184432},
      {mgmt_db,0},
      {mnesia,72912},
      {other_ets,1873688},
      {binary,55376},
      {msg_index,28720},
      {code,25082003},
      {atom,1041593},
      {other_system,9173572},
      {allocated_unused,8315896},
      {reserved_unallocated,3670016},
      {strategy,rss},
      {total,[{erlang,58272776},{rss,70258688},{allocated,66588672}
]}]},
 {alarms,[]},
 {listeners,[{clustering,25672,"::"},{amqp,5672,"::"}]},
 {vm_memory_calculation_strategy,rss},
 {vm_memory_high_watermark,0.4},
 {vm_memory_limit,3281294131},
 {disk_free_limit,50000000},
 {disk_free,122394349568},
 {file_descriptors,
     [{total_limit,924},{total_used,2},{sockets_limit,829},{sockets_used,0}]},
 {processes,[{limit,1048576},{used,204}]},
 {run_queue,0},
 {uptime,111},
 {kernel,{net_ticktime,60}}]

6、Rabbitmq CLI介紹

自帶多個命令行工具

1)rabbitmqctl  #管理與操做命令

  • 中止節點

  • 訪問節點狀態,有效配置,運行情況檢查

  • 虛擬主機管理

  • 用戶和權限管理

  • 政策管理

  • 列出隊列,鏈接,渠道,交流,消費者

  • 集羣成員管理

[root@master ~]# rabbitmqctl list_bindings    #查看綁定信息
Listing bindings for vhost /...
[root@master ~]# rabbitmqctl list_exchanges   #查看交換器
Listing exchanges for vhost / ...
amq.rabbitmq.trace    topic
amq.match    headers
    direct
amq.headers    headers
amq.direct    direct
amq.rabbitmq.event    topic
amq.topic    topic
amq.fanout    fanout
[root@master ~]# rabbitmqctl list_queues   #查看隊列
Timeout: 60.0 seconds ...
Listing queues for vhost / ...
更多操做內容請參考:http://www.rabbitmq.com/rabbitmqctl.8.html

2)rabbitmq-plugins #是一個管理插件的工具

[root@master ~]# rabbitmq-plugins --help
Usage:
rabbitmq-plugins [-n <node>] [-l] [-q] <command> [<command options>]

General options:
    -n node
    -q quiet
    -l longnames

Default node is "rabbit@server"where `server` is the local hostname. On a host
named "server.example.com", the node name of the RabbitMQ Erlang node will
usually be rabbit@server (unless RABBITMQ_NODENAME has been set to some
non-default value at broker startup time). The output of hostname -s is usually
the correct suffix to use after the "@" sign. See rabbitmq-server(1for
details of configuring the RabbitMQ broker.

Quiet output mode is selected with the "-q" flag. Informational messages are
suppressed when quiet mode is in effect.

If RabbitMQ broker uses long node names for erlang distribution, "longnames"
option should be specified.

Some commands accept an optional virtual host parameter for which
to display results. The default value is "/".

Commands:
    disable <plugin>|--all [--offline] [--online]
    enable <plugin>|--all [--offline] [--online]
    help <command>
    list [pattern] [--verbose] [--minimal] [--enabled] [--implicitly-enabled]
    set [<plugin>] [--offline] [--online]

<timeout> - operation timeout in seconds. Default is "infinity".
參考文章:http://www.rabbitmq.com/rabbitmq-plugins.8.html

3)rabbitmqadmin #它能夠執行一些與WEB界面相同的操做,rabbitmqadmin只是一個專門的HTTP客戶端。

安裝管理插件後,http://{主機名}:15672 /cli/rabbitmqadmin 進行下載
[root@master ~]# wget https://raw.githubusercontent.com/rabbitmq/rabbitmq-management/v3.7.6/bin/rabbitmqadmin
[root@master ~]# cp rabbitmqadmin /usr/local/bin/
[root@master ~]# chmod +x /usr/local/bin/rabbitmqadmin

7、RabbitMQ集羣

RabbitMQ 是用 erlang 開發的,集羣很是方便,由於 erlang 天生就是一門分佈式語言,但其自己並不支持負載均衡。

RabbitMQ 的集羣節點包括:

1)內存節點
內存節點就是將全部數據放在內存,只保存狀態到內存(例外的狀況:持久的queue內容將被保存到 disk)
2)磁盤節點。
磁盤節點將數據放在磁盤,保存狀態到內存和磁盤,內存節點雖然不寫入磁盤,可是它執行比磁盤節點要好,集羣中,只須要一個磁盤節點來保存狀態 就足夠了,若是集羣中只有內存節點,那麼不能中止它們,不然全部的狀態,消息等都會丟失。

圖片

不過,如前文所述,若是在投遞消息時,打開了消息的持久化,那即便是內存節點,數據仍是安全的放在磁盤。一個 RabbitMQ 集羣中能夠共享 user、vhost、queue、exchange 等,全部的數據和狀態都是必須在全部節點上覆制的,一個例外是那些當前只屬於建立它的節點的消息隊列,儘管它們可見且可被全部節點讀取。 RabbitMQ 節點能夠動態地加入到集羣中,一個節點它能夠加入到集羣中,也能夠從集羣環集羣進行一個基本的負載均衡。

Rabbit 模式大概分爲如下三種:

1)單一模式
2)普通模式
3)鏡像模式

單一模式:最簡單的狀況,非集羣模式。
普通模式:默認的集羣模式。

對於 Queue 來講,消息實體只存在於其中一個節點,A、B 兩個節點僅有相同的元數據,即隊列結構。當消息進入 A 節點的 Queue 中後,consumer 從 B 節點拉取時,RabbitMQ 會臨時在 A、B 間進行消息傳輸,把 A 中的消息實體取出並通過 B 發送給 consumer. 因此 consumer 應儘可能鏈接每個節點,從中取消息。即對於同一個邏輯隊列,要在多個節點創建物理 Queue。不然不管 consumer 連 A 或 B,出口總在 A,會產生瓶頸。該模式存在一個問題就是當 A 節點故障後,B 節點沒法取到 A 節點中還未消費的消息實體。若是作了消息持久化,那麼得等 A 節點恢復,而後纔可被消費。

鏡像模式:

把須要的隊列作成鏡像隊列,存在於多個節點,屬於 RabbitMQ 的 HA 方案。
該模式解決了上述問題,其實質和普通模式不一樣之處在於,消息實體會主動在鏡像節點間同步,而不是在 consumer 取數據時臨時拉取。該模式帶來的反作用也很明顯,除了下降系統性能外,若是鏡像隊列數量過多,加之大量的消息進入,集羣內部的網絡帶寬將會被這種同步通信大大消耗掉,所,在對可靠性要求較高的場合中適用。

推薦閱讀

[強烈推薦] 精心整理|公衆號文章目錄大全

企業面試題|最常問的MySQL面試題集合(一)

一晚上之間霸屏朋友圈的《來阿里前 vs 來阿里後》

重磅消息|民工哥公衆號改名啦.........

緩存技術PK|Memcached vs Redis, 選哪個??

打造高逼格、可視化的Docker容器監控系統平臺

ProxySQL+Mysql實現數據庫讀寫分離實戰

容器技術|Docker三劍客之Compose

民工哥的十年故事續集:杭漂十年,今撤霸都!


·end·

相關文章
相關標籤/搜索