1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        消息隊(duì)列MQ/JMS/Kafka,你都了解嗎?

        共 6170字,需瀏覽 13分鐘

         ·

        2021-07-10 04:36

        不點(diǎn)藍(lán)字,我們哪來故事?

        每天 11 點(diǎn)更新文章,餓了點(diǎn)外賣,點(diǎn)擊 ??《無門檻外賣優(yōu)惠券,每天免費(fèi)領(lǐng)!》

        來源:blog.csdn.net/m0_37892044/

        article/details/106603925

        • 1 消息隊(duì)列介紹
          • 1.1 什么是消息隊(duì)列
          • 1.2 消息隊(duì)列(Message queue)有什么用?
          • 1.3 消息隊(duì)列的兩種模式
        • 2 JMS介紹
          • 2.1 JSM消息模型
          • 2.2 JMS消費(fèi)
          • 2.3 JMS編程模型
        • 3 MQ介紹
          • 3.1 AMQP協(xié)議
          • 3.2 RabbitMQ模型
        • 4 Kafka
          • 4.1 kafka原理圖
          • 4.2 生產(chǎn)者結(jié)構(gòu)圖

        是不是平常聽到說消息隊(duì)列啊,JMS啊,MQ啊 、kafka啊巴啦啦的一堆術(shù)語,聽不懂?關(guān)系混亂?今天就讓我們來一起來看看他們都是什么吧。

        1 消息隊(duì)列介紹

        首先舉個(gè)收快遞的栗子,傳統(tǒng)的收快遞,快遞小哥把我們的快遞送到我們的手里。他需要什么條件嗯?

        • 快遞小哥有時(shí)間送,
        • 我們有時(shí)間取,
        • 快遞小哥和我們約定一個(gè)時(shí)間地點(diǎn)。

        但是嗯??爝f小哥有那么多的快遞需要送,可能送我快遞的時(shí)候,我不在家,可能我在家的時(shí)候,快遞小哥送其他的地方的快遞。所以嗯,這個(gè)時(shí)候,要么就是坐在家里等快遞,要么就只能從新約個(gè)時(shí)間點(diǎn)在送。那怎么辦去避免這個(gè)情況嗯?

        于是嗯快遞柜出現(xiàn)了??爝f小哥不用關(guān)心我什么時(shí)候在家,因?yàn)榭爝f小哥有時(shí)間了,就把快遞放快遞柜,而我有時(shí)間了,我就去快遞柜取我的快遞。

        那么快遞柜所起到的作用就是我們今天要收的消息隊(duì)列。我們可以把消息隊(duì)列比作是一個(gè)存放快遞的的快遞柜,當(dāng)我們需要獲取我們快遞的時(shí)候就可以從快遞柜里面拿到屬于我們的快遞。

        1.1 什么是消息隊(duì)列

        我們可以把消息隊(duì)列比作是一個(gè)存放消息的容器,當(dāng)我們需要使用消息的時(shí)候可以取出消息供自己使用。我們看看維基百科上的描述:在計(jì)算機(jī)科學(xué)中,消息隊(duì)列(Message queue)是一種進(jìn)程間通信或同一進(jìn)程的不同線程間的通信方式,軟件的貯列用來處理一系列的輸入,通常是來自用戶。

        是不是很難理解,我們換個(gè)說法來理解

        我們可以把消息隊(duì)列比作是一個(gè)存放消息的容器,當(dāng)我們需要使用消息的時(shí)候可以取出消息供自己使用。

        1.2 消息隊(duì)列(Message queue)有什么用?

        消息隊(duì)列是分布式系統(tǒng)中重要的組件,使用消息隊(duì)列主要是為了通過異步處理提高系統(tǒng)性能和削峰、降低系統(tǒng)耦合性。

        通過異步處理提高系統(tǒng)性能(削峰、減少響應(yīng)所需時(shí)間)

        舉個(gè)例子:我們在某個(gè)網(wǎng)站進(jìn)行注冊賬號(hào),我們需要做如下四件事:

        • 填寫我們的注冊信息;
        • 提交我們的注冊信息;
        • 我們的郵箱收到注冊信息;
        • 我們的短信收到注冊信息。

        如果采用同步串行,所需要的時(shí)間是:a+b+c+d

        圖片

        如果采用同步并行,所需要的時(shí)間是:a+b+max(c,d)

        圖片

        如果采用消息隊(duì)列,所需要的時(shí)間是:a+b+消息隊(duì)列

        圖片

        降低系統(tǒng)耦合性

        舉個(gè)例子,A公司做了某個(gè)系統(tǒng),B公司覺得A公司的某個(gè)功能很好,于是B公司和A公司的系統(tǒng)進(jìn)行了集成。這時(shí)C公司也覺得A公司的這個(gè)功能很好,于是,C公司也和A公司的系統(tǒng)進(jìn)行了集成。以后還有D公司…。

        介于這種情況,A公司的系統(tǒng)和其他公司的耦合度都很高,每集成一個(gè)公司的系統(tǒng),A公司都需要修改自己的系統(tǒng)。如果采用消息隊(duì)列,則變成了如下:

        圖片

        不管以后還有多少公司的應(yīng)用程序想要用A公司的程序,都不需要和A公司進(jìn)行集成,誰需要這個(gè)功能,誰就去消息隊(duì)列里面獲取。

        1.3 消息隊(duì)列的兩種模式

        點(diǎn)對點(diǎn)模式

        應(yīng)用程序由:消息隊(duì)列,發(fā)送方,接收方組成。

        每個(gè)消息都被發(fā)送到一個(gè)特定的隊(duì)列,接收者從隊(duì)列中獲取消息。隊(duì)列保留著消息,直到他們被消費(fèi)或超時(shí)。

        圖片

        發(fā)布訂閱模式

        用用程序有由:角色主題(Topic)、發(fā)布者(Publisher)、訂閱者(Subscriber)構(gòu)成。

        發(fā)布者發(fā)布一個(gè)消息,該消息通過topic傳遞給所有的客戶端。該模式下,發(fā)布者與訂閱者都是匿名的,即發(fā)布者與訂閱者都不知道對方是誰。并且可以動(dòng)態(tài)的發(fā)布與訂閱Topic。Topic主要用于保存和傳遞消息,且會(huì)一直保存消息直到消息被傳遞給客戶端。

        圖片

        介紹完了消息隊(duì)列,接著我們介紹JMS

        2 JMS介紹

        JMS即Java消息服務(wù)(Java Message Service)應(yīng)用程序接口,是一個(gè)Java平臺(tái)中關(guān)于面向消息中間件(MOM)的API,類似于JDBC。用于在兩個(gè)應(yīng)用程序之間,或分布式系統(tǒng)中發(fā)送消息,進(jìn)行異步通信。它提供創(chuàng)建、發(fā)送、接收、讀取消息的服務(wù)。由Sun公司和它的合作伙伴設(shè)計(jì)的應(yīng)用程序接口和相應(yīng)語法,使得Java程序能夠和其他消息組件進(jìn)行通信。

        JMS是一個(gè)消息服務(wù)的標(biāo)準(zhǔn)或者說是規(guī)范,允許應(yīng)用程序組件基于JavaEE平臺(tái)創(chuàng)建、發(fā)送、接收和讀取消息。它使分布式通信耦合度更低,消息服務(wù)更加可靠以及異步性。

        介紹到這里,應(yīng)該明白了消息隊(duì)列和JMS的區(qū)別了吧?

        • 消息隊(duì)列:計(jì)算機(jī)科學(xué)中,A和B進(jìn)行通信的一種方式。
        • JMS:java平臺(tái)之間分布式通信的一種標(biāo)準(zhǔn)或者規(guī)范。

        換句話說,JMS就是java對于消息隊(duì)列的一種實(shí)現(xiàn)方式。

        2.1 JSM消息模型

        點(diǎn)對點(diǎn),發(fā)布訂閱,消息隊(duì)列中已經(jīng)說的很清楚了,這里就不重復(fù)說了。

        2.2 JMS消費(fèi)

        • 同步(Synchronous)

        訂閱者/接收方通過調(diào)用 receive()來接收消息。在receive()方法中,線程會(huì)阻塞直到消息到達(dá)或者到指定時(shí)間后消息仍未到達(dá)。

        • 異步(Asynchronous)

        消息訂閱者需注冊一個(gè)消息監(jiān)聽者,類似于事件監(jiān)聽器,只要消息到達(dá),JMS服務(wù)提供者會(huì)通過調(diào)用監(jiān)聽器的onMessage()遞送消息。

        2.3 JMS編程模型

        JMS編程模型非常類似于JDBC?;貞浺幌?,我們之前講到的MyBatis。

        • SqlSessionFactoryBuilder去構(gòu)造SqlSessionFactory會(huì)話工廠;
        • SqlSessionFactory會(huì)話工廠給我們打開SqlSession會(huì)話;
        • SqlSession幫我們?nèi)ミB接數(shù)據(jù)庫,接著我們就可以執(zhí)行增刪查改。
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession openSession = sqlSessionFactory.openSession(true);
        ProjectMapper mapper = openSession.getMapper(ProjectMapper.class);
        mapper.queryAllTaskByInit("init");

        JMS模型如下

        • Connection Factory給我創(chuàng)建Connection連接;
        • Connection連接給我們創(chuàng)建了Session會(huì)話;
        • Session會(huì)話給我們創(chuàng)建消費(fèi)者和生產(chǎn)者;
        • 生產(chǎn)者生成消息;
        • 消費(fèi)者消費(fèi)消息;
        圖片

        3 MQ介紹

        上文中,我們說到了,JMS他并不是一種真正意義的技術(shù),而是一種接口,一種規(guī)范。就想JDBC一樣,無論是mybatis、hibernate,還是springJPA,不管你是那種技術(shù)實(shí)現(xiàn),反正你得遵守JDBC的規(guī)范。

        在Java中,目前基于JMS實(shí)現(xiàn)的消息隊(duì)列常見技術(shù)有ActiveMQ、RabbitMQ、RocketMQ。值得注意的是,RocketMQ并沒有完全遵守JMS規(guī)范,并且Kafka不是JMS的實(shí)現(xiàn)。

        3.1 AMQP協(xié)議

        這里我們以RabbitMQ為例介紹MQ,首先介紹下AMQP

        AMQP協(xié)議(Advanced Message Queuing Protocol,高級消息隊(duì)列協(xié)議)是一個(gè)進(jìn)程間傳遞異步消息的網(wǎng)絡(luò)協(xié)議。

        AMQP 模型

        圖片

        AMQP 工作過程

        發(fā)布者(Publisher)發(fā)布消息(Message),經(jīng)由交換機(jī)(Exchange)。

        交換機(jī)根據(jù)路由規(guī)則將收到的消息分發(fā)給與該交換機(jī)綁定的隊(duì)列、(Queue)。

        最后 AMQP 代理會(huì)將消息投遞給訂閱了此隊(duì)列的消費(fèi)者,或者消費(fèi)者按照需求自行獲取。

        RabbitMQ是MQ產(chǎn)品的典型代表,是一款基于AMQP協(xié)議可復(fù)用的企業(yè)消息系統(tǒng)

        3.2 RabbitMQ模型

        RabbitMQ由兩部分組成,分別是服務(wù)端和應(yīng)用端;

        • 服務(wù)端包括:隊(duì)列和交換機(jī)。
        • 客戶端包括:生產(chǎn)者和消費(fèi)者。

        在rabbitmq server上可以創(chuàng)建多個(gè)虛擬的message broker。每一個(gè)broker本質(zhì)上是一個(gè)mini-rabbitmq server,分別管理各自的exchange,和bindings。

        broker相當(dāng)于物理的server,可以為不同app提供邊界隔離,使得應(yīng)用安全的運(yùn)行在不同的broker實(shí)例上,相互之間不會(huì)干擾。producer和consumer連接rabbit server需要指定一個(gè)broker。

        圖片
        圖片

        Exchange有4種類型:direct(默認(rèn)),fanout, topic, 和headers

        • Direct:直接交換器,工作方式類似于單播,Exchange會(huì)將消息發(fā)送完全匹配ROUTING_KEY的Queue。
        • Fanout:廣播是式交換器,不管消息的ROUTING_KEY設(shè)置為什么,Exchange都會(huì)將消息轉(zhuǎn)發(fā)給所有綁定的Queue(所謂綁定就是將一個(gè)特定的 Exchange 和一個(gè)特定的 Queue 綁定起來。Exchange 和Queue的綁定可以是多對多的關(guān)系)。
        • Topic:主題交換器,工作方式類似于組播,Exchange會(huì)將消息轉(zhuǎn)發(fā)和ROUTING_KEY匹配模式相同的所有隊(duì)列,比如,ROUTING_KEY為user.stock的Message會(huì)轉(zhuǎn)發(fā)給綁定匹配模式為 * .stock,user.stock, * . * 和#.user.stock.#的隊(duì)列。( * 表是匹配一個(gè)任意詞組,#表示匹配0個(gè)或多個(gè)詞組)。

        至于如何在代碼中使用RabbitMQ,這里我們先不擼代碼,本文目前只介紹理論梳理知識(shí)點(diǎn)。

        4 Kafka

        上完中我們提到過,kafka不是JMS的實(shí)現(xiàn),因此在MQ章節(jié)中,我們沒有提及到它?,F(xiàn)在我們開始學(xué)習(xí)kafka吧。

        先來放張kafka的原理圖,相信你看到這個(gè)圖片時(shí),內(nèi)心是奔潰的。我草,啥玩意。接下來我們就一點(diǎn)一點(diǎn)的消化吧。

        4.1 kafka原理圖

        圖片

        先介紹上圖中的術(shù)語。

        • Producer :消息生產(chǎn)者,就是向kafka broker發(fā)消息的客戶端。
        • Consumer :消息消費(fèi)者,向kafka broker取消息的客戶端。
        • Topic :kafka給消息提供的分類方式。broker用來存儲(chǔ)不同topic的消息數(shù)據(jù)。一個(gè)Topic可以認(rèn)為是一類消息,每個(gè)topic將被分成多個(gè)partition(區(qū)),每個(gè)partition在存儲(chǔ)層面是append log文件。任何發(fā)布到此partition的消息都會(huì)被直接追加到log文件的尾部,每條消息在文件中的位置稱為offset(偏移量),offset為一個(gè)long型數(shù)字,它是唯一標(biāo)記一條消息。它唯一的標(biāo)記一條消息。kafka并沒有提供其他額外的索引機(jī)制來存儲(chǔ)offset,因?yàn)樵趉afka中幾乎不允許對消息進(jìn)行“隨機(jī)讀寫”。
        • broker:中間件的kafka cluster,存儲(chǔ)消息,是由多個(gè)server組成的集群。
        • Partition:為了實(shí)現(xiàn)擴(kuò)展性,一個(gè)非常大的topic可以分布到多個(gè)broker(即服務(wù)器)上,一個(gè)topic可以分為多個(gè)partition,每個(gè)partition是一個(gè)有序的隊(duì)列。partition中的每條消息都會(huì)被分配一個(gè)有序的id(offset)。kafka只保證按一個(gè)partition中的順序?qū)⑾l(fā)給consumer,不保證一個(gè)topic的整體(多個(gè)partition間)的順序。
        • Offset:kafka的存儲(chǔ)文件都是按照offset.kafka來命名,例如你想找位于2049的位置,只要找到2048.kafka的文件即可。當(dāng)然the first offset就是00000000000.kafka。

        類似于JMS的特性,但不是JMS規(guī)范的實(shí)現(xiàn)。kafka對消息保存時(shí)根據(jù)Topic進(jìn)行歸類,發(fā)送消息者成為Producer,消息接受者成為Consumer,此外kafka集群有多個(gè)kafka實(shí)例組成,每個(gè)實(shí)例(server)成為broker。無論是kafka集群,還是producer和consumer都依賴于zookeeper來保證系統(tǒng)可用性集群保存信息。

        kafka基于文件存儲(chǔ)。通過分區(qū),可以將日志內(nèi)容分散到多個(gè)server上,來避免文件尺寸達(dá)到單機(jī)磁盤的上限,每個(gè)partiton都會(huì)被當(dāng)前server(kafka實(shí)例)保存;可以將一個(gè)topic切分多任意多個(gè)partitions,來消息保存/消費(fèi)的效率.此外越多的partitions意味著可以容納更多的consumer,有效提升并發(fā)消費(fèi)的能力。

        kafka和JMS不同的是:即使消息被消費(fèi),消息仍然不會(huì)被立即刪除。日志文件將會(huì)根據(jù)broker中的配置要求,保留一定的時(shí)間之后刪除。

        Kafka高可用機(jī)制

        • 多個(gè)broker組成,每個(gè)broker是一個(gè)節(jié)點(diǎn);
        • 你創(chuàng)建一個(gè)topic,這個(gè)topic可以劃分為多個(gè)partition,每個(gè)partition可以存在于不同的broker上,每個(gè)partition就放一部分?jǐn)?shù)據(jù)。
        • 采用replica副本機(jī)制,每個(gè)partition的數(shù)據(jù)都會(huì)同步到其他機(jī)器上,形成多個(gè)replica副本。
        • 所有replica會(huì)選舉一個(gè)leader出來,那么生產(chǎn)和消費(fèi)都跟這個(gè)leader打交道,然后其他replica就是follower。
        • 讀數(shù)據(jù)時(shí),從leader讀取,寫數(shù)據(jù)時(shí),leader把數(shù)據(jù)同步到所有follower上去。如果某個(gè)broker宕機(jī)了,這個(gè)broker在其他的broker還保留副本,假設(shè)這個(gè)broker上面存在leader,那么就重新選一個(gè)leader。

        內(nèi)容有點(diǎn)多,需要結(jié)合圖片一點(diǎn)一點(diǎn)消化

        4.2 生產(chǎn)者結(jié)構(gòu)圖

        圖片

        至此,雖然看的云里霧里,不過相信你們還是能區(qū)分了吧?

        整理一下:

        • 消息隊(duì)列:指計(jì)算機(jī)領(lǐng)域中,A和B通信的一種通信方式;
        • JMS:Java中對于消息隊(duì)列的接口規(guī)范;
        • ActiveMQ/RabbitMQ:JMS接口規(guī)范具體實(shí)現(xiàn)的一種技術(shù);
        • RocketMQ:不完全是JMS接口規(guī)范具體實(shí)現(xiàn)的一種技術(shù);
        • Kafka:非JMS接口規(guī)范具體實(shí)現(xiàn)的一種技術(shù);
        - END -

        往期推薦

        GitHub的AI寫代碼翻車了,會(huì)在注釋里給你寫上what the f***,因?yàn)?..

        深圳一普通中學(xué)老師工資單曝光,秒殺程序員

        重裝IDEA如何同步個(gè)人配置?

        還可以這么理解 Elasticsearch

        下方二維碼關(guān)注我

        技術(shù)草根堅(jiān)持分享 編程,算法,架構(gòu)

        看完文章,餓了點(diǎn)外賣,點(diǎn)擊 ??《無門檻外賣優(yōu)惠券,每天免費(fèi)領(lǐng)!》

        朋友,助攻一把!點(diǎn)個(gè)在看!
        瀏覽 84
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            靠逼视频网站在线观看 | 看插逼视频 | 国产精品久久久久永久免费观看 | 色噜噜在线视频观看 | 青草色在线| 欧洲一级毛片AV | 超碰在线国产97 | 特级大胆gogo4444人体 | 九一精品国产福利在线看 | 寡妇高潮免费视频一区二区三区 |