Nginx是一個(gè) 輕量級(jí)/高性能的反向代理Web服務(wù)器,他實(shí)現(xiàn)非常高效的反向代理、負(fù)載平衡,他可以處理2-3萬(wàn)并發(fā)連接數(shù),官方監(jiān)測(cè)能支持5萬(wàn)并發(fā),現(xiàn)在中國(guó)使用nginx網(wǎng)站用戶有很多,例如:新浪、網(wǎng)易、 騰訊等。
1)跨平臺(tái)、配置簡(jiǎn)單、方向代理、高并發(fā)連接:處理2-3萬(wàn)并發(fā)連接數(shù),官方監(jiān)測(cè)能支持5萬(wàn)并發(fā),內(nèi)存消耗小:開啟10個(gè)nginx才占150M內(nèi)存 ,nginx處理靜態(tài)文件好,耗費(fèi)內(nèi)存少。
2)Nginx內(nèi)置的健康檢查功能:如果有一個(gè)服務(wù)器宕機(jī),會(huì)做一個(gè)健康檢查,再發(fā)送的請(qǐng)求就不會(huì)發(fā)送到宕機(jī)的服務(wù)器了。重新將請(qǐng)求提交到其他的節(jié)點(diǎn)上。
優(yōu)點(diǎn):1)占內(nèi)存小,可實(shí)現(xiàn)高并發(fā)連接,處理響應(yīng)快
2)可實(shí)現(xiàn)http服務(wù)器、虛擬主機(jī)、方向代理、負(fù)載均衡
3)Nginx配置簡(jiǎn)單,可以不暴露正式的服務(wù)器IP地址
缺點(diǎn):1)動(dòng)態(tài)處理差:nginx處理靜態(tài)文件好,耗費(fèi)內(nèi)存少,但是處理動(dòng)態(tài)頁(yè)面則很雞肋,所以前端一般用nginx作為反向代理抗住壓力。
1)http服務(wù)器。Nginx是一個(gè)http服務(wù)可以獨(dú)立提供http服務(wù)。可以做網(wǎng)頁(yè)靜態(tài)服務(wù)器。
2)虛擬主機(jī)。可以實(shí)現(xiàn)在一臺(tái)服務(wù)器虛擬出多個(gè)網(wǎng)站,例如個(gè)人網(wǎng)站使用的虛擬機(jī)。
3)反向代理,負(fù)載均衡。當(dāng)網(wǎng)站的訪問(wèn)量達(dá)到一定程度后,單臺(tái)服務(wù)器不能滿足用戶的請(qǐng)求時(shí),需要用多臺(tái)服務(wù)器集群可以使用nginx做反向代理。并且多臺(tái)服務(wù)器可以平均分擔(dān)負(fù)載,不會(huì)應(yīng)為某臺(tái)服務(wù)器負(fù)載高宕機(jī)而某臺(tái)服務(wù)器閑置的情況。
4)nginx中也可以配置安全管理、比如可以使用Nginx搭建API接口網(wǎng)關(guān),對(duì)每個(gè)接口服務(wù)進(jìn)行攔截。
因?yàn)樗氖录幚頇C(jī)制:異步非阻塞事件處理機(jī)制運(yùn)用了epoll模型,提供了一個(gè)隊(duì)列,排隊(duì)解決。
server{ # 第一個(gè)Server區(qū)塊開始,表示一個(gè)獨(dú)立的虛擬主機(jī)站點(diǎn)
? ? listen ? 80; ? ? ??? ??? ? ? ? ? ?# 提供服務(wù)的端口,默認(rèn)80
? ? server_name ?localhost; ? # 提供服務(wù)的域名主機(jī)名
? ? location / { ? ? ? ? ? ??? ? ? ? ? ?# 第一個(gè)location區(qū)塊開始
? ? ? ? root ? html; ? ? ? ?? ??? ? # 站點(diǎn)的根目錄,相當(dāng)于Nginx的安裝目錄
? ? ? ? index ?index.html index.htm; ? ??? ?# 默認(rèn)的首頁(yè)文件,多個(gè)用空格分開
? ? } ? ? ? ? ??? ??? ??? ??? ? # 第一個(gè)location區(qū)塊結(jié)果
} ? ? ?
首先,Nginx 在啟動(dòng)時(shí),會(huì)解析配置文件,得到需要監(jiān)聽的端口與 IP 地址,然后在 Nginx 的 Master 進(jìn)程里面先初始化好這個(gè)監(jiān)控的Socket(創(chuàng)建 S ocket,設(shè)置 addr、reuse 等選項(xiàng),綁定到指定的 ip 地址端口,再 listen 監(jiān)聽)。正向代理就是一個(gè)人發(fā)送一個(gè)請(qǐng)求直接就到達(dá)了目標(biāo)的服務(wù)器。
反方代理就是請(qǐng)求統(tǒng)一被Nginx接收,nginx反向代理服務(wù)器接收到之后,按照一定的規(guī)則分發(fā)給了后端的業(yè)務(wù)處理服務(wù)器進(jìn)行處理了。
反向代理服務(wù)器可以隱藏源服務(wù)器的存在和特征。它充當(dāng)互聯(lián)網(wǎng)云和web服務(wù)器之間的中間層。這對(duì)于安全方面來(lái)說(shuō)是很好的,特別是當(dāng)您使用web托管服務(wù)時(shí)。
①輪詢:Nginx根據(jù)請(qǐng)求發(fā)送來(lái)的順序,依次把請(qǐng)求循環(huán)的發(fā)給列表中的服務(wù)器;
②按權(quán)重:提前為每個(gè)服務(wù)器指定一個(gè)權(quán)重,Nginx在分配請(qǐng)求時(shí)會(huì)優(yōu)先把請(qǐng)求分配給權(quán)重較高的服務(wù)器(一般選擇給性能較好的服務(wù)器賦予較大的權(quán)重);
③hash綁定:可以為每個(gè)ip地址使用hash綁定,這樣每個(gè)訪客訪問(wèn)的服務(wù)器固定,可以解決seeion存儲(chǔ)問(wèn)題;常見的用法是對(duì)用戶的IP或者ID進(jìn)行這個(gè)策略,然后「負(fù)載均衡器」就能保證同一個(gè)IP來(lái)源或者同一個(gè)用戶永遠(yuǎn)會(huì)被送到同一個(gè)后端服務(wù)器上了,一般用于處理緩存、會(huì)話等功能的時(shí)候特別好用;
④響應(yīng)策略:按后端服務(wù)器響應(yīng)時(shí)間,響應(yīng)快的優(yōu)先分配;也就是說(shuō),不管后端服務(wù)器負(fù)載高不高,也不管配置如何,只要覺(jué)得這個(gè)服務(wù)器在當(dāng)前時(shí)刻能最快的響應(yīng)用戶的請(qǐng)求,那么就優(yōu)先把請(qǐng)求轉(zhuǎn)發(fā)給它,這樣的話,對(duì)于用戶而言,體驗(yàn)也最好。那「負(fù)載均衡器」是怎么知道哪一臺(tái)后端服務(wù)在當(dāng)前時(shí)刻響應(yīng)能力最佳呢?這就需要「負(fù)載均衡器」不停的去統(tǒng)計(jì)每一臺(tái)后端服務(wù)器對(duì)請(qǐng)求的處理速度了,比如一分鐘統(tǒng)計(jì)一次,生成一個(gè)后端服務(wù)器處理速度的排行榜。然后「負(fù)載均衡器」根據(jù)這個(gè)排行榜去轉(zhuǎn)發(fā)服務(wù);
⑤負(fù)載度策略:負(fù)載度策略是指當(dāng)「負(fù)載均衡器」往后端轉(zhuǎn)發(fā)流量的時(shí)候,會(huì)先去評(píng)估后端每臺(tái)服務(wù)器的負(fù)載壓力情況,對(duì)于壓力比較大的后端服務(wù)器轉(zhuǎn)發(fā)的請(qǐng)求就少一些,對(duì)于壓力比較小的后端服務(wù)器可以多轉(zhuǎn)發(fā)一些請(qǐng)求給它。這種方式就充分的結(jié)合了后端服務(wù)器的運(yùn)行狀態(tài),來(lái)動(dòng)態(tài)的分配流量了,比輪詢的方式更為科學(xué)一些。但是這種方式也帶來(lái)了一些弊端,因?yàn)樾枰獎(jiǎng)討B(tài)的評(píng)估后端服務(wù)器的負(fù)載壓力,那這個(gè)「負(fù)載均衡器」除了轉(zhuǎn)發(fā)請(qǐng)求以外,還要做很多額外的工作,比如采集 連接數(shù)、請(qǐng)求數(shù)、CPU負(fù)載指標(biāo)、IO負(fù)載指標(biāo)等等,通過(guò)對(duì)這些指標(biāo)進(jìn)行計(jì)算和對(duì)比,判斷出哪一臺(tái)后端服務(wù)器的負(fù)載壓力較大。因此這種方式帶來(lái)了效果優(yōu)勢(shì)的同時(shí),也增加了「負(fù)載均衡器」的實(shí)現(xiàn)難度和維護(hù)成本。
1)Nginx是當(dāng)下最熱的Web容器,網(wǎng)站優(yōu)化的重要點(diǎn)在于靜態(tài)化網(wǎng)站,網(wǎng)站靜態(tài)化的關(guān)鍵點(diǎn)則是是動(dòng)靜分離,動(dòng)靜分離是讓動(dòng)態(tài)網(wǎng)站里的動(dòng)態(tài)網(wǎng)頁(yè)根據(jù)一定規(guī)則把不變的資源和經(jīng)常變的資源區(qū)分開來(lái),動(dòng)靜資源做好了拆分以后,我們則根據(jù)靜態(tài)資源的特點(diǎn)將其做緩存操作。
2)讓靜態(tài)的資源只走靜態(tài)資源服務(wù)器,動(dòng)態(tài)的走動(dòng)態(tài)的服務(wù)器
3)Nginx的靜態(tài)處理能力很強(qiáng),但是動(dòng)態(tài)處理能力不足,因此,在企業(yè)中常用動(dòng)靜分離技術(shù)。
4)對(duì)于靜態(tài)資源比如圖片,js,css等文件,我們則在反向代理服務(wù)器nginx中進(jìn)行緩存。這樣瀏覽器在請(qǐng)求一個(gè)靜態(tài)資源時(shí),代理服務(wù)器nginx就可以直接處理,無(wú)需將請(qǐng)求轉(zhuǎn)發(fā)給后端服務(wù)器tomcat。 若用戶請(qǐng)求的動(dòng)態(tài)文件,比如servlet,jsp則轉(zhuǎn)發(fā)給Tomcat服務(wù)器處理,從而實(shí)現(xiàn)動(dòng)靜分離。這也是反向代理服務(wù)器的一個(gè)重要的作用。
CDN ,即內(nèi)容分發(fā)網(wǎng)絡(luò)。其目的是,通過(guò)在現(xiàn)有的 Internet中 增加一層新的網(wǎng)絡(luò)架構(gòu),將網(wǎng)站的內(nèi)容發(fā)布到最接近用戶的網(wǎng)絡(luò)邊緣,使用戶可就近取得所需的內(nèi)容,提高用戶訪問(wèn)網(wǎng)站的速度。一般來(lái)說(shuō),因?yàn)楝F(xiàn)在 CDN 服務(wù)比較大眾,所以基本所有公司都會(huì)使用 CDN 服務(wù)。
在有多個(gè)cpu的情況下,可以設(shè)置多個(gè)worker,worker進(jìn)程的數(shù)量可以設(shè)置到和cpu的核心數(shù)一樣多,如果在單個(gè)cpu上起多個(gè)worker進(jìn)程,那么操作系統(tǒng)會(huì)在多個(gè)worker之間進(jìn)行調(diào)度,這種情況會(huì)降低系統(tǒng)性能,如果只有一個(gè)cpu,那么只啟動(dòng)一個(gè)worker進(jìn)程就可以了。
漏桶算法思路很簡(jiǎn)單,我們把水比作是請(qǐng)求,漏桶比作是系統(tǒng)處理能力極限,水先進(jìn)入到漏桶里,漏桶里的水按一定速率流出,當(dāng)流出的速率小于流入的速率時(shí),由于漏桶容量有限,后續(xù)進(jìn)入的水直接溢出(拒絕請(qǐng)求),以此實(shí)現(xiàn)限流。
令牌桶算法的原理也比較簡(jiǎn)單,我們可以理解成醫(yī)院的掛號(hào)看病,只有拿到號(hào)以后才可以進(jìn)行診病。
系統(tǒng)會(huì)維護(hù)一個(gè)令牌(token)桶,以一個(gè)恒定的速度往桶里放入令牌(token),這時(shí)如果有請(qǐng)求進(jìn)來(lái)想要被處理,則需要先從桶里獲取一個(gè)令牌(token),當(dāng)桶里沒(méi)有令牌(token)可取時(shí),則該請(qǐng)求將被拒絕服務(wù)。令牌桶算法通過(guò)控制桶的容量、發(fā)放令牌的速率,來(lái)達(dá)到對(duì)請(qǐng)求的限制。
ActiveMQ是一種開源的,實(shí)現(xiàn)了JMS1.1規(guī)范的,面向消息(MOM)的中間件,為應(yīng)用程序提供高效的、可擴(kuò)展的、穩(wěn)定的和安全的企業(yè)級(jí)消息通信。
ActiveMQ的作用就是系統(tǒng)之間進(jìn)行通信。 當(dāng)然可以使用其他方式進(jìn)行系統(tǒng)間通信, 如果使用 ActiveMQ的話可以對(duì)系統(tǒng)之間的調(diào)用進(jìn)行解耦, 實(shí)現(xiàn)系統(tǒng)間的異步通信。 原理就是生產(chǎn)者生產(chǎn)消息, 把消息發(fā)送給ActiveMQ。 ActiveMQ接收到消息, 然后查看有多少個(gè)消費(fèi)者, 然后把消息轉(zhuǎn)發(fā)給消費(fèi)者, 此過(guò)程中生產(chǎn)者無(wú)需參與。 消費(fèi)者接收到消息后做相應(yīng)的處理和生產(chǎn)者沒(méi)有任何關(guān)系。
消息通信的基本方式有兩種:
1.同步方式
兩個(gè)通信應(yīng)用服務(wù)之間必須要進(jìn)行同步,兩個(gè)服務(wù)之間必須都是正常運(yùn)行的。發(fā)送程序和接收程序都必須一直處于運(yùn)行狀態(tài),并且隨時(shí)做好相互通信的準(zhǔn)備。發(fā)送程序首先向接收程序發(fā)起一個(gè)請(qǐng)求,稱之為發(fā)送消息,發(fā)送程序緊接著就會(huì)堵塞當(dāng)前自身的進(jìn)程,不與其他應(yīng)用進(jìn)行任何的通信以及交互,等待接收程序的響應(yīng),待發(fā)送消息得到接收程序的返回消息之后會(huì)繼續(xù)向下運(yùn)行,進(jìn)行下一步的業(yè)務(wù)處理。
2.異步方式
兩個(gè)通信應(yīng)用之間可以不用同時(shí)在線等待,任何一方只需各自處理自己的業(yè)務(wù),比如發(fā)送方發(fā)送消息以后不用登錄接收方的響應(yīng),可以接著處理其他的任務(wù)。也就是說(shuō)發(fā)送方和接收方都是相互獨(dú)立存在的,發(fā)送方只管方,接收方只能接收,無(wú)須去等待對(duì)方的響應(yīng)。Java 中 JMS 就是典型的異步消息處理機(jī)制,JMS 消息有兩種類型:點(diǎn)對(duì)點(diǎn)、發(fā)布/訂閱。
1)publish(發(fā)布)-subscribe(訂閱)(發(fā)布-訂閱方式)
發(fā)布/訂閱方式用于多接收客戶端的方式.作為發(fā)布訂閱的方式,可能存在多個(gè)接收客戶端,并且接收端客戶端與發(fā)送客戶端存在時(shí)間上的依賴。一個(gè)接收端只能接收他創(chuàng)建以后發(fā)送客戶端發(fā)送的信息。作為subscriber ,在接收消息時(shí)有兩種方法,destination的receive方法,和實(shí)現(xiàn)message listener 接口的onMessage方法。
2)p2p(point-to-point)(點(diǎn)對(duì)點(diǎn))
p2p的過(guò)程則理解起來(lái)比較簡(jiǎn)單。它好比是兩個(gè)人打電話,這兩個(gè)人是獨(dú)享這一條通信鏈路的。一方發(fā)送消息,另外一方接收,就這么簡(jiǎn)單。在實(shí)際應(yīng)用中因?yàn)橛卸鄠€(gè)用戶對(duì)使用p2p的鏈路,相互通信的雙方是通過(guò)一個(gè)類似于隊(duì)列的方式來(lái)進(jìn)行交流。和前面pub-sub的區(qū)別在于一個(gè)topic有一個(gè)發(fā)送者和多個(gè)接收者,而在p2p里一個(gè)queue只有一個(gè)發(fā)送者和一個(gè)接收者。
工作模式:Topic是“訂閱-發(fā)布”模式,如果當(dāng)前沒(méi)有訂閱者,消息將會(huì)被丟棄,如果有多個(gè)訂閱者,那么這些訂閱者都會(huì)受到消息;Queue是“負(fù)載均衡”模式,如果當(dāng)前沒(méi)有消費(fèi)者,消息不會(huì)被丟棄;如果有多個(gè)消費(fèi)者,那么一條消息也只能發(fā)送給一個(gè)消費(fèi)者,并且要求消費(fèi)者ack信息。
有無(wú)狀態(tài):Topic無(wú)狀態(tài);Queue 數(shù)據(jù)默認(rèn)會(huì)在mq服務(wù)器上以文件的形式存儲(chǔ),比如activemq一般保存在$AMQ_HOME\data\kr-store\data下面,也可以配置成DB存儲(chǔ)。
傳遞完整性:Topic模式如果沒(méi)有訂閱,消息就會(huì)被丟棄。Queue消息不會(huì)被丟棄。
處理效率:由于消息會(huì)隨著訂閱者的數(shù)量進(jìn)行復(fù)制,所以處理性能會(huì)隨著訂閱者的增加而明顯降低,并且還要結(jié)合不同的消息協(xié)議自身的性能差異;Queue模式由于一條消息只能被一個(gè)消費(fèi)者消費(fèi),所以就算消費(fèi)者再多,性能也不會(huì)有明顯降低,當(dāng)然不同的消息協(xié)議的具體性能也是有差異的。
一般來(lái)說(shuō)我們可以在業(yè)務(wù)段加一張表,用來(lái)存放消息是否執(zhí)行成功,每次業(yè)務(wù)事物commit之后,告知服務(wù)端,已經(jīng)處理過(guò)該消息,這樣即使你消息重發(fā)了,也不會(huì)導(dǎo)致重復(fù)處理。
為了避免意外宕機(jī)以后丟失信息,需要做到重啟后可以恢復(fù)消息隊(duì)列,消息系統(tǒng)一半都會(huì)采用持久化機(jī)制。ActiveMQ的消息持久化機(jī)制有JDBC,AMQ,KahaDB和LevelDB,無(wú)論使用哪種持久化方式,消息的存儲(chǔ)邏輯都是一致的。就是在發(fā)送者將消息發(fā)送出去后,消息中心首先將消息存儲(chǔ)到本地?cái)?shù)據(jù)文件、內(nèi)存數(shù)據(jù)庫(kù)或者遠(yuǎn)程數(shù)據(jù)庫(kù)等。再試圖將消息發(fā)給接收者,成功則將消息從存儲(chǔ)中刪除,失敗則繼續(xù)嘗試嘗試發(fā)送。消息中心啟動(dòng)以后,要先檢查指定的存儲(chǔ)位置是否有未成功發(fā)送的消息,如果有,則會(huì)先把存儲(chǔ)位置中的消息發(fā)出去。
如果一條消息不能被處理,會(huì)被退回服務(wù)器重新分配,如果只有一個(gè)消費(fèi)者,該消息又會(huì)重新被獲取,重新拋異常。如果有多個(gè)消費(fèi)者,往往在一個(gè)服務(wù)器上不能處理的消息,在另外的服務(wù)器上依然不能被處理。消息在重試 6 次后仍不能發(fā)送成功的,ActiveMQ 認(rèn)為這條消息是“有毒”的,將會(huì)把消息丟到死信隊(duì)列里。
RabbitMQ就是 AMQP 協(xié)議的 Erlang 的實(shí)現(xiàn)(當(dāng)然 RabbitMQ 還支持 STOMP2、 MQTT3 等協(xié)議 ) AMQP 的模型架構(gòu) 和 RabbitMQ 的模型架構(gòu)是一樣的,生產(chǎn)者將消息發(fā)送給交換器,交換器和隊(duì)列綁定 。RabbitMQ 中的交換器、交換器類型、隊(duì)列、綁定、路由鍵等都是遵循的 AMQP 協(xié)議中相應(yīng)的概念。
采用AMQP高級(jí)消息隊(duì)列協(xié)議的一種消息隊(duì)列技術(shù),最大的特點(diǎn)就是消費(fèi)并不需要確保提供方存在,實(shí)現(xiàn)了服務(wù)之間的高度解耦。
1.在分布式系統(tǒng)下具備異步,削峰,負(fù)載均衡等一系列高級(jí)功能;
2.擁有持久化的機(jī)制,進(jìn)程消息,隊(duì)列中的信息也可以保存下來(lái)。
3.實(shí)現(xiàn)消費(fèi)者和生產(chǎn)者之間的解耦。
4.對(duì)于高并發(fā)場(chǎng)景下,利用消息隊(duì)列可以使得同步訪問(wèn)變?yōu)榇性L問(wèn)達(dá)到一定量的限,利于數(shù)據(jù)庫(kù)的操作。
5.可以使用消息隊(duì)列達(dá)到異步下單的效果,排隊(duì)中,后臺(tái)進(jìn)行邏輯下單。
1.服務(wù)間異步通信
2.順序消費(fèi)
3.定時(shí)任務(wù)
4.請(qǐng)求削峰
Broker:簡(jiǎn)單來(lái)說(shuō)就是消息隊(duì)列服務(wù)器實(shí)體
Exchange:消息交換機(jī),它指定消息按什么規(guī)則,路由到哪個(gè)隊(duì)列
Queue:消息隊(duì)列載體,每個(gè)消息都會(huì)被投入到一個(gè)或多個(gè)隊(duì)列
Binding:綁定,它的作用就是把exchange和queue按照路由規(guī)則綁定起來(lái)
Routing Key: 路由關(guān)鍵字,exchange根據(jù)這個(gè)關(guān)鍵字進(jìn)行消息投遞
VHost:vhost可以理解為虛擬broker ,即mini-RabbitMQ server。其內(nèi)部均含有獨(dú)立的queue、exchange和binding等,但最最重要的是,其擁有獨(dú)立的權(quán)限系統(tǒng),可以做到vhost范圍的用戶控制。當(dāng)然,從RabbitMQ的全局角度,vhost可以作為不同權(quán)限隔離的手段(一個(gè)典型的例子就是不同的應(yīng)用可以跑在不同的 vhost 中)。
Producer: 消息生產(chǎn)者,就是投遞消息的程序
Consumer:消息消費(fèi)者,就是接受消息的程序
Channel:消息通道,在客戶端的每個(gè)連接里,可建立多個(gè)channel,每個(gè)channel代表一個(gè)會(huì)話任務(wù)由Exchange、Queue、RoutingKey三個(gè)才能決定一個(gè)從Exchange到Queue的唯一的線路。
消息的發(fā)送方有個(gè)確認(rèn)模式,具體的流程如下:
1.將信道設(shè)置成confirm模式(發(fā)送方確認(rèn)模式),則所有在信道上發(fā)布的消息都會(huì)被指派一個(gè)唯一的ID。
2.一旦消息被投遞到目的隊(duì)列后,或者消息被寫入磁盤后(可持久化的消息),信道會(huì)發(fā)送一個(gè)確認(rèn)給生產(chǎn)者(包含消息唯一 ID)。
3.如果 RabbitMQ發(fā)生內(nèi)部錯(cuò)誤從而導(dǎo)致消息丟失,會(huì)發(fā)送一條nack(notacknowledged,未確認(rèn))消息。發(fā)送方確認(rèn)模式是異步的,生產(chǎn)者應(yīng)用程序在等待確認(rèn)的同時(shí),可以繼續(xù)發(fā)送消息。當(dāng)確認(rèn)消息到達(dá)生產(chǎn)者應(yīng)用程序,生產(chǎn)者應(yīng)用程序的回調(diào)方法就會(huì)被觸發(fā)來(lái)處理確認(rèn)消息。
消息的接收方消息確認(rèn)機(jī)制,具體的流程如下:
消費(fèi)者接收每一條消息后都必須進(jìn)行確認(rèn)(消息接收和消息確認(rèn)是兩個(gè)不同操作)。只有消費(fèi)者確認(rèn)了消息,RabbitMQ才能安全地把消息從隊(duì)列中刪除。這里并沒(méi)有用到超時(shí)機(jī)制,RabbitMQ僅通過(guò)Consumer的連接中斷來(lái)確認(rèn)是否需要重新發(fā)送消息。也就是說(shuō),只要連接不中斷,RabbitMQ給了Consumer足夠長(zhǎng)的時(shí)間來(lái)處理消息。保證數(shù)據(jù)的最終一致性;
如果消費(fèi)者接收到消息,在確認(rèn)之前斷開了連接或取消訂閱,RabbitMQ會(huì)認(rèn)為消息沒(méi)有被分發(fā),然后重新分發(fā)給下一個(gè)訂閱的消費(fèi)者。
在消息生產(chǎn)時(shí),RabbitMQ內(nèi)部針對(duì)每條生產(chǎn)者發(fā)送的消息生成一個(gè)inner-msg-id,作為去重的依據(jù)(消息投遞失敗并重傳),避免重復(fù)的消息進(jìn)入隊(duì)列;
在消息消費(fèi)時(shí),要求消息體中必須要有一個(gè) bizId(對(duì)于同一業(yè)務(wù)全局唯一,如支付ID、訂單ID、帖子ID 等)作為去重的依據(jù),避免同一條消息被重復(fù)消費(fèi)。
消息不丟失需要堆消息進(jìn)行持久化。
確保持久性消息能從服務(wù)器重啟中恢復(fù)的方式是,將它們寫入磁盤上的一個(gè)持久化日志文件,當(dāng)發(fā)布一條持久性消息到持久交換器上時(shí),Rabbit會(huì)在消息提交到日志文件后才發(fā)送響應(yīng)。一旦消費(fèi)者從持久隊(duì)列中消費(fèi)了一條持久化消息,RabbitMQ會(huì)在持久化日志中把這條消息標(biāo)記為等待垃圾收集。如果持久化消息在被消費(fèi)之前RabbitMQ重啟,那么Rabbit會(huì)自動(dòng)重建交換器和隊(duì)列(以及綁定),并重新發(fā)布持久化日志文件中的消息到合適的隊(duì)列。
由于TCP連接的創(chuàng)建和銷毀開銷較大,且并發(fā)數(shù)受系統(tǒng)資源限制,會(huì)造成性能瓶頸。RabbitMQ使用信道的方式來(lái)傳輸數(shù)據(jù)。信道是建立在真實(shí)的TCP連接內(nèi)的虛擬連接,且每條TCP連接上的信道數(shù)量沒(méi)有限制。
若該隊(duì)列至少有一個(gè)消費(fèi)者訂閱,消息將以循環(huán)(round-robin)的方式發(fā)送給消費(fèi)者。每條消息只會(huì)分發(fā)給一個(gè)訂閱的消費(fèi)者(前提是消費(fèi)者能夠正常處理消息并進(jìn)行確認(rèn))。
主要有3種:
1.fanout:如果交換器收到消息,將會(huì)廣播到所有綁定的隊(duì)列上
2.direct:如果路由鍵完全匹配,消息就被投遞到相應(yīng)的隊(duì)列
3.topic:可以使來(lái)自不同源頭的消息能夠到達(dá)同一個(gè)隊(duì)列。 使用topic交換器時(shí),可以使用通配符
1.簡(jiǎn)單模式,用的默認(rèn)交換機(jī),1個(gè)生產(chǎn)者,1個(gè)消費(fèi)者,一個(gè)消息只能被一個(gè)消費(fèi)者消息
2.工作模,多個(gè)消費(fèi)者監(jiān)聽同一個(gè)隊(duì)列,如果任務(wù)數(shù)據(jù)比較多,可以多幾個(gè)消費(fèi)者,可以加快消費(fèi)的速度
3.訂閱發(fā)布模式,引入了交換機(jī)的類型fanout,廣播模式 ,每個(gè)消費(fèi)者單獨(dú)監(jiān)聽自己的對(duì)列都可以取消費(fèi)自己隊(duì)列的消息。
4.routing,是direct的的交換機(jī)類型,指定路由
5.topic,是topic的交換機(jī)類型,比路由多了通配符的更加的靈活
完成RabbitMQ消息路由的核心組件是 Exchange。而消息的路由是由Exchange類型 和 Binding 來(lái)決定的。Binding 表示建立 Queue 和 Exchange 之間的綁定關(guān)系,每一個(gè)綁定關(guān)系會(huì)存在一個(gè) BindingKey。通過(guò)這種方式相當(dāng)于在 Exchange 中建立了一個(gè)路由關(guān)系表。生產(chǎn)者發(fā)送消息的時(shí)候,需要聲明一個(gè) RoutingKey(路由鍵),Exchange 拿到RoutingKey 之后,根據(jù) RoutingKey 和路由表里面的 BindingKey 進(jìn)行匹配,而匹配的規(guī)則是通過(guò) Exchange類型來(lái)決定的。在 RabbitMQ 中,默認(rèn)有四種類型的 Exchange:Direct ,F(xiàn)anout、Topic和Header。
Direct,叫直連,也就是完整匹配方式,需要Routing Key 和 Binding Key 完全一致,相當(dāng)于點(diǎn)對(duì)點(diǎn)的發(fā)送。
Topic: 叫主題,這種方式是通過(guò)設(shè)置通配符來(lái)動(dòng)態(tài)匹配,相當(dāng)于正則。就是用Routing Key 去匹配Binging Key。BingingKey支持兩個(gè)通配符。
Fanout:叫廣播,這種方式不需要設(shè)置Routing Key,而是把消息廣播給綁定到當(dāng)前 Exchange 上的所有隊(duì)列上。
1)拆分多個(gè)queue(消息隊(duì)列),每個(gè)queue(消息隊(duì)列) 一個(gè)consumer(消費(fèi)者),就是多一些queue(消息隊(duì)列)而已,這種方式會(huì)比較麻煩;
2)一個(gè)queue (消息隊(duì)列)但是對(duì)應(yīng)一個(gè)consumer(消費(fèi)者),然后這個(gè)consumer(消費(fèi)者)內(nèi)部用內(nèi)存隊(duì)列做排隊(duì),然后分發(fā)給底層不同的worker來(lái)處理。
首先,必然導(dǎo)致性能的下降,因?yàn)閷懘疟P比寫RAM慢的多,message的吞吐量可能有10倍的差距。
其次,message的持久化機(jī)制用在RabbitMQ的內(nèi)置cluster方案時(shí)會(huì)出現(xiàn)“坑爹”問(wèn)題。矛盾點(diǎn)在于,若message設(shè)置了persistent屬性,但queue未設(shè)置durable屬性,那么當(dāng)該queue的owner node出現(xiàn)異常后,在未重建該queue前,發(fā)往該queue 的message將被 blackholed;若 message 設(shè)置了 persistent屬性,同時(shí)queue也設(shè)置了durable屬性,那么當(dāng)queue的owner node異常且無(wú)法重啟的情況下,則該queue無(wú)法在其他node上重建,只能等待其owner node重啟后,才能恢復(fù)該 queue的使用,而在這段時(shí)間內(nèi)發(fā)送給該queue的message將被 blackholed 。
所以,是否要對(duì)message進(jìn)行持久化,需要綜合考慮性能需要,以及可能遇到的問(wèn)題。若想達(dá)到100,000 條/秒以上的消息吞吐量(單RabbitMQ服務(wù)器),則要么使用其他的方式來(lái)確保message的可靠delivery ,要么使用非常快速的存儲(chǔ)系統(tǒng)以支持全持久化(例如使用SSD)。
另外一種處理原則是:僅對(duì)關(guān)鍵消息作持久化處理(根據(jù)業(yè)務(wù)重要程度),且應(yīng)該保證關(guān)鍵消息的量不會(huì)導(dǎo)致性能瓶頸。
RabbitMQ有三種模式:?jiǎn)螜C(jī)模式、普通集群模式、鏡像集群模式。
單機(jī)模式就是Demo級(jí)別的,一般就是你本地啟動(dòng)了玩玩兒的?,沒(méi)人生產(chǎn)用單機(jī)模式
普通集群模式就是在多臺(tái)機(jī)器上啟動(dòng)多個(gè)RabbitMQ實(shí)例,每個(gè)機(jī)器啟動(dòng)一個(gè)。你創(chuàng)建的queue,只會(huì)放在一個(gè)RabbitMQ實(shí)例上,但是每個(gè)實(shí)例都同步queue的元數(shù)據(jù)。你消費(fèi)的時(shí)候,實(shí)際上如果連接到了另外一個(gè)實(shí)例,那么那個(gè)實(shí)例會(huì)從queue所在實(shí)例上拉取數(shù)據(jù)過(guò)來(lái)。這方案主要是提高吞吐量的,就是說(shuō)讓集群中多個(gè)節(jié)點(diǎn)來(lái)服務(wù)某個(gè)queue的讀寫操作。
鏡像集群模式才是所謂的RabbitMQ的高可用模式。這種模式下,每個(gè)RabbitMQ節(jié)點(diǎn)都有這個(gè)queue的一個(gè)完整鏡像,包含queue的全部數(shù)據(jù)的意思。然后每次你寫消息到queue的時(shí)候,都會(huì)自動(dòng)把消息同步到多個(gè)實(shí)例的queue上。RabbitMQ有很好的管理控制臺(tái),就是在后臺(tái)新增一個(gè)策略,這個(gè)策略是鏡像集群模式的策略,指定的時(shí)候是可以要求數(shù)據(jù)同步到所有節(jié)點(diǎn)的,也可以要求同步到指定數(shù)量的節(jié)點(diǎn),再次創(chuàng)建queue的時(shí)候,應(yīng)用這個(gè)策略,就會(huì)自動(dòng)將數(shù)據(jù)同步到其他的節(jié)點(diǎn)上去了。這樣的好處在于,你任何一個(gè)機(jī)器宕機(jī)了,沒(méi)事兒,其它機(jī)器(節(jié)點(diǎn))還包含了這個(gè)queue的完整數(shù)據(jù),別的consumer都可以到其它節(jié)點(diǎn)上去消費(fèi)數(shù)據(jù)。壞處在于,第一,這個(gè)性能開銷也太大了吧,消息需要同步到所有機(jī)器上,導(dǎo)致網(wǎng)絡(luò)帶寬壓力和消耗很重!RabbitMQ一個(gè)queue的數(shù)據(jù)都是放在一個(gè)節(jié)點(diǎn)里的,鏡像集群下,也是每個(gè)節(jié)點(diǎn)都放這個(gè)queue的完整數(shù)據(jù)。
mq是一個(gè)消息隊(duì)列,其主要目的是為了解決傳統(tǒng)的消息傳輸上管理困難,效率不高的問(wèn)題。mq有三大優(yōu)點(diǎn):解耦,異步,削峰。
解耦: 如果是傳統(tǒng)的消息通訊方式,無(wú)論是哪一方都要去維護(hù)一份供外部通訊的這個(gè)一個(gè)接口,而且各方處理消息的能力有限,效率上明顯跟不上,并且這樣子二者之間的耦合度非常高,對(duì)于拓展管理方面極不友好,而是要了mq就不一樣,發(fā)送方只需要將消息發(fā)送給mq就可以了,別的不用考慮,接口什么的由mq去維護(hù),接收方也只需要去mq里消費(fèi)消息就可以了,就需要其他開銷,一切由mq中間件來(lái)做,達(dá)到了解耦操作.
異步: 使用mq,還可以達(dá)到異步效果,極大地提升了消息傳輸?shù)男?發(fā)送方在發(fā)送消息后不需要關(guān)心消費(fèi)方是否能消費(fèi)完成,還可以繼續(xù)發(fā)送其他消息.
削峰:如果是傳統(tǒng)的消息通訊,一下子有大量的消息發(fā)送給接收方,這樣對(duì)于接收方的處理壓力是很大的,而我們剛好可以利用mq達(dá)到一個(gè)緩沖操作,一旦流量超出了接收方處理范圍,不用擔(dān)心,只需要慢慢消費(fèi)即可,像經(jīng)典的雙十一,就很容易會(huì)使用到mq這么一個(gè)優(yōu)點(diǎn).
mq缺點(diǎn):因?yàn)樵黾恿酥虚g件,系統(tǒng)復(fù)雜度肯定大大提高,增加了很多維護(hù)的成本,比如我們要保證消息不丟失(一致性)和消息冪等性問(wèn)題,還要保證mq的高可用等。
1)異步處理 - 相比于傳統(tǒng)的串行、并行方式,提高了系統(tǒng)吞吐量。
2)應(yīng)用解耦 - 系統(tǒng)間通過(guò)消息通信,不用關(guān)心其他系統(tǒng)的處理。
3)流量削鋒 - 可以通過(guò)消息隊(duì)列長(zhǎng)度控制請(qǐng)求量;可以緩解短時(shí)間內(nèi)的高并發(fā)請(qǐng)求。
4)日志處理 - 解決大量日志傳輸。
5)消息通訊 - 消息隊(duì)列一般都內(nèi)置了高效的通信機(jī)制,因此也可以用在純的消息通訊。比如實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)消息隊(duì)列,或者聊天室等。
1)系統(tǒng)可用性降低:本來(lái)系統(tǒng)運(yùn)行好好的,現(xiàn)在你非要加入個(gè)消息隊(duì)列進(jìn)去,那消息隊(duì)列掛了,你的系統(tǒng)不是呵呵了。因此,系統(tǒng)可用性會(huì)降低;
2)系統(tǒng)復(fù)雜度提高:加入了消息隊(duì)列,要多考慮很多方面的問(wèn)題,比如:一致性問(wèn)題、如何保證消息不被重復(fù)消費(fèi)、如何保證消息可靠性傳輸?shù)取R虼耍枰紤]的東西更多,復(fù)雜性增大。
3)一致性問(wèn)題:A系統(tǒng)處理完了直接返回成功了,人都以為你這個(gè)請(qǐng)求就成功了;但是問(wèn)題是,要是BCD三個(gè)系統(tǒng)那里,BD兩個(gè)系統(tǒng)寫庫(kù)成功了,結(jié)果C系統(tǒng)寫庫(kù)失敗了,咋整?你這數(shù)據(jù)就不一致了。
所以消息隊(duì)列實(shí)際是一種非常復(fù)雜的架構(gòu),你引入它有很多好處,但是也得針對(duì)它帶來(lái)的壞處做各種額外的技術(shù)方案和架構(gòu)來(lái)規(guī)避掉。
解耦:以電商應(yīng)用為例,應(yīng)用中有訂單系統(tǒng)、庫(kù)存系統(tǒng)、物流系統(tǒng)、支付系統(tǒng)。用戶創(chuàng)建訂單后,如果耦合調(diào)用庫(kù)存系統(tǒng)、物流系統(tǒng)、支付系統(tǒng),任何一個(gè)子系統(tǒng)出了故障,都會(huì)造成下單操作異常。使用mq后,訂單系統(tǒng)和其余系統(tǒng)完成解耦,不必?fù)?dān)心其他系統(tǒng)出現(xiàn)故障,當(dāng)轉(zhuǎn)變成基于消息隊(duì)列的方式后,系統(tǒng)間調(diào)用的問(wèn)題會(huì)減少很多,比如物流系統(tǒng)因?yàn)榘l(fā)生故障,需要幾分鐘來(lái)修復(fù)。在這幾分鐘的時(shí)間里,物流系統(tǒng)要處理的內(nèi)存被緩存在消息隊(duì)列中,用戶的下單操作可以正常完成。當(dāng)物流系統(tǒng)恢復(fù)后,繼續(xù)處理訂單信息即可,中單用戶感受不到物流系統(tǒng)的故障,提升系統(tǒng)的可用性。
異步:有些服務(wù)間的調(diào)用并不是同步的,而是異步執(zhí)行,例如,A調(diào)用B,B需要花費(fèi)很長(zhǎng)時(shí)間執(zhí)行,此時(shí)A需要知道B什么時(shí)間可以執(zhí)行完成,在未使用MQ時(shí),一般會(huì)有兩種方法實(shí)現(xiàn),1.A不斷地輪詢查看B是否完成。2、就是A提供一個(gè)調(diào)用接口,當(dāng)B執(zhí)行完成之后,調(diào)用A的回調(diào)接口,以此實(shí)現(xiàn)。
當(dāng)然MQ的出現(xiàn)很好的解決這個(gè)問(wèn)題,A調(diào)用B后,只需要監(jiān)聽B處理完成消息,當(dāng)B處理完后,會(huì)發(fā)送一條消息給MQ,MQ會(huì)將此消息轉(zhuǎn)發(fā)給A服務(wù)。這樣就省去了A的輪詢或者B對(duì)A的回調(diào)。A也能夠即使得到異步處理消息。
削峰:比如說(shuō),如果訂單系統(tǒng)最多能處理一萬(wàn)次訂單,這個(gè)處理能力應(yīng)付正常時(shí)段的下單時(shí)是沒(méi)有問(wèn)題的,正常時(shí)段我們下單一秒后就能返回結(jié)果。但是在高峰期,如果有兩萬(wàn)次下單操作系統(tǒng)是處理不了的,只能限制訂單超過(guò)一萬(wàn)后不允許用戶下單。使用MQ做緩沖,我們可以取消這個(gè)限制,把一秒內(nèi)下的訂單分散成一段時(shí)間來(lái)處理,這時(shí)有些用戶可能在下單十幾秒后才能收到下單成功,雖然這樣會(huì)影響一定的體驗(yàn),但是要比不能下單好的多。
AMQP協(xié)議 AMQP即Advanced Message Queuing Protocol,一個(gè)提供統(tǒng)一消息服務(wù)的應(yīng)用層標(biāo)準(zhǔn)高級(jí)消息隊(duì)列協(xié)議,是應(yīng)用層協(xié)議的一個(gè)開放標(biāo)準(zhǔn),為面向消息的中間件設(shè)計(jì)。基于此協(xié)議的客戶端與消息中間件可傳遞消息,并不受客戶端/中間件不同產(chǎn)品,不同開發(fā)語(yǔ)言等條件的限制。
優(yōu)點(diǎn):可靠、通用
MQTT協(xié)議 MQTT(Message Queuing Telemetry Transport,消息隊(duì)列遙測(cè)傳輸)是IBM開發(fā)的一個(gè)即時(shí)通訊協(xié)議,有可能成為物聯(lián)網(wǎng)的重要組成部分。該協(xié)議支持所有平臺(tái),幾乎可以把所有聯(lián)網(wǎng)物品和外部連接起來(lái),被用來(lái)當(dāng)做傳感器和致動(dòng)器(比如通過(guò)Twitter讓房屋聯(lián)網(wǎng))的通信協(xié)議。
優(yōu)點(diǎn):格式簡(jiǎn)潔、占用帶寬小、移動(dòng)端通信、PUSH、嵌入式系統(tǒng)
STOMP協(xié)議 STOMP(Streaming Text Orientated Message Protocol)是流文本定向消息協(xié)議,是一種為MOM(Message Oriented Middleware,面向消息的中間件)設(shè)計(jì)的簡(jiǎn)單文本協(xié)議。STOMP提供一個(gè)可互操作的連接格式,允許客戶端與任意STOMP消息代理(Broker)進(jìn)行交互。
優(yōu)點(diǎn):命令模式(非topic/queue模式)
XMPP協(xié)議 XMPP(可擴(kuò)展消息處理現(xiàn)場(chǎng)協(xié)議,Extensible Messaging and Presence Protocol)是基于可擴(kuò)展標(biāo)記語(yǔ)言(XML)的協(xié)議,多用于即時(shí)消息(IM)以及在線現(xiàn)場(chǎng)探測(cè)。適用于服務(wù)器之間的準(zhǔn)即時(shí)操作。核心是基于XML流傳輸,這個(gè)協(xié)議可能最終允許因特網(wǎng)用戶向因特網(wǎng)上的其他任何人發(fā)送即時(shí)消息,即使其操作系統(tǒng)和瀏覽器不同。
優(yōu)點(diǎn):通用公開、兼容性強(qiáng)、可擴(kuò)展、安全性高,但XML編碼格式占用帶寬大
其他基于TCP/IP自定義的協(xié)議:有些特殊框架(如:redis、kafka、zeroMq等)根據(jù)自身需要未嚴(yán)格遵循MQ規(guī)范,而是基于TCP\IP自行封裝了一套協(xié)議,通過(guò)網(wǎng)絡(luò)socket接口進(jìn)行傳輸,實(shí)現(xiàn)了MQ的功能。
1)點(diǎn)對(duì)點(diǎn)通訊:點(diǎn)對(duì)點(diǎn)方式是最為傳統(tǒng)和常見的通訊方式,它支持一對(duì)一、一對(duì)多、多對(duì)多、多對(duì)一等多種配置方式,支持樹狀、網(wǎng)狀等多種拓?fù)浣Y(jié)構(gòu)。
2)多點(diǎn)廣播:MQ適用于不同類型的應(yīng)用。其中重要的,也是正在發(fā)展中的是"多點(diǎn)廣播"應(yīng)用,即能夠?qū)⑾l(fā)送到多個(gè)目標(biāo)站點(diǎn)(Destination List)。可以使用一條MQ指令將單一消息發(fā)送到多個(gè)目標(biāo)站點(diǎn),并確保為每一站點(diǎn)可靠地提供信息。MQ不僅提供了多點(diǎn)廣播的功能,而且還擁有智能消息分發(fā)功能,在將一條消息發(fā)送到同一系統(tǒng)上的多個(gè)用戶時(shí),MQ將消息的一個(gè)復(fù)制版本和該系統(tǒng)上接收者的名單發(fā)送到目標(biāo)MQ系統(tǒng)。目標(biāo)MQ系統(tǒng)在本地復(fù)制這些消息,并將它們發(fā)送到名單上的隊(duì)列,從而盡可能減少網(wǎng)絡(luò)的傳輸量。
3)發(fā)布/訂閱(Publish/Subscribe)模式:發(fā)布/訂閱功能使消息的分發(fā)可以突破目的隊(duì)列地理指向的限制,使消息按照特定的主題甚至內(nèi)容進(jìn)行分發(fā),用戶或應(yīng)用程序可以根據(jù)主題或內(nèi)容接收到所需要的消息。發(fā)布/訂閱功能使得發(fā)送者和接收者之間的耦合關(guān)系變得更為松散,發(fā)送者不必關(guān)心接收者的目的地址,而接收者也不必關(guān)心消息的發(fā)送地址,而只是根據(jù)消息的主題進(jìn)行消息的收發(fā)。在MQ家族產(chǎn)品中,MQ Event Broker是專門用于使用發(fā)布/訂閱技術(shù)進(jìn)行數(shù)據(jù)通訊的產(chǎn)品,它支持基于隊(duì)列和直接基于TCP/IP兩種方式的發(fā)布和訂閱。
4)集群(Cluster):為了簡(jiǎn)化點(diǎn)對(duì)點(diǎn)通訊模式中的系統(tǒng)配置,MQ提供 Cluster 的解決方案。集群類似于一個(gè) 域(Domain) ,集群內(nèi)部的隊(duì)列管理器之間通訊時(shí),不需要兩兩之間建立消息通道,而是采用 Cluster 通道與其它成員通訊,從而大大簡(jiǎn)化了系統(tǒng)配置。此外,集群中的隊(duì)列管理器之間能夠自動(dòng)進(jìn)行負(fù)載均衡,當(dāng)某一隊(duì)列管理器出現(xiàn)故障時(shí),其它隊(duì)列管理器可以接管它的工作,從而大大提高系統(tǒng)的高可靠性;
在消息生產(chǎn)時(shí),MQ內(nèi)部針對(duì)每條生產(chǎn)者發(fā)送的消息生成一個(gè)唯一id,作為去重和冪等的依據(jù)(消息投遞失敗并重傳),避免重復(fù)的消息進(jìn)入隊(duì)列。
在消息消費(fèi)時(shí),要求消息體中也要有一全局唯一id作為去重和冪等的依據(jù),避免同一條消息被重復(fù)消費(fèi)。
一般這個(gè)時(shí)候,只能臨時(shí)緊急擴(kuò)容了,具體操作步驟和思路如下:
1)先修復(fù) consumer 的問(wèn)題,確保其恢復(fù)消費(fèi)速度,然后將現(xiàn)有 consumer 都停掉;
2)新建一個(gè) topic,partition 是原來(lái)的 10 倍,臨時(shí)建立好原先 10 倍的 queue 數(shù)量;
3)然后寫一個(gè)臨時(shí)的分發(fā)數(shù)據(jù)的 consumer 程序,這個(gè)程序部署上去消費(fèi)積壓的數(shù)據(jù),消費(fèi)之后不做耗時(shí)的處理,直接均勻輪詢寫入臨時(shí)建立好的 10 倍數(shù)量的queue;
4)接著臨時(shí)用 10 倍的機(jī)器來(lái)部署 consumer,每一批 consumer 消費(fèi)一個(gè)臨時(shí) queue 的數(shù)據(jù)。這種做法相當(dāng)于是臨時(shí)將 queue 資源和 consumer 資源擴(kuò)大10倍,以正常的 10 倍速度來(lái)消費(fèi)數(shù)據(jù);
5)等快速消費(fèi)完積壓數(shù)據(jù)之后,得恢復(fù)原先部署的架構(gòu),重新用原先的 consumer 機(jī)器來(lái)消費(fèi)消息。
綜上,各種對(duì)比之后,有如下建議:
一般的業(yè)務(wù)系統(tǒng)要引入MQ,最早大家都用ActiveMQ,但是現(xiàn)在確實(shí)大家用的不多了,沒(méi)經(jīng)過(guò)大規(guī)模吞吐量場(chǎng)景的驗(yàn)證,社區(qū)也不是很活躍,所以大家還是算了吧,我個(gè)人不推薦用這個(gè)了;
后來(lái)大家開始用RabbitMQ,但是確實(shí)erlang語(yǔ)言阻止了大量的Java工程師去深入研究和掌控它,對(duì)公司而言,幾乎處于不可控的狀態(tài),但是確實(shí)人家是開源的,比較穩(wěn)定的支持,活躍度也高;
不過(guò)現(xiàn)在確實(shí)越來(lái)越多的公司會(huì)去用RocketMQ,確實(shí)很不錯(cuò),畢竟是阿里出品,但社區(qū)可能有突然黃掉的風(fēng)險(xiǎn)(目前 RocketMQ已捐給Apache,但GitHub上的活躍度其實(shí)不算高)對(duì)自己公司技術(shù)實(shí)力有絕對(duì)自信的,推薦用RocketMQ,否則回去老老實(shí)實(shí)用RabbitMQ 吧,人家有活躍的開源社區(qū),絕對(duì)不會(huì)黃。
所以中小型公司,技術(shù)實(shí)力較為一般,技術(shù)挑戰(zhàn)不是特別高,用RabbitMQ是不錯(cuò)的選擇;大型公司,基礎(chǔ)架構(gòu)研發(fā)實(shí)力較強(qiáng),用 RocketMQ是很好的選擇。如果是大數(shù)據(jù)領(lǐng)域的實(shí)時(shí)計(jì)算、日志采集等場(chǎng)景,用Kafka是業(yè)內(nèi)標(biāo)準(zhǔn)的,絕對(duì)沒(méi)問(wèn)題,社區(qū)活躍度很高,絕對(duì)不會(huì)黃,何況幾乎是全世界這個(gè)領(lǐng)域的事實(shí)性規(guī)范。
這個(gè)首先你可以說(shuō)下你們公司選用的是什么消息中間件,比如用的是RabbitMQ,然后可以初步給一些你對(duì)不同MQ中間件技術(shù)的選型分析。舉個(gè)例子:比如說(shuō)ActiveMQ是老牌的消息中間件,國(guó)內(nèi)很多公司過(guò)去運(yùn)用的還是非常廣泛的,功能很強(qiáng)大。但是問(wèn)題在于沒(méi)法確認(rèn)ActiveMQ可以支撐互聯(lián)網(wǎng)公司的高并發(fā)、高負(fù)載以及高吞吐的復(fù)雜場(chǎng)景,在國(guó)內(nèi)互聯(lián)網(wǎng)公司落地較少。而且使用較多的是一些傳統(tǒng)企業(yè),用ActiveMQ做異步調(diào)用和系統(tǒng)解耦。
然后你可以說(shuō)說(shuō)RabbitMQ,他的好處在于可以支撐高并發(fā)、高吞吐、性能很高,同時(shí)有非常完善便捷的后臺(tái)管理界面可以使用。另外,他還支持集群化、高可用部署架構(gòu)、消息高可靠支持,功能較為完善。而且經(jīng)過(guò)調(diào)研,國(guó)內(nèi)各大互聯(lián)網(wǎng)公司落地大規(guī)模RabbitMQ集群支撐自身業(yè)務(wù)的case較多,國(guó)內(nèi)各種中小型互聯(lián)網(wǎng)公司使用RabbitMQ的實(shí)踐也比較多。除此之外,RabbitMQ的開源社區(qū)很活躍,較高頻率的迭代版本,來(lái)修復(fù)發(fā)現(xiàn)的bug以及進(jìn)行各種優(yōu)化,因此綜合考慮過(guò)后,公司采取了RabbitMQ。但是RabbitMQ也有一點(diǎn)缺陷,就是他自身是基于erlang語(yǔ)言開發(fā)的,所以導(dǎo)致較為難以分析里面的源碼,也較難進(jìn)行深層次的源碼定制和改造,畢竟需要較為扎實(shí)的erlang語(yǔ)言功底才可以。
然后可以聊聊RocketMQ,是阿里開源的,經(jīng)過(guò)阿里的生產(chǎn)環(huán)境的超高并發(fā)、高吞吐的考驗(yàn),性能卓越,同時(shí)還支持分布式事務(wù)等特殊場(chǎng)景。而且RocketMQ是基于Java語(yǔ)言開發(fā)的,適合深入閱讀源碼,有需要可以站在源碼層面解決線上生產(chǎn)問(wèn)題,包括源碼的二次開發(fā)和改造。
另外就是Kafka。Kafka提供的消息中間件的功能明顯較少一些,相對(duì)上述幾款MQ中間件要少很多。但是Kafka的優(yōu)勢(shì)在于專為超高吞吐量的實(shí)時(shí)日志采集、實(shí)時(shí)數(shù)據(jù)同步、實(shí)時(shí)數(shù)據(jù)計(jì)算等場(chǎng)景來(lái)設(shè)計(jì)。因此Kafka在大數(shù)據(jù)領(lǐng)域中配合實(shí)時(shí)計(jì)算技術(shù)(比如Spark Streaming、Storm、Flink)使用的較多。但是在傳統(tǒng)的MQ中間件使用場(chǎng)景中較少采用。