RabbitMQ之集羣搭建

RabbitMQ之集羣搭建

-Author:dongdong

-Email: [email protected]

RabbitMQ 高可用集羣搭建及電商平臺使用經驗總結:

  1. 面向EDA(事件驅動架構)的方式來設計你的消息
  2. AMQP routing key的設計
  3. RabbitMQ cluster搭建
  4. Mirror queue policy設置
  5. 兩個不錯的RabbitMQ plugin 大型應用插件(Sharding、Rederation)
  6. Queue鏡像失敗手動同步
  7. 各集羣配置同步方式(RabbitMQ export\import)
  8. 客戶端連接方式(儘量採用AMQP組來動態鏈接)
  9. RabbitMQ 產線二次產品化封裝(消息補償、發送消息持久化、異常處理、監控頁面、重複消息剔除)

1.面向EDA(事件驅動架構)的方式來設計你的消息

在通常情況下你在使用消息中間件的時候,都是未經設計的使用,你沒有把應用架構和系統架構邊界搞清楚。消息中間件只是一個純粹的技術工具,當你引入的時候是站在應用架構的角度引入的。這是架構的角度,也是架構的上帝視角,這樣你就不會用到最後發現越來越混亂,而且也無法結合軟件模式、方法論、最佳實踐來綜合提升系統的架構能力。

EDA(Event Driven Architecture,EDA) 事件驅動架構,它是一種用來在SOA或者Micro service中進行的架構模式。它的好處有幾個,柔性具有很高的伸縮性。

既然要EDA就要規劃好你當前的系統邊界之內有多少業務實體,這些實體是圍繞着領域模型而得來。所以這裏不要很主觀的就定義一些你認爲的事件,這些事件要根據業務實體中的對象來設計。業務實體起碼是有唯一Identity的。比如,訂單、商品,圍繞着這些實體展開,訂單可能有幾個狀態是比較常用的,創建、支付、配送、取消。商品可能有價格、關鍵屬性修改等等。這些實體的抽象和提煉取決於你當前的業務。

(有關這方面內容可以參考:《領域驅動設計》、《探索CQRS和事件源》)

這些是相對理論的指導思想,有了這些之後你可以落地你的Rabbitmq,這樣你就不會跑偏了。比如,你的消息名稱不會是看起來沒結構和層次的,deliveryMssage(配送消息)。而是應該,order.delivery.ondeliveryEvented(訂單.配送.配送完成事件)這樣的結構。

當你的層次結構不滿足業務需求的時候,你可能還需要進一步明確事件範圍,order.viporder.delivery.ondeliveryEvented(訂單.VIP訂單.配送.配送完成事件)。

![202205-20161210194527538-1135172120](C:\Users\ldyld\Pictures\Camera Roll\202205-20161210194527538-1135172120.png)

上圖是一個事件驅動的基本場景,它最矚目的幾個特性就是這幾個,首先是異步化的,可以大大提高系統的抗峯值能力。然後就是解耦,這不用說了,設計模式裏的觀察者模式沒有人不知道它的好處。伸縮性,可以按需scaleout,比如rabbitmq的node可以很方便的加入。最終一致性解決了分佈式系統的CAP定理的問題。

2.AMQP routing key的設計

AMQP協議中約定了routing key的設計和交互。爲了實現訂閱發佈功能,我們需要某種方式能夠訂閱自己所感興趣的事件。所以在AMQP中的Binding中,可以根據routing key來進行模式匹配。所以,這裏可以結合amqp routingkey與領域事件,發出來的事件就相當於amqp中的routingkey,這樣可以完美的結合起來。

你的事件肯定是隨着業務發展逐漸增加的,而這個事件集合也沒辦法在一開始就定義清楚,所以這裏有一個需要注意的就是,綁定的時候千萬不要寫死具體的routing key。比如,order.delivery.OnDeliveryEvented,這是訂單配送,此時你Binding的時候routingkey就寫成了”order.delivery.OnDeliveryEvented”。未來訂單事件一擴展,就會很麻煩,不相關的事件都被訂閱到,無法細化或者事件你無法獲取到,因爲routingkey改變了。所以在綁定的時候記住具體點綁定,也就是藉助字符串的模式匹配綁定,比如,.delivery.,*.onDeliveryEvented”這樣。將來越來越多的routingkey和event出來都不會影響你的綁定。你只需要根據自己的關心程度,綁定在事件的不同層級上即可。

![202205-20161210194528319-754960138](C:\Users\ldyld\Pictures\Camera Roll\202205-20161210194528319-754960138.png)

上圖中,orderBinding綁定了order事件,它訂閱了頂級事件,也就是說未來任何類型的訂單都可以被訂閱到,比如,order.normalorder.delivery.onDeliveryEvent也可以被訂閱到。而viporderBinding訂閱了viporder事件,如果發送了一個order.normalorder.delivery.onDeliveryEvent就跟它沒關係了。

3.RabbitMQ cluster搭建

搞清楚了應用架構的事情,我們開始着手搭建RabbitMQ cluster。rabbitmq這款AMQP產品是用erlang開發的,那麼我們稍微介紹下erlang。

我第一次正式接觸erlang就是從rabbitmq開始的,一開始並沒有太多感覺到特別的地方,後來才明白越明白越發現挺喜歡這門語言的。喜歡的理由就是,它是天然的分佈式語言。這句話說起來好像挺平常的,但是當你明白了.erlang.cookie機制之後才恍然大悟。瞬間頓悟了,爲什麼要用erlang來搞rabbitmq,而是它真的很適合信息交換之類的軟件。erlang是愛立信公司開發的專門用來開發高性能信息交換機的,想想也會覺得那些軟件的性能和穩定性要求是極高的。RabbitMQ的節點發現和互連真的很方便,這在erlang的虛擬機中就集成了,而且具有高度容錯能力。反正我對它很有好感。

還有一點值得驕傲的是RabbitMQ是偉大的pivotal公司的,你應該知道pivotal公司是幹什麼的,如果你還不清楚建議你立刻google下。(RabbtiMQ 官網:<http://www.rabbitmq.com/&gt;)

3.1.安裝erlang & RabbitMQ

要想安裝RabbitMQ,首先需要安裝和配置好它的宿主環境erlang。去erlang官網下載好erlang otp_src源碼包,然後在本地執行源碼安裝。(erlang官網:<http://www.erlang.org/&gt;)

1.安裝依賴環境:

1)安裝GCC GCC-C++ Openssl等模塊,安裝過就不需要安裝了

[root@mq]# yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel openssl-devel

2)安裝ncurses

[root@mq]# yum -y install ncurses-devel 

2.下載erlang:

官網下載:http://erlang.org/download/

或者直接下載

[root@mq]# wget http://erlang.org/download/otp_src_21.2.tar.gz
[root@mq]# tar xzvf otp_src_21.2.tar.gz 
[root@mq]# cd otp_src_21.2

執行

[root@mq]# ./configure --prefix /usr/local/soft

進行環境的檢查和安裝路徑的選擇

[root@mq otp_src_21.2]# make &&  make install

查看安裝位置:

[root@mq otp_src_21.2]# find / -name erlang

/root/otp_src_21.2/lib/jinterface/java_src/com/ericsson/otp/erlang
/root/otp_src_21.2/bootstrap/lib/jinterface/priv/com/ericsson/otp/erlang
/usr/local/soft/lib/erlang

配置環境變量:

在/etc/profile文件最後加上

[root@mq ~]# vim /etc/profile

export PATH=$PATH:/usr/local/soft/lib/erlang/bin

[root@mq ~]# source /etc/profile

查看是否安裝成功:

[root@mq otp_src_21.2]# erl

Erlang/OTP 21 [erts-10.2][source] [64-bit][smp:1:1] [ds:1:1:10][async-threads:1] [hipe]

Eshell V10.2  (abort with ^G)
1>

接下來安裝RabbitMQ

RabbitMQ官網提供了新版的rpm包(http://www.rabbitmq.com/download.html),但是安裝的時候會提示需要erlang版本>=19.3,然而默認yum倉庫中的版本較低。
其實RabbitMQ在github上有提供新的erlang包(https://github.com/rabbitmq/erlang-rpm

也可以直接加到yum源中

[root@mq ~]# vim /etc/yum.repos.d/rabbitmq-erlang.repo

[rabbitmq-erlang]
name=rabbitmq-erlang
baseurl=https://dl.bintray.com/rabbitmq/rpm/erlang/20/el/7
gpgcheck=1
gpgkey=https://dl.bintray.com/rabbitmq/Keys/rabbitmq-release-signing-key.asc
repo_gpgcheck=0
enabled=1
[root@mq ~]# yum clean all
[root@mq ~]# yum makecache

然後下載RabbitMQ的RPM包(http://www.rabbitmq.com/download.html)

這裏是centos7的版本 
[root@mq ~]# wget https://dl.bintray.com/rabbitmq/all/rabbitmq-server/3.7.4/rabbitmq-server-3.7.4-1.el7.noarch.rpm 
[root@mq ~]# yum  -y install rabbitmq-server-3.7.4-1.el7.noarch.rpm yum會自動去源裏安裝依賴包

安裝到這裏就完成了,下面進行簡單的配置

 啓動RabbitMQ服務
[root@mq ~]# service rabbitmq-server start
Redirecting to /bin/systemctl start rabbitmq-server.service
 狀態查看
[root@mq ~]# rabbitmqctl status
Status of node rabbit@mq2 ...
[{pid,52995},
 {running_applications,
     [{rabbit,"RabbitMQ","3.7.4"},
      {mnesia,"MNESIA  CXC 138 12","4.15.3.2"},
      {rabbit_common,
          "Modules shared by rabbitmq-server and rabbitmq-erlang-client",
          "3.7.4"},
      {ranch_proxy_protocol,"Ranch Proxy Protocol Transport","1.4.4"},
      {ranch,"Socket acceptor pool for TCP protocols.","1.4.0"},
      {ssl,"Erlang/OTP SSL application","8.2.6.4"},
      {public_key,"Public key infrastructure","1.5.2"},
      {crypto,"CRYPTO","4.2.2.2"},
      {asn1,"The Erlang ASN1 compiler version 5.0.5.1","5.0.5.1"},
      {xmerl,"XML parser","1.3.16"},
      {inets,"INETS  CXC 138 49","6.5.2.4"},
      {os_mon,"CPO  CXC 138 46","2.4.4"},
      {jsx,"a streaming, evented json parsing toolkit","2.8.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.2"},
      {syntax_tools,"Syntax tools","2.1.4.1"},
      {sasl,"SASL  CXC 138 11","3.1.2"},
      {stdlib,"ERTS  CXC 138 10","3.4.5.1"},
      {kernel,"ERTS  CXC 138 10","5.4.3.2"}]},
 {os,{unix,linux}},
 {erlang_version,
     "Erlang/OTP 20 [erts-9.3.3.6] [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,5864},
      {other_proc,19366464},
      {metrics,184432},
      {mgmt_db,0},
      {mnesia,72816},
      {other_ets,1864576},
      {binary,56152},
      {msg_index,28528},
      {code,24980384},
      {atom,1041593},
      {other_system,9156871},
      {allocated_unused,12563024},
      {reserved_unallocated,667648},
      {strategy,rss},
      {total,[{erlang,56757680},{rss,69988352},{allocated,69320704}]}]},
 {alarms,[]},
 {listeners,[{clustering,25672,"::"},{amqp,5672,"::"}]},
 {vm_memory_calculation_strategy,rss},
 {vm_memory_high_watermark,0.4},
 {vm_memory_limit,408762777},
 {disk_free_limit,50000000},
 {disk_free,14542917632},
 {file_descriptors,
     [{total_limit,924},{total_used,2},{sockets_limit,829},{sockets_used,0}]},
 {processes,[{limit,1048576},{used,199}]},
 {run_queue,0},
 {uptime,41},
 {kernel,{net_ticktime,60}}]
 啓用插件
[root@mq ~]# rabbitmq-plugins enable rabbitmq_management
The following plugins have been configured:
  rabbitmq_management
  rabbitmq_management_agent
  rabbitmq_web_dispatch
Applying plugin configuration to rabbit@mq2...
The following plugins have been enabled:
  rabbitmq_management
  rabbitmq_management_agent
  rabbitmq_web_dispatch

started 3 plugins.
 重啓服務
[root@mq ~]# service rabbitmq-server restart
Redirecting to /bin/systemctl restart rabbitmq-server.service
 添加帳號:name 密碼:passwd
[root@mq ~]# rabbitmqctl add_user name passwd
Adding user "name" ...
 賦予其administrator角色
[root@mq ~]# rabbitmqctl set_user_tags name administrator
Setting tags for user "name" to [administrator] ...
  設置權限
[root@mq ~]# rabbitmqctl set_permissions -p / name ".*" ".*" ".*"
Setting permissions for user "name" in vhost "/" ...

然後就能夠訪問http://ip:15672進入web管理頁面了(外部訪問別忘記修改防火牆)。

2

RabbitMQ之集羣搭建

注:以上步驟本人親自試過。如有其他錯誤請訪問http://www.baidu.com

保證兩個節點都是可以正常工作的。下面我們就將這兩個節點連接起來形成高可用的cluster,這樣我們就可以讓我們的exchange、queue在這兩個節點之間複製,形成高可用的queue。

cd 到你的home目錄下,裏面有一個隱藏的.erlang.cookie文件,這就是我在前面介紹erlang時候提到的,這個文件是erlang用來發現和互連的基礎。我們需要做的很簡單,將兩個節點中的.erlang.cookie設置成一樣的。這是erlang的約定,一樣的cookie hash key他認爲是合法和正確的連接。

找不到的話就選擇用 find / -name .erlang.cookie 查找

root@mq2 ]# find / -name .erlang.cookie

/var/lib/rabbitmq/.erlang.cookie

[root@mq2 otp_src_21.2]# cd /var/lib/rabbitmq/

[root@mq2 rabbitmq]# ls -a

.  ..  config  .erlang.cookie  mnesia  schema

.erlang.cookie默認是隻讀的,你需要修改下寫入權限,然後複製粘貼下cookie 字符串即可。

[root@mq2 rabbitmq]# chmod u+w .erlang.cookie

配置好了之後接下來配置hosts文件,erlang會使用hosts文件裏的配置去發現節點。

vim /etc/hosts

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.2.182   rabbitmq_node2
192.168.2.152   rabbitmq_node1

保證同樣的配置在所有的節點上都是相同的。驗證你配置的正確不正確你只需要在你的機器上ping rabbitmq_node1,試下請求的ip是不是你配置的即可。按照DNS的請求原理,hosts是最高優先權,除非瀏覽器有緩存,你直接用ping就不會有問題的。

選擇一個節點stop,然後連接到另外節點。

[root@mqrabbitmq]# rabbitmqctl stop_app

Stopping rabbit application on node rabbit@mq2 ...

[root@rabbitmq_node1 ~]# rabbitmqctl join_cluster rabbit@rabbitmq_node2

Clustering node rabbit@rabbitmq_node1 with rabbit@rabbitmq_node2

如若報錯:

  • Clustering node rabbit@rabbitmq_node1 with rabbit@rabbitmq_node2
    Error: unable to perform an operation on node 'rabbit@rabbitmq_node2'. Please see diagnostics information and suggestions below.
    
    Most common reasons for this are:
    
    - Target node is unreachable (e.g. due to hostname resolution, TCP connection or firewall issues)
    - CLI tool fails to authenticate with the server (e.g. due to CLI tool's Erlang cookie not matching that of the server)
    - Target node is not running
    
    In addition to the diagnostics info below:
    
    - See the CLI, clustering and networking guides on http://rabbitmq.com/documentation.html to learn more
    - Consult server logs on node rabbit@rabbitmq_node2
    
    DIAGNOSTICS
    
    attempted to contact: [rabbit@rabbitmq_node2]
    
    rabbit@rabbitmq_node2:
    
    - connected to epmd (port 4369) on rabbitmq_node2
    - epmd reports node 'rabbit' uses port 25672 for inter-node and CLI tool traffic 
    - TCP connection succeeded but Erlang distribution failed 
    - Authentication failed (rejected by the remote node), please check the Erlang cookie
    
    Current node details:
    
    - node name: rabbitmqcli70@rabbitmq_node1
    - effective user's home directory: /var/lib/rabbitmq
    - Erlang cookie hash: D5jFGsQ9svZgg1Q+H9fLgA==

    一、查看/etc/hosts是否正確

    二、查看cat /var/lib/rabbitmq/.erlang.cookie裏面的數據是否一致,如若不一致請修改一致。

節點已經連接成功。

如若是第一個創建的用戶登錄不進去請重新建立一個administrator賬戶,進行進去。

4默認情況下節點佔用的memory是總內存的40%,可以根據自己的用途仔細研究rabbitmq的配置項。爲了提高性能,不需要兩個節點都是disc的節點,所以我們需要啓動一個節點爲RAM模式。

[root@rabbitmq_node2 ~]#  rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbitmq_node2 ...

[root@rabbitmq_node2 ~]# rabbitmqctl change_cluster_node_type  ram
Turning rabbit@rabbitmq_node2 into a ram node

[root@rabbitmq_node2 ~]# rabbitmqctl start_app
Starting node rabbit@rabbitmq_node2 ...
 completed with 3 plugins.

RabbitMQ之集羣搭建

4.Mirror queue policy設置

節點是準備好了,接下來我們需要設置exchange、queue 高可用策略,這樣才能真的做到高可用。現在是物理上的機器或者說虛擬機節點是高可用的,但是裏面的對象需要我們進行配置策略。

RabbitMQ支持很好的策略模式,需要管理員才能操作。

首先我們需要創建一個屬於自己業務範圍內的vhost,標示一個邏輯上的獨立空間,所有的賬號、策略、隊列都是強制在某個虛擬機裏的。我創建了一個common vhost。

開始添加policie。![](C:\Users\ldyld\Pictures\Camera Roll\1545882840(1).png)

![](C:\Users\ldyld\Pictures\Camera Roll\202205-20161210194532476-1243228310.png)

最主要是Apply to ,可以作用在exchange或者queues上,當然也可以包含這兩個。策略選擇還是比較豐富的,最常用的是HAmode,還有MessageTTL(消息的過期時間)。這些策略按照幾個維度分組了,有跟高可用相關的,有Federation(集羣之間同步消息)相關的 ,有Queue相關的,還有Exchange相關的。可以根據的業務場景進行調整。

![](C:\Users\ldyld\Pictures\Camera Roll\1545889849(1).png)

我們定義了策略的匹配模式.order.,這樣可以避免將所有的exchange、queue都鏡像了

![](C:\Users\ldyld\Pictures\Camera Roll\1545890950(1).png)

我們定義了策略的匹配模式.order.,這樣可以避免將所有的exchange、queue都鏡像了。

![](C:\Users\ldyld\Pictures\Camera Roll\202205-20161210194534788-83779070.png)

我們新建了一個ex.order.topic exchange,它的features中應用了exchange_queue_ha策略。(相同的策略是無法疊加使用的。)其他的exchange並沒有應用這個策略,是因爲我們的pattern限定了只匹配.order.的名稱。

![](C:\Users\ldyld\Pictures\Camera Roll\1545891585(1).png)

創建一個qu.order.crm queue,注意看它的node屬性裏有一個”Synchronised mirrors:rabbit@rabbitmq_node2“鏡像複製。features裏也應用了exchange_queue_ha策略。這個時候,隊列其實在兩個節點裏都是有的,雖然我們創建的時候是在rabbit@rabbitmq_node1裏的,但是它會複製到集羣裏的其他節點。在創建HAmode的時候可以提供HA params參數,來限定複製節點的個數,這通常用來提高性能和HA之間的平衡。

5.兩個不錯的RabbitMQ plugin 大型應用插件(Sharding、Rederation)

在rabbitmq-plugins中有兩個plugin還是可以試着研究研究的。rabbitmq-plugins list。

[root@rabbitmq_node2 ~]# rabbitmq-plugins list

 Configured: E = explicitly enabled; e = implicitly enabled
 | Status: * = running on rabbit@rabbitmq_node2
 |/
[  ] rabbitmq_amqp1_0                  3.7.4
[  ] rabbitmq_auth_backend_cache       3.7.4
[  ] rabbitmq_auth_backend_http        3.7.4
[  ] rabbitmq_auth_backend_ldap        3.7.4
[  ] rabbitmq_auth_mechanism_ssl       3.7.4
[  ] rabbitmq_consistent_hash_exchange 3.7.4
[  ] rabbitmq_event_exchange           3.7.4
[  ] rabbitmq_federation               3.7.4
[  ] rabbitmq_federation_management    3.7.4
[  ] rabbitmq_jms_topic_exchange       3.7.4
[E*] rabbitmq_management               3.7.4
[e*] rabbitmq_management_agent         3.7.4
[  ] rabbitmq_mqtt                     3.7.4
[  ] rabbitmq_peer_discovery_aws       3.7.4
[  ] rabbitmq_peer_discovery_common    3.7.4
[  ] rabbitmq_peer_discovery_consul    3.7.4
[  ] rabbitmq_peer_discovery_etcd      3.7.4
[  ] rabbitmq_peer_discovery_k8s       3.7.4
[  ] rabbitmq_random_exchange          3.7.4
[  ] rabbitmq_recent_history_exchange  3.7.4
[  ] rabbitmq_sharding                 3.7.4
[  ] rabbitmq_shovel                   3.7.4
[  ] rabbitmq_shovel_management        3.7.4
[  ] rabbitmq_stomp                    3.7.4
[  ] rabbitmq_top                      3.7.4
[  ] rabbitmq_tracing                  3.7.4
[  ] rabbitmq_trust_store              3.7.4
[e*] rabbitmq_web_dispatch             3.7.4
[  ] rabbitmq_web_mqtt                 3.7.4
[  ] rabbitmq_web_mqtt_examples        3.7.4
[  ] rabbitmq_web_stomp                3.7.4
[  ] rabbitmq_web_stomp_examples       3.7.4

rabbitmq_sharding、rabbitmq_federation,rabbitmq_sharding的版本有點低了,github地址:<https://github.com/rabbitmq/rabbitmq-sharding&gt;

![](C:\Users\ldyld\Pictures\Camera Roll\202205-20161210194535085-1405490880.png)

Rederation 可以用來進行跨cluster或者node之間同步消息。<http://www.rabbitmq.com/federated-exchanges.html&gt;

這個用來在不同的domain之間傳遞消息還是個不錯的解決方案,跨機房或者跨網絡區域,訂閱別人的rabbitmq消息始終不太穩定,可以用這種方式來傳遞消息。

![](C:\Users\ldyld\Pictures\Camera Roll\202205-20161210194535788-1801747645.png)

6.Queue鏡像失敗手動同步

有時候可能由於各種原因導致queue mirror失敗,這個時候可以手動進行同步,而不是像其他分佈式系統來重啓節點或者重建數據。

![](C:\Users\ldyld\Pictures\Camera Roll\202205-20161210194537194-581264582.png)

![](C:\Users\ldyld\Pictures\Camera Roll\202205-20161210194538960-1663001934.png)

![](C:\Users\ldyld\Pictures\Camera Roll\202205-20161210194539741-1598509320.png)

8.客戶端連接方式(儘量採用AMQP組來動態鏈接)

由於RabbitMQ是AMQP協議的實現,所以在進行遠程連接的時候儘量採用amqp協議的方式連接。

var amqpList = new List<AmqpTcpEndpoint> 
{ 
    new AmqpTcpEndpoint(new Uri("amqp://192.168.0.105:5672")), 
    new AmqpTcpEndpoint(new Uri("amqp://192.168.0.107:5672")) 
};

關於集羣的vip方案其實也是需要綜合考慮的,如果是統一的地址會面臨三個問題,DNS、LoadBalance、VIP,這三個點都有可能導致集羣連接不上。現在越來越多的方案傾向於在客戶端做負載和故障轉移,這有很多好處,消除了中間節點帶來的故障概率。如果這三個點加在一起出現的可用性指標肯定是比直接在客戶端連接的低的多。

我們碰到最多就是VIP的問題,這類系統的VIP不同於數據庫,數據庫的master\slave大多都是要人工check後才切換,不會隨便自動的切換主從庫。而非數據庫的VIP大多都是Keepalived自動檢測切換,這帶來一些列問題,包括連接重試、心跳保持。這只是VIP的出錯場景之一。還有LoadBalance帶來的問題,DNS出錯的可能性也是很大。所以我傾向於使用客戶端來做這些。

![](C:\Users\ldyld\Pictures\Camera Roll\202205-20161210194540788-1994426582.png)

有幾個地方很重要,第一個就是消息的Persistent持久化狀態要帶上,第二個就是ContentType,這個屬性很實用,方便你查看消息的正文。

![](C:\Users\ldyld\Pictures\Camera Roll\202205-20161210194541601-158848831.png)

如果沒設置,默認是null。

第三個就是AutomaticRecoveryEnabled,自動連接重試,這致命重要。當上面的VIP切換之後這個可以保命。第四個就是TopologyRecoveryEnabled,重新恢復Exchange、queue、binding。在出現網絡斷開之後,一旦恢復連接就會恢復這些設置以保證是最新的設置。

9.RabbitMQ 產線二次產品化封裝(消息補償、發送消息持久化、異常處理、監控頁面、重複消息剔除)

不管rabbitmq保證的多麼強壯,多麼高可用,記住一定要有備用方案。

在之前我寫了一篇文章,WebAPi的可視化輸出模式(RabbitMQ、消息補償相關)——所有webapi似乎都缺失的一個功能

說了就是消息的持久化和補償。
![](C:\Users\ldyld\Pictures\Camera Roll\202205-20161210194542304-11838963.png)

一旦將發送和接受的消息持久化之後我們能做到事情就比較多了。消息補償是可以做的,異常也不用擔心。但是在發送消息的時候一定要注意,是先持久化消息在業務邏輯處理。爲了應對特殊活動的監控,還可以開發一定的業務來監控消息的接受和處理的數量,然後自動補償。

在開發補償程序的時候有一個邏輯挺饒人的,當你對某一個消息進行補償的時候會多出發送消息,而接受的消息肯定是比你發送的少。所以你在統計的時候記得DISTINCT下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章