一、MQ介紹
1.什么是MQ丹鸿?為什么要用MQ越走?
1.1MQ定義
MessageQueue,消息隊列靠欢。 隊列廊敌,是一種FIFO 先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu)。消息由生產(chǎn)者發(fā)送到MQ進(jìn)行排隊门怪,然后按原來的順序交由消息的消費者進(jìn)行處理骡澈。
例如:QQ和微信就是典型的MQ。
1.2MQ的作用主要有以下三個方面
1)異步
例子:快遞員發(fā)快遞掷空,直接到客戶家效率會很低肋殴。引入菜鳥驛站后,快遞員只需要把快遞放到菜鳥驛站坦弟,就可以繼續(xù)發(fā)其他快遞去了护锤。客戶再按自己的時間安排去菜鳥驛站取快遞酿傍。
作用:異步能提高系統(tǒng)的響應(yīng)速度烙懦、吞吐量。
2)解耦
例子:《Thinking in JAVA》很經(jīng)典赤炒,但是都是英文氯析,我們看不懂,所以需要編輯社可霎,將文章翻譯成其他語言魄鸦,這樣就可以完成英語與其他語言的交流。
作用:
a)服務(wù)之間進(jìn)行解耦癣朗,才可以減少服務(wù)之間的影響。提高系統(tǒng)整體的穩(wěn)定性以及可擴(kuò)展性旺罢。
b)另外旷余,解耦后可以實現(xiàn)數(shù)據(jù)分發(fā)绢记。生產(chǎn)者發(fā)送一個消息后,可以由一個或者多個消費者進(jìn)行消費正卧,并且消費者的增加或者減少對生產(chǎn)者沒有影響蠢熄。
3)削峰
例子:長江每年都會漲水,但是下游出水口的速度是基本穩(wěn)定的炉旷,所以會漲水签孔。引入三峽大壩后,可以把水儲存起來窘行,下游慢慢排水饥追。
作用:以穩(wěn)定的系統(tǒng)資源應(yīng)對突發(fā)的流量沖擊。
2.MQ的優(yōu)缺點
?上面MQ的作用也就是使用MQ的優(yōu)點罐盔。 但是引入MQ也是有他的缺點的:
a)系統(tǒng)可用性降低
系統(tǒng)引入的外部依賴增多但绕,系統(tǒng)的穩(wěn)定性就會變差。一旦MQ宕機(jī)惶看,對業(yè)務(wù)會產(chǎn)生影響捏顺。這就需要考慮如何保證MQ的高可用。
b)系統(tǒng)復(fù)雜度提高
引入MQ后系統(tǒng)的復(fù)雜度會大大提高纬黎。以前服務(wù)之間可以進(jìn)行同步的服務(wù)調(diào)用幅骄,引入MQ后,會變?yōu)楫惒秸{(diào)用本今,數(shù)據(jù)的鏈路就會變得更復(fù)雜昌执。并且還會帶來其他一些問題。比如:如何保證消費不會丟失诈泼?不會被重復(fù)調(diào)用懂拾?怎么保證消息的順序性等問題。
c)消息一致性問題
A系統(tǒng)處理完業(yè)務(wù)铐达,通過MQ發(fā)送消息給B岖赋、C系統(tǒng)進(jìn)行后續(xù)的業(yè)務(wù)處理。如果B系統(tǒng)處理成功瓮孙,C系統(tǒng)處理失敗怎么辦唐断?這就需要考慮如何保證消息數(shù)據(jù)處理的一致性。
3.幾大MQ產(chǎn)品特點比較
常用的MQ產(chǎn)品包括Kafka杭抠、RabbitMQ和RocketMQ脸甘。我們對這三個產(chǎn)品做下簡單的比較,重點需要理解他們的適用場景偏灿。
關(guān)于RabbitMQ的功能特性丹诀,可以在官網(wǎng)(?https://www.rabbitmq.com/?)上看到,包含 Asynchronous Message(異步消息)、Developer Experience(開發(fā)體驗)铆遭、Distributed Deployment(分布式部署)硝桩、Enterprise & Cloud Ready(企業(yè)云部署)、Tools & Plugins(工具和插件)枚荣、Management & Monitoring(管理和監(jiān)控)六大部分碗脊。所以其中的功能是相當(dāng)豐富的,而我們肯定只能關(guān)注重點的部分內(nèi)容橄妆,所以還是要經(jīng)常到官網(wǎng)上去看看的衙伶。
二、Rabbitmq安裝
1.實驗環(huán)境
準(zhǔn)備了三臺虛擬機(jī) 192.168.232.128~130害碾,預(yù)備搭建三臺機(jī)器的集群矢劲。
三臺機(jī)器均預(yù)裝CentOS7 操作系統(tǒng)。分別配置機(jī)器名 worker1蛮原,worker2卧须,worker3。然后需要關(guān)閉防火墻(或者找到RabbitMQ的業(yè)務(wù)端口全部打開儒陨。 5672(amqp端口)花嘶;15672(http Api端口);25672(集群通信端口))蹦漠。
2.版本選擇
RabbitMQ版本椭员,通常與他的大的功能是有關(guān)系的。3.8.x版本主要是圍繞Quorum Queue功能笛园,而3.9.x版本主要是圍繞Streams功能隘击。目前還有3.10.x版本,還在rc階段研铆。我們這次選擇3.9.15版本埋同。
RabbitMQ是基于Erlang語言開發(fā),所以安裝前需要安裝Erlang語言環(huán)境棵红。需要注意下的是RabbitMQ與ErLang是有版本對應(yīng)關(guān)系的凶赁。3.9.15版本的RabbitMQ只支持23.2以上到24.3版本的Erlang。
Docker hub上也已經(jīng)有官方上傳的鏡像逆甜。
3.安裝Erlang語言包
這個語言包虱肄,在windows下的安裝比較簡單,是一個可執(zhí)行程序交煞,直接圖形化安裝就行了咏窿。
Linux上的安裝稍微復(fù)雜,需要有非常多的依賴包素征。簡單起見集嵌,可以下載rabbitmq提供的zero dependency版本萝挤。 下載地址:https://github.com/rabbitmq/erlang-rpm/releases
下載完成后,可以嘗試使用下面的指令安裝:
這樣Erlang語言包就安裝完成了纸淮。 安裝完后可以使用 erl -version 指令檢測下erlang是否安裝成功平斩。
4.安裝RabbitMQ
RabbitMQ的安裝方式有很多亚享,我們采用RPM安裝包的方式咽块。安裝包可以到github倉庫中下載發(fā)布包。下載地址:https://github.com/rabbitmq/rabbitmq-server/releases
然后使用 rpm -Uvh 指令安裝RabbitMQ的rpm包時欺税,會報錯侈沪,需要安裝一個socat。
而這個socat我也在網(wǎng)上下載到了rpm安裝包晚凿。 socat-1.7.3.2-1.1.el7.x86_64.rpm 亭罪,但是安裝時,卻提示需要tcp_wrappers依賴歼秽。
這時应役,當(dāng)然可以按他的提示去安裝依賴包。 但是我就沒有這么做了燥筷。 直接用yum安裝這個socat依賴箩祥。在使用yum時,可以做一個小配置肆氓,將yum源配置成阿里的yum源袍祖,這樣速度會比較快。
socat安裝完成后谢揪,就可以安裝RabbitMQ了蕉陋。
安裝完成后,可以查看下他的安裝情況拨扶。
其他常用的啟停操作:
rabbitmq-server -deched --后臺啟動服務(wù)
rabbitmqctl start_app --啟動服務(wù)
rabbitmqctl stop_app --關(guān)閉服務(wù)
這樣RabbitMQ服務(wù)就啟動完成了凳鬓。 之后可以配置下打開他的Web管理頁面:
可以看到,這時需要重啟RabbitMQ服務(wù)才能生效患民。重啟后缩举,就可以訪問Web控制臺了。?
訪問端口:192.168.232.129:15672酒奶。
這時蚁孔,可以使用默認(rèn)的guest/guest用戶登錄。 但是注意下惋嚎,默認(rèn)情況下杠氢,只允許在localhost本地登錄,遠(yuǎn)程訪問是無法登錄的另伍。這時鼻百,可以創(chuàng)建一個管理員賬戶來登錄绞旅。
?這樣就可以用admin/admin用戶登錄Web控制臺了。
三温艇、RabbitMQ集群搭建
1.集群模式
在RabbitMQ中因悲,一個節(jié)點的服務(wù)其實也是作為一個集群來處理的,在web控制臺的admin-> cluster 中可以看到集群的名字勺爱,并且可以在頁面上修改晃琳。而多節(jié)點的集群有兩種方式:
1)默認(rèn)的普通集群模式
這種模式使用Erlang語言天生具備的集群方式搭建。這種集群模式下琐鲁,集群的各個節(jié)點之間只會有相同的元數(shù)據(jù)卫旱,即隊列結(jié)構(gòu),而消息不會進(jìn)行冗余围段,只存在一個節(jié)點中顾翼。消費時,如果消費的不是存有數(shù)據(jù)的節(jié)點奈泪, RabbitMQ會臨時在節(jié)點之間進(jìn)行數(shù)據(jù)傳輸适贸,將消息從存有數(shù)據(jù)的節(jié)點傳輸?shù)较M的節(jié)點。
很顯然涝桅,這種集群模式的消息可靠性不是很高拜姿。因為如果其中有個節(jié)點服務(wù)宕機(jī)了,那這個節(jié)點上的數(shù)據(jù)就無法消費了苹支,需要等到這個節(jié)點服務(wù)恢復(fù)后才能消費砾隅,而這時,消費者端已經(jīng)消費過的消息就有可能給不了服務(wù)端正確應(yīng)答债蜜,服務(wù)起來后晴埂,就會再次消費這些消息,造成這部分消息重復(fù)消費寻定。 另外儒洛,如果消息沒有做持久化,重啟就消息就會丟失狼速。
并且琅锻,這種集群模式也不支持高可用,即當(dāng)某一個節(jié)點服務(wù)掛了后向胡,需要手動重啟服務(wù)恼蓬,才能保證這一部分消息能正常消費。
所以這種集群模式只適合一些對消息安全性不是很高的場景僵芹。而在使用這種模式時处硬,消費者應(yīng)該盡量的連接上每一個節(jié)點,減少消息在集群中的傳輸拇派。
2)鏡像模式
這種模式是在普通集群模式基礎(chǔ)上的一種增強(qiáng)方案荷辕,這也就是RabbitMQ的官方HA高可用方案凿跳。需要在搭建了普通集群之后再補(bǔ)充搭建。其本質(zhì)區(qū)別在于疮方,這種模式會在鏡像節(jié)點中間主動進(jìn)行消息同步控嗜,而不是在客戶端拉取消息時臨時同步。
并且在集群內(nèi)部有一個算法會選舉產(chǎn)生master和slave骡显,當(dāng)一個master掛了后疆栏,也會自動選出一個來。從而給整個集群提供高可用能力蟆盐。
這種模式的消息可靠性更高承边,因為每個節(jié)點上都存著全量的消息遭殉。而他的弊端也是明顯的石挂,集群內(nèi)部的網(wǎng)絡(luò)帶寬會被這種同步通訊大量的消耗,進(jìn)而降低整個集群的性能险污。這種模式下痹愚,隊列數(shù)量最好不要過多。
2.搭建普通集群
1:需要同步集群節(jié)點中的cookie蛔糯。
默認(rèn)會在 /var/lib/rabbitmq/目錄下生成一個.erlang.cookie拯腮。 里面有一個字符串。我們要做的就是保證集群中三個節(jié)點的這個cookie字符串一致蚁飒。
我們實驗中將worker1和worker3加入到worker2的RabbitMQ集群中动壤,所以將worker2的.erlang.cookie文件分發(fā)到worker1和worker3。
2:將worker1的服務(wù)加入到worker2的集群中淮逻。
首先需要保證worker1上的rabbitmq服務(wù)是正常啟動的琼懊。 然后執(zhí)行以下指令:
- -ram 表示以Ram節(jié)點加入集群。RabbitMQ的集群節(jié)點分為disk和ram爬早。disk節(jié)點會將元數(shù)據(jù)保存到硬盤當(dāng)中哼丈,而ram節(jié)點只是在內(nèi)存中保存元數(shù)據(jù)。
a)由于ram節(jié)點減少了很多與硬盤的交互筛严,所以醉旦,ram節(jié)點的元數(shù)據(jù)使用性能會比較高。但是桨啃,同時车胡,這也意味著元數(shù)據(jù)的安全性是不如disk節(jié)點的。在我們這個集群中照瘾,worker1和worker3都以ram節(jié)點的身份加入到worker2集群里匈棘,因此,是存在單點故障的网杆。如果worker2節(jié)點服務(wù)崩潰羹饰,那么元數(shù)據(jù)就有可能丟失伊滋。在企業(yè)進(jìn)行部署時,性能與安全性需要自己進(jìn)行平衡队秩。
b)這里說的元數(shù)據(jù)僅僅只包含交換機(jī)笑旺、隊列等的定義,而不包含具體的消息馍资。因此筒主,ram節(jié)點的性能提升,僅僅體現(xiàn)在對元數(shù)據(jù)進(jìn)行管理時鸟蟹,比如修改隊列queue乌妙,交換機(jī)exchange,虛擬機(jī)vhosts等時建钥,與消息的生產(chǎn)和消費速度無關(guān)藤韵。
c)如果一個集群中,全部都是ram節(jié)點熊经,那么元數(shù)據(jù)就有可能丟失泽艘。這會造成集群停止之后就啟動不起來了。RabbitMQ會盡量阻止創(chuàng)建一個全是ram節(jié)點的集群镐依,但是并不能徹底阻止匹涮。所以,綜合考慮槐壳,官方其實并不建議使用ram節(jié)點然低,更推薦保證集群中節(jié)點的資源投入,使用disk節(jié)點务唐。
然后同樣把worer3上的rabbitmq加入到worker2的集群中雳攘。
加入完成后,可以在worker2的Web管理界面上看到集群的節(jié)點情況:
也可以用后臺指令查看集群狀態(tài): rabbitmqctl cluster_status
3.搭建鏡像集群
以上就完成了普通集群的搭建绍哎。 再此基礎(chǔ)上来农,可以繼續(xù)搭建鏡像集群。
通常在生產(chǎn)環(huán)境中崇堰,為了減少RabbitMQ集群之間的數(shù)據(jù)傳輸沃于,在配置鏡像策略時,會針對固定的虛擬主機(jī)virtual host來配置海诲。
RabbitMQ中的vritual host可以類比為MySQL中的庫繁莹,針對每個虛擬主機(jī),可以配置不同的權(quán)限特幔、策略等咨演。并且不同虛擬主機(jī)之間的數(shù)據(jù)是相互隔離的。
我們首先創(chuàng)建一個/mirror的虛擬主機(jī)蚯斯,然后再添加給對應(yīng)的鏡像策略:
同樣薄风,這些配置的策略也可以在Web控制臺操作饵较。另外也提供了HTTP API來進(jìn)行這些操作。
這些參數(shù)需要大致了解下遭赂。其中循诉,pattern是隊列的匹配規(guī)則, ^表示全部匹配。 ^ ha \ 這樣的配置表示以ha開頭撇他。通常就用虛擬主機(jī)來區(qū)分就夠了茄猫,這個隊列匹配規(guī)則就配置成全匹配。
然后幾個關(guān)鍵的參數(shù):
HA mode: 可選值 all , exactly, nodes困肩。生產(chǎn)上通常為了保證高可用,就配all锌畸。
a)all : 隊列鏡像到集群中的所有節(jié)點勇劣。當(dāng)新節(jié)點加入集群時,隊列也會被鏡像到這個節(jié)點蹋绽。
b)exactly : 需要搭配一個數(shù)字類型的參數(shù)(ha-params)芭毙。隊列鏡像到集群中指定數(shù)量的節(jié)點。如果集群內(nèi)節(jié)點數(shù)少于這個數(shù)字卸耘,則隊列鏡像到集群內(nèi)的所有節(jié)點。如果集群內(nèi)節(jié)點少于這個數(shù)粘咖,當(dāng)一個包含鏡像的節(jié)點停止服務(wù)后蚣抗,新的鏡像就不會去另外找節(jié)點進(jìn)行鏡像備份了。
c)nodes: 需要搭配一個字符串類型的參數(shù)瓮下。將隊列鏡像到指定的節(jié)點上翰铡。如果指定的隊列不在集群中,不會報錯讽坏。當(dāng)聲明隊列時锭魔,如果指定的所有鏡像節(jié)點都不在線,那隊列會被創(chuàng)建在發(fā)起聲明的客戶端節(jié)點上路呜。
還有其他很多參數(shù)迷捧,可以后面慢慢再了解。
通常鏡像模式的集群已經(jīng)足夠滿足大部分的生產(chǎn)場景了胀葱。雖然他對系統(tǒng)資源消耗比較高漠秋,但是在生產(chǎn)環(huán)境中,系統(tǒng)的資源都是會做預(yù)留的抵屿,所以正常的使用是沒有問題的庆锦。但是在做業(yè)務(wù)集成時,還是需要注意隊列數(shù)量不宜過多轧葛,并且盡量不要讓RabbitMQ產(chǎn)生大量的消息堆積搂抒。
這樣搭建起來的RabbitMQ已經(jīng)具備了集群特性艇搀,往任何一個節(jié)點上發(fā)送消息,消息都會及時同步到各個節(jié)點中求晶。而在實際企業(yè)部署時中符,往往會以RabbitMQ的鏡像隊列作為基礎(chǔ),再增加一些運(yùn)維手段誉帅,進(jìn)一步提高集群的安全性和實用性淀散。
例如,增加keepalived保證每個RabbitMQ的穩(wěn)定性蚜锨,當(dāng)某一個節(jié)點上的RabbitMQ服務(wù)崩潰時档插,可以及時重新啟動起來。另外亚再,也可以增加HA-proxy來做前端的負(fù)載均衡郭膛,通過HA-proxy增加一個前端轉(zhuǎn)發(fā)的虛擬節(jié)點,應(yīng)用可以像使用一個單點服務(wù)一樣使用一個RabbitMQ集群氛悬。這些運(yùn)維方案我們就不做過多介紹了则剃,有興趣可以自己了解下。
四如捅、RabbitMQ基礎(chǔ)使用
RabbitMQ搭建完成后棍现,可以在Web控制臺上選擇Exchange或者Queue來發(fā)送消息了,我們可以簡單體驗下镜遣,也可以留到下一部分編程模型時再深入體驗己肮。
例如,先在Admin菜單悲关,配置admin用戶可以操作/mirror虛擬機(jī)谎僻。
然后,創(chuàng)建一個經(jīng)典隊列寓辱。
創(chuàng)建完成后艘绍,選擇這個test1隊列,就可以在頁面上直接發(fā)送消息以及消費消息了秫筏。
在整體使用過程中你會發(fā)現(xiàn)诱鞠,對于隊列,有Classic跳昼、Quorum般甲、Stream三種類型,其中鹅颊,Classic和Quorum兩種類型敷存,使用上幾乎是沒有什么區(qū)別的。但是Stream隊列就無法直接消費消息了。這種區(qū)別也會帶到后面的使用過程中锚烦。
然后觅闽,RabbitMQ的各種管理功能,整理上還是非常簡單的涮俄,幾乎所有的配置都可以在Web管理頁面上直觀的看到蛉拙,并直接完成操作。同時彻亲,這些管理功能孕锄,也都可以通過后端的命令行工具進(jìn)行。在進(jìn)行體驗的過程中苞尝,也可以自行嘗試了解后端配置的各種指令畸肆。每個指令都有help幫助文檔,大家可以自行嘗試了解宙址。