日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

消息隊(duì)列選型[首選Kafka](備選:RabbitMQ/NSQ/RocketMQ/disque/Kafka)

 WindySky 2017-10-10


第一梯隊(duì): KafKa ~ Disque ~ NSQ


第二梯隊(duì): RocketMQ ~ RabbitMQ


第三梯隊(duì):





消息隊(duì)列選型

Sep 27, 2015

什么是消息隊(duì)列

顧名思義,消息隊(duì)列就是用存放消息的隊(duì)列結(jié)構(gòu),簡(jiǎn)稱(chēng)MQ。那什么是消息呢?廣義上來(lái)說(shuō),所有的網(wǎng)絡(luò)通信都可以看做是消息的傳遞。在通信的過(guò)程中,添加一個(gè)隊(duì)列緩沖,可以使得許多問(wèn)題變得非常容易解決。

圖:不使用消息隊(duì)列的網(wǎng)絡(luò)架構(gòu)

不使用消息隊(duì)列的網(wǎng)絡(luò)架構(gòu)

圖:使用消息隊(duì)列的網(wǎng)絡(luò)架構(gòu)

使用消息隊(duì)列的網(wǎng)絡(luò)架構(gòu)

題外話:在最初的面向?qū)ο缶幊痰脑O(shè)計(jì)中,對(duì)象之間的交互并不是直接的方法調(diào)用,而是消息傳遞。比如,打開(kāi)電腦,并不是簡(jiǎn)單的computer.start(),而是向computer對(duì)象實(shí)例發(fā)一個(gè)“開(kāi)機(jī)”消息,computer對(duì)象實(shí)例收到這個(gè)消息后執(zhí)行start()方法來(lái)處理這個(gè)消息。只不過(guò),當(dāng)下的主流編程語(yǔ)言中,只有Objective C完整的保留了這種語(yǔ)義。

為什要使用消息隊(duì)列

為了更好的說(shuō)明為什么要使用消息隊(duì)列,這個(gè)舉例一個(gè)實(shí)際的例子。現(xiàn)在我們要設(shè)計(jì)一個(gè)開(kāi)放平臺(tái),平臺(tái)中有很多服務(wù)實(shí)例,這些服務(wù)可以是我們自己實(shí)現(xiàn)的服務(wù),也可能是由第三方提供的。服務(wù)之間以事件的方式的通信,服務(wù)提供的API可以是同步調(diào)用,也可以是異步調(diào)用。所有的API通過(guò)統(tǒng)一的代理層對(duì)外開(kāi)放。對(duì)于內(nèi)部服務(wù),需要考慮系統(tǒng)的可伸縮性,充許調(diào)整每個(gè)服務(wù)的實(shí)例數(shù)量并進(jìn)行負(fù)載均衡。對(duì)于由第三方提供的服務(wù),需要進(jìn)行并發(fā)控制,以免壓力過(guò)大造成服務(wù)中斷。

圖:平臺(tái)的整體架構(gòu)

平臺(tái)的整體架構(gòu)

不使用消息隊(duì)列的實(shí)現(xiàn)方案

圖:平臺(tái)的通信模型(不使用消息隊(duì)列)

平臺(tái)的通信模型

在這種方案中,接入代理層的每個(gè)實(shí)例都要維護(hù)所有服務(wù)實(shí)例的配置參數(shù)。當(dāng)系統(tǒng)中的服務(wù)實(shí)例數(shù)量發(fā)生變化,或需要接入新的第三方實(shí)例時(shí),需要同步修改所有的接入層實(shí)例。接入層不僅需要處理請(qǐng)求的負(fù)載均衡,還要實(shí)現(xiàn)對(duì)第三方服務(wù)的并發(fā),服務(wù)實(shí)例的失效檢測(cè)、重試等復(fù)雜的控制邏輯。

而在事件代理層,由于事件轉(zhuǎn)發(fā)實(shí)際上是廣播方式,同一個(gè)事件往往需要轉(zhuǎn)發(fā)多次,在當(dāng)前的方案中,如果采用同步方式,一個(gè)事件的處理時(shí)間,取決于所有接收方的的處理時(shí)間之和。如果采用異步方式,則取決于所有接收方的的處理時(shí)間的最大值,并且代理層的實(shí)現(xiàn)的復(fù)雜度會(huì)大大增加。

引入消息隊(duì)列的方案

圖:平臺(tái)的通信模型(使用消息隊(duì)列)

平臺(tái)的通信模型

在這種方案中,引入了基于生產(chǎn)消費(fèi)模型的消息隊(duì)列后,天然具備了負(fù)載均衡能力。同時(shí),隊(duì)列中的消息是由服務(wù)實(shí)例自行拉取的,所以不論是接入層,還是消息隊(duì)列,都不要關(guān)心服務(wù)實(shí)例的部署細(xì)節(jié)。服務(wù)實(shí)例也可以處行控制拉取消息的頻率,實(shí)現(xiàn)并發(fā)控制。

但由于引入消息隊(duì)列后,每一次的請(qǐng)求都不會(huì)被直接響應(yīng),這對(duì)于異步請(qǐng)求沒(méi)有問(wèn)題,但對(duì)于同步請(qǐng)求,處理起來(lái)就有些麻煩了。還好,在一些成熟的消息隊(duì)列方案中,會(huì)提供request-reply模式,用于處理同步請(qǐng)求。這也是后我們進(jìn)行技術(shù)選型的重要考慮因素。

而對(duì)于事件代理層,現(xiàn)在只需要把事件加入到隊(duì)列中就萬(wàn)事大吉了。

當(dāng)然了,實(shí)踐中還有很多細(xì)節(jié)問(wèn)題要處理,但整體上來(lái)說(shuō),不論是初期的實(shí)現(xiàn)成本,還是后續(xù)的維護(hù)成本,都要比不使用隊(duì)列時(shí)的方案優(yōu)化不少。

消息隊(duì)列有哪些實(shí)現(xiàn)方案

消息隊(duì)列的核心思想非常簡(jiǎn)單,就是一個(gè)生產(chǎn)消費(fèi)隊(duì)列,所以,即便是自己實(shí)現(xiàn),成本也是可以接受的。而且,從面的可以看到,消息隊(duì)列的設(shè)計(jì)基本上與具體業(yè)務(wù)沒(méi)有什么關(guān)聯(lián)。所以業(yè)界也早有很多成熟的實(shí)現(xiàn)方案可供選擇,包括筆者所在的公司內(nèi)部,也有一些消息隊(duì)列方案可供選用。

基于成熟網(wǎng)絡(luò)編程框架開(kāi)發(fā)

由于消息隊(duì)列的原理很簡(jiǎn)單,所以不免會(huì)有人躍躍欲試的想要自己實(shí)現(xiàn)。這當(dāng)然是一個(gè)可以選的方案,但在筆者看來(lái),這不應(yīng)該是一個(gè)首選的方案。因?yàn)橐粋€(gè)完備的消息隊(duì)列需要考慮很多細(xì)節(jié)問(wèn)題,在?MQ的文檔中就詳細(xì)的列舉了這些問(wèn)題:

How do we handle I/O? Does our application block, or do we handle I/O in the background? This is a key design decision. Blocking I/O creates architectures that do not scale well. But background I/O can be very hard to do right.
  • 這個(gè)問(wèn)題是說(shuō)系統(tǒng)采用同步IO,還是異步IO,同步IO代碼邏輯簡(jiǎn)單、直觀、易維護(hù),但性能有限。異步IO性能好,但代碼往往需要按特定的模式去書(shū)寫(xiě),對(duì)于后期接手項(xiàng)目的人來(lái)說(shuō),學(xué)習(xí)和維護(hù)成本較高。
How do we handle dynamic components, i.e., pieces that go away temporarily? Do we formally split components into “clients” and “servers” and mandate that servers cannot disappear? What then if we want to connect servers to servers? Do we try to reconnect every few seconds?
  • 這個(gè)問(wèn)題說(shuō)的是集群的可維護(hù)性和容錯(cuò)性,當(dāng)集群的拓?fù)浒l(fā)生變生時(shí),如何處理,某個(gè)模塊臨時(shí)下線了,相關(guān)聯(lián)的模塊如何容錯(cuò)并以最低的代價(jià)切換到其它的可用模塊上,當(dāng)故障模塊恢復(fù)后,或有新增機(jī)器擴(kuò)容后,又如何以最低的代價(jià)將新增結(jié)點(diǎn)加入拓?fù)渲小?/li>
How do we represent a message on the wire? How do we frame data so it’s easy to write and read, safe from buffer overflows, efficient for small messages, yet adequate for the very largest videos of dancing cats wearing party hats?
  • 這里的問(wèn)題是如保設(shè)計(jì)數(shù)據(jù)串行化協(xié)議,要考慮讀寫(xiě)效率、緩沖區(qū)溢出、短消息的效率、大消息的效率、流媒體傳輸?shù)鹊?,這里補(bǔ)充一個(gè)問(wèn)題:是否需要兼性多種協(xié)議?
How do we handle messages that we can’t deliver immediately? Particularly, if we’re waiting for a component to come back online? Do we discard messages, put them into a database, or into a memory queue?
  • 這個(gè)問(wèn)題其實(shí)是針對(duì)像?MQ這樣的無(wú)持久化的消息隊(duì)列而言的,因?yàn)闆](méi)有持久化,所有的消息只能緩存在內(nèi)存里,如果下游模塊故障或處理速度過(guò)慢就會(huì)造成隊(duì)列溢出,對(duì)于這種情況,是阻塞消息發(fā)送模塊停止發(fā)送消息,直到下游恢復(fù),還是直接丟充一部分消息,需要做出技術(shù)決策。?MQ選擇了前者。
Where do we store message queues? What happens if the component reading from a queue is very slow and causes our queues to build up? What’s our strategy then?
  • 如果消息需要持久化,如何持久化?隊(duì)列消費(fèi)過(guò)慢時(shí)如何處理?
How do we handle lost messages? Do we wait for fresh data, request a resend, or do we build some kind of reliability layer that ensures messages cannot be lost? What if that layer itself crashes?
  • 如保處理消息丟失的問(wèn)題?系統(tǒng)可靠生與數(shù)據(jù)一致性問(wèn)題,CAP原則,也是一個(gè)如何取舍的問(wèn)題
What if we need to use a different network transport. Say, multicast instead of TCP unicast? Or IPv6? Do we need to rewrite the applications, or is the transport abstracted in some layer?
  • 是否兼容多種傳輸層協(xié)議?TCP?UDP?IPC?UNIX SOCKET?
How do we route messages? Can we send the same message to multiple peers? Can we send replies back to an original requester?
  • 如何處理消息路由,舉個(gè)例子:假設(shè),A模塊通過(guò)MQ發(fā)布消息給B模塊和C模塊,B模塊與C模塊收到消息后,需要通過(guò)MQ向A模塊發(fā)送確認(rèn)消息。這時(shí)MQ需要能夠自動(dòng)的將B和C的應(yīng)答消息轉(zhuǎn)發(fā)給A,而不是其它模塊。這個(gè)也是實(shí)現(xiàn)前面提到的request-reply模式的關(guān)健所在。
How do we write an API for another language? Do we re-implement a wire-level protocol or do we repackage a library? If the former, how can we guarantee efficient and stable stacks? If the latter, how can we guarantee interoperability?
  • 如何封MQ自己的交互協(xié)議,為解決數(shù)據(jù)的一致性、消息路由等問(wèn)題,MQ必然要有一個(gè)自己的接口交互邏輯,如錯(cuò)誤重試、消息重發(fā)、地址封裝等,這些邏輯的封裝以何種方式提供?還是要每個(gè)接入的模塊都自己實(shí)現(xiàn)?
How do we represent data so that it can be read between different architectures? Do we enforce a particular encoding for data types? How far is this the job of the messaging system rather than a higher layer?
  • 與第三個(gè)問(wèn)題類(lèi)似,只是角度不同
How do we handle network errors? Do we wait and retry, ignore them silently, or abort?
  • 如保處理各種網(wǎng)絡(luò)異常

看完了這些問(wèn)題,你是否仍然堅(jiān)持要自己實(shí)現(xiàn)一個(gè)MQ呢?

基于?MQ開(kāi)發(fā)

?MQ實(shí)際上是只是一個(gè)LIB,他對(duì)消息通信的模型進(jìn)行了抽象和封裝,覆蓋了上面提到的大部分問(wèn)題,可以說(shuō),基于?MQ開(kāi)發(fā)了一個(gè)MQ是件非常輕松的事情。而且?MQ的文檔如提供了大量的實(shí)例,這些本身已經(jīng)滿足大部分的應(yīng)用場(chǎng)景。使用者可以利用?MQ組合出一套最簡(jiǎn)也最易維護(hù)的消息隊(duì)列系統(tǒng),并按著業(yè)務(wù)需求進(jìn)行有針對(duì)性的優(yōu)化。?MQ唯一缺失的特性就是持久化。

使用成熟的中間件

雖然用?MQ開(kāi)發(fā)一個(gè)MQ非常簡(jiǎn)單,但終究還是要開(kāi)發(fā),而實(shí)際上,很多時(shí)候,MQ都是與業(yè)務(wù)無(wú)關(guān)的,因此也就有了很多可以直接使用的中間件,只需部署好相應(yīng)的環(huán)境就可以直接使用了。

ActiveMQ

重量級(jí)的老牌兒MQ,誕生自JAVA生態(tài),功能完備,相關(guān)的介紹很多,這里不再贅述。

RabbitMQ

同樣是老牌兒MQ,基于erlang實(shí)現(xiàn),語(yǔ)言無(wú)關(guān),功能完備,誕生自金融領(lǐng)域。

Kafka

MQ中的后起之秀,在很多場(chǎng)景下都超越了前輩,誕生自hadoop生態(tài),在大數(shù)據(jù)的支持方面,目前無(wú)人能出其右。

nmq

筆者公司內(nèi)部的MQ,功能比較單一,但性能高,穩(wěn)定性好。

選擇哪個(gè)中間件?

到底應(yīng)該哪個(gè)方案,還是要看具體的需求。在我們的設(shè)計(jì)中,MQ的功能與業(yè)務(wù)無(wú)關(guān),因此優(yōu)先考慮使用已有的中間件搭建。那么具本選擇哪個(gè)中間件呢?先來(lái)梳理下我們對(duì)MQ的需求:

功能需求

如前文所述,除了最基本生產(chǎn)消費(fèi)模型,還需要MQ能支持REQUEST-REPLY模型,以提供對(duì)同步調(diào)用的支持。 此外,如果MQ能提供PUBLISH-SUBSCRIBE模型,則事件代理的實(shí)現(xiàn)可以更加簡(jiǎn)單。

性能需求

考慮未來(lái)一到兩年內(nèi)產(chǎn)品的發(fā)展,消息隊(duì)列的呑吐量預(yù)計(jì)不會(huì)超過(guò) 1W qps,但由單條消息延遲要求較高,希望盡量的短。

可用性需求

因?yàn)槭窃诰€服務(wù),因此需要較高的可用性,但充許有少量消息丟失。

易用性需求

包括學(xué)習(xí)成本、初期的開(kāi)發(fā)部署成本、日常的運(yùn)維成本等。

橫向?qū)Ρ?/h3>

ActiveMQ與RabbitMQ在很多方面都很相似,但ActiveMQ對(duì)非JAVA生態(tài)的支持不及rabbitMQ, 加之精力有限,因此本文重點(diǎn)關(guān)注RabbitMQ。

特性 ActiveMQ RabbitMQ Kafka NMQ
PRODUCER-COMSUMER 支持 支持 支持 -
PUBLISH-SUBSCRIBE 支持 支持 支持 支持
REQUEST-REPLY 支持 支持 - 不支持
API完備性 低(靜態(tài)配置)
多語(yǔ)言支持 支持,JAVA優(yōu)先 語(yǔ)言無(wú)關(guān) 支持,JAVA優(yōu)先 C/C++
單機(jī)呑吐量 萬(wàn)級(jí) 萬(wàn)級(jí) 十萬(wàn)級(jí) 單機(jī)萬(wàn)級(jí)
消息延遲 - 微秒級(jí) 毫秒級(jí) -
可用性 高(主從) 高(主從) 非常高(分布式) 非常高(分布式)
消息丟失 - 理論上不會(huì)丟失 -
消息重復(fù) - 可控制 理論上會(huì)有重復(fù) -
文檔的完備性
提供快速入門(mén) 無(wú)
首次部署難度 -

注: - 表示尚未查找到準(zhǔn)確數(shù)據(jù)

從上表中可以很明顯的看到,最后的決擇就是在rabbitmq與kafka之間了??紤]前面需求,系統(tǒng)的吞吐量不是特別大,但希望延時(shí)盡量的小,而且我們的系統(tǒng)會(huì)基于PYTHON和PHP構(gòu)建。因此綜合上述結(jié)果,RabbitMQ最終勝出。



    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多