欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android MessageQueue消息隊(duì)列主要作用詳解

 更新時(shí)間:2023年02月16日 16:43:54   作者:守住Android最后的光  
Android 消息機(jī)制主要指的是 Handler 的運(yùn)行機(jī)制及其所依賴的 MessageQueue 和 Looper 的工作過程,Handler、MessageQueue、Looper組成一個(gè)相互聯(lián)系的整體。本文先從 MessageQueue 的源碼來說明其實(shí)現(xiàn)原理

定義

隊(duì)列是 Apache RocketMQ 中消息存儲(chǔ)和傳輸?shù)膶?shí)際容器,也是 Apache RocketMQ 消息的最小存儲(chǔ)單元。 Apache RocketMQ 的所有主題都是由多個(gè)隊(duì)列組成,以此實(shí)現(xiàn)隊(duì)列數(shù)量的水平拆分和隊(duì)列內(nèi)部的流式存儲(chǔ)。

隊(duì)列的主要作用如下:

  • 存儲(chǔ)順序性 隊(duì)列天然具備順序性,即消息按照進(jìn)入隊(duì)列的順序?qū)懭氪鎯?chǔ),同一隊(duì)列間的消息天然存在順序關(guān)系,隊(duì)列頭部為最早寫入的消息,隊(duì)列尾部為最新寫入的消息。消息在隊(duì)列中的位置和消息之間的順序通過位點(diǎn)(Offset)進(jìn)行標(biāo)記管理。
  • 流式操作語義 Apache RocketMQ 基于隊(duì)列的存儲(chǔ)模型可確保消息從任意位點(diǎn)讀取任意數(shù)量的消息,以此實(shí)現(xiàn)類似聚合讀取、回溯讀取等特性,這些特性是RabbitMQ、ActiveMQ等非隊(duì)列存儲(chǔ)模型不具備的。

模型關(guān)系

在整個(gè) Apache RocketMQ 的領(lǐng)域模型中,隊(duì)列所處的流程和位置如下:

Apache RocketMQ 默認(rèn)提供消息可靠存儲(chǔ)機(jī)制,所有發(fā)送成功的消息都被持久化存儲(chǔ)到隊(duì)列中,配合生產(chǎn)者和消費(fèi)者客戶端的調(diào)用可實(shí)現(xiàn)至少投遞一次的可靠性語義。

Apache RocketMQ 隊(duì)列模型和Kafka的分區(qū)(Partition)模型類似。在 Apache RocketMQ 消息收發(fā)模型中,隊(duì)列屬于主題的一部分,雖然所有的消息資源以主題粒度管理,但實(shí)際的操作實(shí)現(xiàn)是面向隊(duì)列。例如,生產(chǎn)者指定某個(gè)主題,向主題內(nèi)發(fā)送消息,但實(shí)際消息發(fā)送到該主題下的某個(gè)隊(duì)列中。

Apache RocketMQ 中通過修改隊(duì)列數(shù)量,以此實(shí)現(xiàn)橫向的水平擴(kuò)容和縮容。

內(nèi)部屬性

讀寫權(quán)限

  • 定義:當(dāng)前隊(duì)列是否可以讀寫數(shù)據(jù)。
  • 取值:由服務(wù)端定義,枚舉值如下
  • 6:讀寫狀態(tài),當(dāng)前隊(duì)列允許讀取消息和寫入消息。
  • 4:只讀狀態(tài),當(dāng)前隊(duì)列只允許讀取消息,不允許寫入消息。
  • 2:只寫狀態(tài),當(dāng)前隊(duì)列只允許寫入消息,不允許讀取消息。
  • 0:不可讀寫狀態(tài),當(dāng)前隊(duì)列不允許讀取消息和寫入消息。
  • 約束:隊(duì)列的讀寫權(quán)限屬于運(yùn)維側(cè)操作,不建議頻繁修改。

行為約束

每個(gè)主題下會(huì)由一到多個(gè)隊(duì)列來存儲(chǔ)消息,每個(gè)主題對(duì)應(yīng)的隊(duì)列數(shù)與消息類型以及實(shí)例所處地域(Region)相關(guān),隊(duì)列數(shù)暫不支持修改。

版本兼容性

隊(duì)列的名稱屬性在 Apache RocketMQ 服務(wù)端的不同版本中有如下差異:

  • 服務(wù)端3.x/4.x版本:隊(duì)列名稱由{主題名稱}+{BrokerID}+{QueueID}三元組組成,和物理節(jié)點(diǎn)綁定。
  • 服務(wù)端5.x版本:隊(duì)列名稱為一個(gè)集群分配的全局唯一的字符串組成,和物理節(jié)點(diǎn)解耦。

因此,在開發(fā)過程中,建議不要對(duì)隊(duì)列名稱做任何假設(shè)和綁定。如果您在代碼中自定義拼接隊(duì)列名稱并和其他操作進(jìn)行綁定,一旦服務(wù)端版本升級(jí),可能會(huì)出現(xiàn)隊(duì)列名稱無法解析的兼容性問題。

使用建議

按照實(shí)際業(yè)務(wù)消耗設(shè)置隊(duì)列數(shù)

Apache RocketMQ 的隊(duì)列數(shù)可在創(chuàng)建主題或變更主題時(shí)設(shè)置修改,隊(duì)列數(shù)量的設(shè)置應(yīng)遵循少用夠用原則,避免隨意增加隊(duì)列數(shù)量。

主題內(nèi)隊(duì)列數(shù)過多可能對(duì)導(dǎo)致如下問題:

  • 集群元數(shù)據(jù)膨脹 Apache RocketMQ 會(huì)以隊(duì)列粒度采集指標(biāo)和監(jiān)控?cái)?shù)據(jù),隊(duì)列過多容易造成管控元數(shù)據(jù)膨脹。
  • 客戶端壓力過大 Apache RocketMQ 的消息讀寫都是針對(duì)隊(duì)列進(jìn)行操作,隊(duì)列過多容易產(chǎn)生空輪詢請(qǐng)求,增加系統(tǒng)負(fù)荷。

常見隊(duì)列增加場景

需要增加隊(duì)列實(shí)現(xiàn)物理節(jié)點(diǎn)負(fù)載均衡 Apache RocketMQ 每個(gè)主題的多個(gè)隊(duì)列可以分布在不同的服務(wù)節(jié)點(diǎn)上,在集群水平擴(kuò)容增加節(jié)點(diǎn)后,為了保證集群流量的負(fù)載均衡,建議在新的服務(wù)節(jié)點(diǎn)上新增隊(duì)列,或?qū)⑴f的隊(duì)列遷移到新的服務(wù)節(jié)點(diǎn)上。

需要增加隊(duì)列實(shí)現(xiàn)順序消息性能擴(kuò)展 在 Apache RocketMQ 服務(wù)端4.x版本中,順序消息的順序性在隊(duì)列內(nèi)生效的,因此順序消息的并發(fā)度會(huì)在一定程度上受隊(duì)列數(shù)量的影響,因此建議僅在系統(tǒng)性能瓶頸時(shí)再增加隊(duì)列。

消息隊(duì)列相關(guān)概念

生產(chǎn)者(Producer): 負(fù)責(zé)產(chǎn)生消息;

消費(fèi)者(Consumer): 負(fù)責(zé)消費(fèi)消息;

消息(Message): 在應(yīng)用間傳送的數(shù)據(jù)。消息可以非常簡單,比如只包含文本字符串,也可以更復(fù)雜,可能包含嵌入對(duì)象;

消息隊(duì)列(Message Queue): 一種應(yīng)用間的通信方式,消息發(fā)送后可以立即返回,由消息系統(tǒng)來確保消息的可靠傳遞。消息發(fā)布者只管把消息發(fā)布到 MQ 中而不用管誰來取,消息使用者只管從 MQ 中取消息而不管是誰發(fā)布的。這樣發(fā)布者和使用者都不用知道對(duì)方的存在。

消息代理(Message Broker): 負(fù)責(zé)存儲(chǔ)/轉(zhuǎn)發(fā)消息,轉(zhuǎn)發(fā)分為推和拉兩種。

  • 拉是指Consumer主動(dòng)從Message Broker獲取消息;
  • 推是指Message Broker主動(dòng)將Consumer感興趣的消息推送給Consumer。

消息隊(duì)列的消費(fèi)場景

消息至多被消費(fèi)一次

該場景是最容易滿足的,特點(diǎn)是整個(gè)消息隊(duì)列吞吐量大,實(shí)現(xiàn)簡單。適合能容忍丟消息,消息重復(fù)消費(fèi)的任務(wù)。

a)Producer發(fā)送消息到Message Broker階段:

Producer發(fā)消息給Message Broker,不要求Message Broker對(duì)接收到的消息響應(yīng)確認(rèn),Producer也不用關(guān)心Message Broker是否收到消息了。

b)Message Broker存儲(chǔ)/轉(zhuǎn)發(fā)階段:

對(duì)Message Broker的存儲(chǔ)不要求持久性,轉(zhuǎn)發(fā)消息時(shí)也不用關(guān)心Consumer是否真的收到了。

c)Consumer消費(fèi)階段:

Consumer從Message Broker中獲取到消息后,可以從Message Broker刪除消息,或Message Broker在消息被Consumer拿去消費(fèi)時(shí)刪除消息,不用關(guān)心Consumer最后對(duì)消息的處理結(jié)果。

消息至少被消費(fèi)一次

適合不能容忍丟消息,但允許重復(fù)消費(fèi)的任務(wù)。

a)Producer發(fā)送消息到Message Broker階段:

Producer發(fā)消息給Message Broker,Message Broker必須響應(yīng)對(duì)消息的確認(rèn)。

b)Message Broker存儲(chǔ)/轉(zhuǎn)發(fā)階段:

Message Broker必須提供持久性保障,轉(zhuǎn)發(fā)消息時(shí),Message Broker需要Consumer通知?jiǎng)h除消息,才能將消息刪除。

c)Consumer消費(fèi)階段:

Consumer從Message Broker中獲取到消息,必須在消費(fèi)完成后,Message Broker上的消息才能被刪除。

消息僅被消費(fèi)一次

適合對(duì)消息消費(fèi)情況要求非常高的任務(wù),實(shí)現(xiàn)較為復(fù)雜,這里的“僅被消費(fèi)一次”包含如下兩種場景:

1)Message Broker上存儲(chǔ)的消息被Consumer僅消費(fèi)一次,場景要求: a)Producer發(fā)送消息到Message Broker階段:

Producer發(fā)消息給Message Broker,不要求Message Broker對(duì)接收到的消息響應(yīng)確認(rèn),Producer也不用關(guān)心Message Broker是否收到消息了。

b)Message Broker存儲(chǔ)/轉(zhuǎn)發(fā)階段:

Message Broker必須提供持久性保障,并且每條消息在其消費(fèi)隊(duì)列里有唯一標(biāo)識(shí)(這個(gè)唯一標(biāo)識(shí)可以由Producer產(chǎn)生,也可以由Message Broker產(chǎn)生)。

c)Consumer消費(fèi)階段:

Consumer從Message Broker中獲取到消息后,需要記錄下消費(fèi)的消息標(biāo)識(shí),以便在后續(xù)消費(fèi)中防止對(duì)某個(gè)消息重復(fù)消費(fèi)。比如Consumer獲取到消息,消費(fèi)完后,還沒來得及從Message Broker刪除消息,就掛了,這樣Message Broker如果把消息重新加入待消費(fèi)隊(duì)列的話,那么這條消息就會(huì)被重復(fù)消費(fèi)了。

2)Producer上產(chǎn)生的消息被Consumer僅消費(fèi)一次,場景要求: a)Producer發(fā)送消息到Message Broker階段:

Producer發(fā)消息給Message Broker,Message Broker必須響應(yīng)對(duì)消息的確認(rèn),并且Producer負(fù)責(zé)為該消息產(chǎn)生唯一標(biāo)識(shí),以防止Consumer重復(fù)消費(fèi)(因?yàn)镻roducer發(fā)消息給Message Broker后,由于網(wǎng)絡(luò)問題沒收到Message Broker的響應(yīng),可能會(huì)重發(fā)消息給到Message Broker)。

b)Message Broker存儲(chǔ)/轉(zhuǎn)發(fā)階段:

Message Broker必須提供持久性保障,并且每條消息在其消費(fèi)隊(duì)列里有唯一標(biāo)識(shí)(這個(gè)唯一標(biāo)識(shí)需要由Producer產(chǎn)生)。

c)Consumer消費(fèi)階段:

Consumer從Message Broker中獲取到消息后,需要記錄下消費(fèi)的消息標(biāo)識(shí),以便在后續(xù)消費(fèi)中防止對(duì)某個(gè)消息重復(fù)消費(fèi)。比如Consumer獲取到消息,消費(fèi)完后,還沒來得及從Message Broker刪除消息,就掛了,這樣Message Broker如果把消息重新加入待消費(fèi)隊(duì)列的話,那么這條消息就會(huì)被重復(fù)消費(fèi)了。

實(shí)踐Hello World

/// <summary>
/// 發(fā)送按鈕事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button1_Click(object sender, EventArgs e)
{
    if (!string.IsNullOrEmpty(textBox1.Text.Trim()))
    {
        try
        {
            //判斷私有隊(duì)列是否存在
            if (!MessageQueue.Exists(@".\Private$\MyPrivateQueue"))
            {
                //創(chuàng)建一個(gè)私有隊(duì)列
                MessageQueue.Create(@".\Private$\MyPrivateQueue");
            }
            //實(shí)例一個(gè)隊(duì)列
            var queue = new MessageQueue(@".\Private$\MyPrivateQueue");
            //發(fā)送消息(第一個(gè)參數(shù)為消息內(nèi)容,第二個(gè)參數(shù)為消息標(biāo)簽或名稱)
            queue.Send(textBox1.Text.Trim(), "TestLable");
        }
        catch (MessageQueueException ex)
        {
            MessageBox.Show(ex.Message, "異常消息", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}

消息隊(duì)列好處或功能

1、消息可以在斷開連接的環(huán)境下發(fā)送。不需要同時(shí)運(yùn)行正在發(fā)送和正在接收的應(yīng)用程序。

2、使用快捷模式,消息可以非??斓匕l(fā)送。在快捷模式下,消息存儲(chǔ)在內(nèi)存中。

3、對(duì)于可恢復(fù)的機(jī)制,消息可以使用有保證的交付方式發(fā)送??苫謴?fù)的消`息存儲(chǔ)在文件中。在服務(wù)器重新啟動(dòng)時(shí)發(fā)送它們。

4、用訪問控制列表來保護(hù)消息隊(duì)列,可以確定哪些用戶可以發(fā)送或接收隊(duì)列中的消息。消息還可以加密,避免網(wǎng)絡(luò)嗅探器讀取其中的數(shù)據(jù)。消息在發(fā)送時(shí)可以指定優(yōu)先級(jí),這樣可以更快地處理高優(yōu)先級(jí)的項(xiàng)。

5、Message Queuing 3.0支持多播消息的發(fā)送。

6、Message queuing 4.0支持病毒消息。病毒消息不能解析??梢远x病毒隊(duì)列中不能解析的消息是可以移動(dòng)的。例如,如果從正常的隊(duì)列中讀取消息后,對(duì)應(yīng)作業(yè)要把消息插入數(shù)據(jù)庫中,但消息不能插入數(shù)據(jù)庫,因此該作業(yè)失敗,該消息就會(huì)發(fā)送到病毒隊(duì)列中。有人負(fù)責(zé)處理病毒隊(duì)列,這個(gè)人應(yīng)以能解析病毒消息的方式來處理該消息。

7、Message Queuing 5.0支持更安全學(xué)身份驗(yàn)證算法,可以處理大量隊(duì)列(Message queuing 4.0在處理幾千個(gè)隊(duì)列時(shí)有性能問題)。

到此這篇關(guān)于Android MessageQueue消息隊(duì)列主要作用詳解的文章就介紹到這了,更多相關(guān)Android MessageQueue消息隊(duì)列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論