扫盲消息队列 | 消息中间件 | Kafka
先吐槽
我真的寫(xiě)技術(shù)文章寫(xiě)到懷疑人生,我翻看歷史發(fā)文記錄,只要我一本正經(jīng)的寫(xiě)的技術(shù)文章,都沒(méi)人看,但是!一發(fā)閑扯淡的內(nèi)容,閱讀量肯定是技術(shù)文的好幾倍(讀者爸爸們別這么搞嘛)
這說(shuō)明啥?說(shuō)明學(xué)習(xí)還是太枯燥無(wú)趣了,但是你想想,每天就網(wǎng)上看閑扯淡的文章,這咋能進(jìn)大廠嘛!對(duì)吧。
再接受幾次這樣的打擊我都不想寫(xiě)技術(shù)文章了。哎!不過(guò)我也就嘴上說(shuō)說(shuō),我還是會(huì)堅(jiān)持寫(xiě)下去的。
反正你們有沒(méi)有認(rèn)真看我不知道,我寫(xiě)完一遍這個(gè)文章,每個(gè)知識(shí)點(diǎn)細(xì)節(jié)我都滾瓜亂熟了,因?yàn)槎际俏乙粋€(gè)字一個(gè)字敲出來(lái)的。
開(kāi)始正文吧!21世紀(jì)的流水線工人,消息隊(duì)列是一定要會(huì)的。
我真的不能再貼心了!!!!
背景
image-20200420194331765分布式微服務(wù)系統(tǒng)下,凡是可以“排隊(duì)”去做的事情,都可以使用消息隊(duì)列。網(wǎng)上買(mǎi)東西同樣也需要“排隊(duì)付款”,但是有人說(shuō),我點(diǎn)確認(rèn)付款后馬上就顯示成功了,沒(méi)感覺(jué)到排隊(duì)呀?其實(shí)在后臺(tái)系統(tǒng)中是排了,只不過(guò)排隊(duì)的時(shí)間對(duì)于人來(lái)說(shuō)有點(diǎn)短,可能1-2秒就結(jié)束了,但是對(duì)于計(jì)算機(jī)來(lái)說(shuō),這1-2秒的時(shí)間很長(zhǎng)了。
大型分布式系統(tǒng)建設(shè)中,消息隊(duì)列主要解決應(yīng)用耦合、異步消息、流量削鋒等問(wèn)題。實(shí)現(xiàn)高性能、高可用、可伸縮和最終一致性架構(gòu)。是大型分布式系統(tǒng)不可缺少的中間件。消息發(fā)布者只管把消息發(fā)布到 MQ 中而不用管誰(shuí)來(lái)取,消息使用者只管從 MQ 中取消息而不管是誰(shuí)發(fā)布的。這樣發(fā)布者和使用者都不用知道對(duì)方的存在。
Web應(yīng)用程序毫無(wú)疑問(wèn)有大量的代碼執(zhí)行HTTP請(qǐng)求/響應(yīng)周期的一部分。這適用于更快的任務(wù)耗費(fèi)數(shù)百毫秒內(nèi)或更少。然而,有些處理,還需要耗時(shí)更多甚至最終會(huì)是一兩秒鐘緩慢的同步執(zhí)行,在如此長(zhǎng)時(shí)間的調(diào)用流轉(zhuǎn)中,肯定有一些調(diào)用是可以不同步的,如下單送積分,用戶(hù)下單是最主要的,送積分的操作可以異步去做,訂單支付成功給用戶(hù)的短信通知,返回支付訂單進(jìn)入下一環(huán)節(jié)更更好,短信通知可以異步去發(fā)送,為了應(yīng)對(duì)諸如此類(lèi)的異步操作,消息隊(duì)列這門(mén)技術(shù)應(yīng)運(yùn)而生。
message-queue-example在計(jì)算機(jī)科學(xué)中,消息隊(duì)列(Message queue)是一種進(jìn)程間通信或同一進(jìn)程的不同線程間的通信方式。實(shí)際上,消息隊(duì)列常常保存在鏈表結(jié)構(gòu)中。[2]擁有權(quán)限的進(jìn)程可以向消息隊(duì)列中寫(xiě)入或讀取消息。
目前,有很多消息隊(duì)列有很多開(kāi)源的實(shí)現(xiàn),包括JBoss Messaging、JORAM、Apache ActiveMQ、Sun Open Message Queue、RabbitMQ[3]、IBM MQ[4]、Apache Qpid[5]、Apache RocketMQ[6]和HTTPSQS。[7]
說(shuō)了這么多沒(méi)用的,消息隊(duì)列到底在企業(yè)里怎么用的?
我就直接上兩段代碼吧
發(fā)送一條消息demo
public?class?MqProducer?{private?final?Logger?LOG?=?LoggerFactory.getLogger(MqProducer.class);@Resourceprivate?Producer?payProducer;public?void?sendPayMsg(String?msg)?{try?{LOG.debug("send?msg:{}",?msg);payProducer.send(msg);//發(fā)送出去一條消息。}?catch?(MQException?e)?{LOG.error("mq消息異常?message:{}",?msg,?e);}} }接收一個(gè)消息demo
public?class?DemoConsumer?{/***?注意:服務(wù)端對(duì)單ip創(chuàng)建相同主題相同隊(duì)列的消費(fèi)者實(shí)例數(shù)有限制,超過(guò)100個(gè)拒絕創(chuàng)建.*?*/private?static?IConsumerProcessor?consumer;public?static?void?main(String[]?args)?throws?Exception?{Properties?properties?=?new?Properties();properties.setProperty(ConsumerConstants.SubscribeGroup,?"dache.risk.log.queue.v2");//?創(chuàng)建topic對(duì)應(yīng)的consumer對(duì)象(注意每次build調(diào)用會(huì)產(chǎn)生一個(gè)新的實(shí)例)consumer?=?KafkaClient.buildConsumerFactory(properties,?"topic.xxx.xxx");//?調(diào)用recvMessageWithParallel設(shè)置listenerconsumer.recvMessageWithParallel(String.class,?new?IMessageListener()?{@Overridepublic?ConsumeStatus?recvMessage(Message?message,?MessagetContext?context)?{//TODO:業(yè)務(wù)側(cè)的消費(fèi)邏輯代碼try?{System.out.println("message=["?+?message.getBody()?+?"]??partition="?+?message.getParttion());}?catch?(Exception?e)?{e.printStackTrace();}return?ConsumeStatus.CONSUME_SUCCESS;}});} }消息長(zhǎng)什么樣子?
{"businessType":1,"cityId":10,"ctime":1567426767077,"dataKey":20190902,"logType":1,"phone":"13212341234","uid":12345678,"userType":1,"uuid":"32EA02C86D78863"}代碼呢,就是普通的java代碼,只不過(guò)引入了一個(gè)kafka的jar,消息就是json串,使用消息隊(duì)列真的就這么點(diǎn)代碼,剩下的內(nèi)容都是業(yè)務(wù)代碼了。
新手關(guān)注消息隊(duì)列,主要關(guān)注兩個(gè)最重要的概念就行了,一個(gè)是生產(chǎn)者,一個(gè)是消費(fèi)者,兩者的關(guān)系和我們?nèi)粘0l(fā)短信一樣,短信是通過(guò)手機(jī)號(hào)發(fā)送接收,系統(tǒng)間消息是通過(guò)topic,可以理解成手機(jī)號(hào)。
Producer消息的生產(chǎn)方,如支付系統(tǒng)確認(rèn)用戶(hù)已經(jīng)支付,支付系統(tǒng)要通知訂單系統(tǒng)和物流系統(tǒng),支付系統(tǒng)就是生產(chǎn)者。
Consumer消費(fèi)的接收方,Producer 的案例中,物流系統(tǒng)就是消費(fèi)方,前兩個(gè)都比較簡(jiǎn)單,我就不多說(shuō)了。
Topic每條發(fā)布到MQ集群的消息都有一個(gè)類(lèi)別,這個(gè)類(lèi)別被稱(chēng)為topic,可以理解成一類(lèi)消息的名字。所有的消息都以topic作為單位進(jìn)行歸類(lèi)。
日常開(kāi)發(fā)中需要關(guān)心哪些指標(biāo)
1.生產(chǎn)消息數(shù)目
每分鐘幾百幾千個(gè)都正常水平吧,業(yè)務(wù)繁忙的每分鐘幾萬(wàn)幾十萬(wàn)也是有的
image-202004201933503712.消息延遲情況
延遲越低越好啦,幾百毫秒正常水平。
image-202004201935407663.消息積壓數(shù)
這個(gè)當(dāng)然是要0了,如果遇到消費(fèi)端服務(wù)器上線,可能會(huì)有段時(shí)間積壓正常,這個(gè)指標(biāo),日常應(yīng)該都是0才對(duì)。
image-20200420194052328為什么使用消息隊(duì)列
開(kāi)頭不是說(shuō)了,排隊(duì)能解決一個(gè)問(wèn)題,就是削峰,意思就是流量洪峰來(lái)了,收銀員結(jié)賬速度依舊是一樣的,不會(huì)被累死,還有兩個(gè)重要的概念就是解耦、異步
使用消息隊(duì)列有什么缺點(diǎn)呢?
這個(gè)新手也一定要知道啦,因?yàn)槊嬖嚬贂?huì)問(wèn)。
消息丟失問(wèn)題: 任何系統(tǒng)不能保證萬(wàn)無(wú)一失,比如 Producer 發(fā)出了10000條消息,Consumer 只收到了 9999 個(gè)消息,有1個(gè)丟了,Consumer 能否接受丟一條?如果是訂單成功短信可以接受丟一條,就是有一個(gè)顧客沒(méi)有通知到已經(jīng)發(fā)貨,但貨還是發(fā)出去了,如果是支付系統(tǒng),用戶(hù)已經(jīng)付款卻因?yàn)橄G失沒(méi)有通知到訂單或物流系統(tǒng),那恐怕顧客要找你麻煩了。
消息重復(fù)問(wèn)題:如 Producer 發(fā)出了10000條消息,Consumer 只收到了 10001 條消息,有一條是重復(fù)的,業(yè)務(wù)能否接受一條重復(fù)的消息,這個(gè)是作為系統(tǒng)設(shè)計(jì)者要考慮的問(wèn)題。
消息的順序問(wèn)題:如 Producer 發(fā)送順序是123,Consumer 收到的消息是132,要考慮消費(fèi)端是否對(duì)順序敏感。
一致性問(wèn)題: 如消息丟失問(wèn)題真的發(fā)生且無(wú)法找回,會(huì)造成兩個(gè)系統(tǒng)的數(shù)據(jù)最終不一致,如果消息延遲,會(huì)造成短暫不一致。
ActiveMQ vs Kafka vs RabbitMQ
RabbitMQ、Kafka和ActiveMQ都是用于提供異步通信和解耦進(jìn)程(分離消息的發(fā)送方和接收方)的消息傳遞技術(shù)。
它們被稱(chēng)為消息隊(duì)列、消息代理或消息傳遞工具。RabbitMQ、Kafka和ActiveMQ都有相同的基本用途,但它們的工作方式不同。Kafka是一個(gè)高吞吐量的分布式消息傳遞系統(tǒng)。
RabbitMQ是一個(gè)基于AMQP的可靠消息代理。ActiveMQ和Kafka都是Apache的產(chǎn)品,都是用Java編寫(xiě)的,RabbitMQ是用Erlang編寫(xiě)的。
進(jìn)BAT你就研究這其中一個(gè)就可以了,數(shù)量不在多,重點(diǎn)是深度。
ActiveMQ,Kafka和RabbitMQ有哪些替代方案?
這些在國(guó)內(nèi)都不是很常用,新手了解一下就可以了,反正,知識(shí)廣度&眼界是有了。
Apollo:在現(xiàn)有REST API的基礎(chǔ)上構(gòu)建一個(gè)通用的GraphQL API,可以快速發(fā)布新的應(yīng)用程序特性,而無(wú)需等待后端更改。
IBM MQ:它是一個(gè)消息傳遞中間件,可以簡(jiǎn)化和加速跨多個(gè)平臺(tái)的不同應(yīng)用程序和業(yè)務(wù)數(shù)據(jù)的集成。它提供了經(jīng)過(guò)驗(yàn)證的企業(yè)級(jí)消息傳遞功能,能夠熟練而安全地移動(dòng)信息。
ZeroMQ:擴(kuò)展性好,開(kāi)發(fā)比較靈活,采用C語(yǔ)言實(shí)現(xiàn),實(shí)際上他只是一個(gè)socket庫(kù)的重新封裝,如果我們做為消息隊(duì)列使用,需要開(kāi)發(fā)大量的代碼
Amazon SQS
關(guān)于消息隊(duì)列的常見(jiàn)面試題
為什么使用消息隊(duì)列?
消息隊(duì)列有什么優(yōu)點(diǎn)和缺點(diǎn)?
那為什么Kafka的吞吐量遠(yuǎn)高于其他同類(lèi)中間件?
比較重要的關(guān)鍵字嗎?比如Producer,Consumer,Partition,Broker,你都是怎么理解的?
參考資料
Thorough Introduction to Apache Kafka
推薦一本書(shū)《深入理解Kafka:核心設(shè)計(jì)與實(shí)踐原理》,微信讀書(shū)就可以免費(fèi)閱讀。
總結(jié)
以上是生活随笔為你收集整理的扫盲消息队列 | 消息中间件 | Kafka的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 程序员过关斩将-- 工作好多年可能还未真
- 下一篇: 7种方法帮助企业改进软件维护效率