(十六)——優(yōu)先級隊(duì)列模式

2018-02-24 15:44 更新

云計(jì)算設(shè)計(jì)模式(十六)——優(yōu)先級隊(duì)列模式

優(yōu)先發(fā)送到服務(wù),以便具有較高優(yōu)先級的請求被接收和高于一個較低優(yōu)先級的更快速地處理請求。這種模式是在應(yīng)用程序是有用的,它提供不同的服務(wù)級別保證或者針對獨(dú)立客戶。

背景和問題

應(yīng)用程序可以委托給其他服務(wù)的具體任務(wù);例如,為了執(zhí)行后臺處理或與其他應(yīng)用程序或服務(wù)的整合。在云中,消息隊(duì)列通常用于將任務(wù)委派給后臺處理。在許多情況下,請求由服務(wù)接收的順序是不重要的。然而,在某些情況下,可能需要優(yōu)先考慮的具體要求。這些要求必須早于較低優(yōu)先級的其他可能先前已發(fā)送由應(yīng)用程序進(jìn)行處理。

解決方案

隊(duì)列通常是先入先出(FIFO)結(jié)構(gòu),而消費(fèi)者通常會收到他們發(fā)布到隊(duì)列中的順序相同的消息。然而,一些消息隊(duì)列支持優(yōu)先級的消息傳遞;應(yīng)用程序發(fā)布一條消息可以分配優(yōu)先級的消息,并在隊(duì)列中的消息會自動重新排序,使得具有較高優(yōu)先級的消息將這些優(yōu)先級較低的前被接收。圖1示出了一個隊(duì)列,它提供優(yōu)先權(quán)的消息。

圖1 - 使用支持消息優(yōu)先級排隊(duì)機(jī)制

注意: 大多數(shù)消息隊(duì)列的實(shí)現(xiàn)支持多個消費(fèi)者(以下的競爭消費(fèi)者模式)和消費(fèi)過程的數(shù)量可以按比例增加或減小的需求支配。

在不支持基于優(yōu)先級的消息隊(duì)列系統(tǒng)中,一種替代的解決方案是為每一個優(yōu)先級的獨(dú)立隊(duì)列。該應(yīng)用程序負(fù)責(zé)將郵件投遞到適當(dāng)?shù)年?duì)列。每個隊(duì)列可以有一個單獨(dú)的消費(fèi)者池。高優(yōu)先級隊(duì)列可以有更快的硬件比低優(yōu)先級隊(duì)列中運(yùn)行的消費(fèi)者一個更大的泳池。圖2示出了這種方法。

圖2 - 使用不同的消息隊(duì)列為每個優(yōu)先級

這種策略的變化是有消費(fèi)者認(rèn)為檢查對高優(yōu)先級隊(duì)列中的消息,然后再才開始從低優(yōu)先級隊(duì)列中讀取消息,如果沒有更高優(yōu)先級的消息都在等待的一個池。還有,使用消費(fèi)過程的一個池的溶液之間的一些語義差異(或者使用支持不同的優(yōu)先級或多個隊(duì)列,每個處理一個單一的優(yōu)先級消息的消息的單個隊(duì)列),以及使用多個隊(duì)列用溶液為每個隊(duì)列一個單獨(dú)的游泳池。

在單池的做法,高優(yōu)先級的消息總是會收到以前低優(yōu)先級的消息處理。在理論中,具有非常低的優(yōu)先級的消息可以被不斷地取代,并且可能永遠(yuǎn)不會被處理。在多池的方法,較低優(yōu)先級的報(bào)文將總是被處理,只是不一樣迅速的那些更高的優(yōu)先級的(取決于池和它們具有可用資源的相對大?。?/p>

使用優(yōu)先級排隊(duì)機(jī)制可提供以下優(yōu)點(diǎn):

  • 它允許應(yīng)用程序以滿足必要的可用性或性能優(yōu)先的業(yè)務(wù)需求,如提供不同級別的服務(wù),以客戶的特定群體。
  • 它可以幫助最大限度地降低運(yùn)營成本。在單隊(duì)列的方式,你可以縮減用戶的數(shù)量,如果有必要的。高優(yōu)先級消息仍將被首先處理(雖然可能更慢),和低優(yōu)先級的消息可能會延遲更長。如果您已實(shí)現(xiàn)與消費(fèi)者的每一個單獨(dú)的隊(duì)列池多個消息隊(duì)列的方式,可以減少消費(fèi)者的池低優(yōu)先級隊(duì)列,或者甚至停止所有監(jiān)聽的訊息的消費(fèi)者暫停處理一些非常低優(yōu)先級隊(duì)列這些隊(duì)列。
  • 在多個消息隊(duì)列的方法可以幫助劃分的基礎(chǔ)上處理要求的消息,以最大限度地提高應(yīng)用程序的性能和可擴(kuò)展性。例如,重要的任務(wù),可以優(yōu)先被立即運(yùn)行,而不太重要的后臺任務(wù)可以被安排在不太繁忙的時段運(yùn)行的接收器來處理接收處理。

問題和注意事項(xiàng)

在決定如何實(shí)現(xiàn)這個模式時,請考慮以下幾點(diǎn):

  • 定義優(yōu)先級的解決方案的情況下。例如,“高優(yōu)先級”可能意味著,信息應(yīng)該在十秒內(nèi)進(jìn)行處理。標(biāo)識要求處理高優(yōu)先級的項(xiàng)目,以及其他什么資源必須分配給符合這些標(biāo)準(zhǔn)。
  • 確定是否所有高優(yōu)先級的項(xiàng)目必須在任何優(yōu)先級較低的項(xiàng)目之前進(jìn)行處理。如果該消息是由消費(fèi)者的一個池被處理,可能有必要提供一種可搶先和暫停正在處理的低優(yōu)先級消息,如果更高優(yōu)先級的消息,有一個任務(wù)的機(jī)制。
  • 在多個隊(duì)列中的方法,使用該監(jiān)聽所有的隊(duì)列,而不是一個專門的客戶池的每個隊(duì)列的消費(fèi)過程的一個池時,消費(fèi)者必須應(yīng)用一種算法,以確保它總是從那些從低之前較高優(yōu)先級的隊(duì)列提供服務(wù)的消息優(yōu)先級隊(duì)列。
  • 監(jiān)視處理的高和低優(yōu)先級隊(duì)列中的速度,以確保在這些隊(duì)列中的消息的預(yù)期的速率進(jìn)行處理。
  • 如果需要,以保證低優(yōu)先級的消息將被處理時,可能有必要實(shí)現(xiàn)與消費(fèi)者的多個池的多個消息隊(duì)列的方法?;蛘?,在一個支持消息優(yōu)先隊(duì)列,它可能會動態(tài)地增加一個排隊(duì)的消息的優(yōu)先級,因?yàn)樗哪挲g。然而,該方法依賴于消息隊(duì)列提供此功能。
  • 使用單獨(dú)的隊(duì)列中每個消息優(yōu)先級最適合有少數(shù)明確定義的優(yōu)先級系統(tǒng)。
  • 消息優(yōu)先級可以通過系統(tǒng)邏輯決定的。例如,而不是明確的高和低優(yōu)先級的消息,他們可以被指定為“自費(fèi)客戶”,或“非自費(fèi)的客戶?!备鶕?jù)您的商業(yè)模式,你的系統(tǒng)可能會分配更多的資源,從收費(fèi)處理消息付費(fèi)用戶比非自費(fèi)的。
  • 有可能是檢查隊(duì)列的消息相關(guān)聯(lián)的金融和處理成本(一些商業(yè)郵件系統(tǒng)的消息被發(fā)布或檢索每次收取一小筆費(fèi)用,每次一個隊(duì)列中查詢消息)。檢查多個隊(duì)列時,該成本將有所增加。
  • 它可以是能夠動態(tài)調(diào)整的基礎(chǔ)上,該池所服務(wù)的隊(duì)列的長度消費(fèi)者的一個池的大小。欲了解更多信息,請參閱自動縮放指導(dǎo)。

何時使用這個模式

這種模式非常適合場景:

  • 系統(tǒng)必須處理可能有不同的側(cè)重點(diǎn)多個任務(wù)。
  • 不同的用戶或租戶應(yīng)配以不同的優(yōu)先級。

例子

微軟 Azure 不提供經(jīng)過整理的本地支持郵件自動優(yōu)先級排隊(duì)機(jī)制。然而,它確實(shí)提供了 Azure 的服務(wù)總線主題和訂閱,支持排隊(duì)機(jī)制,提供郵件過濾,具有多種靈活的功能,使其非常適合用在幾乎所有的優(yōu)先級隊(duì)列的實(shí)現(xiàn)在一起。

一個 Azure 的解決方案,可以實(shí)現(xiàn)服務(wù)總線話題,其中一個應(yīng)用程序可以發(fā)布消息,以同樣的方式作為一個隊(duì)列。消息可以包含在應(yīng)用程序定義的自定義屬性的形式的元數(shù)據(jù)。服務(wù)總線訂閱可以與主題相關(guān)聯(lián),并且這些訂閱可以篩選根據(jù)它們的屬性信息。當(dāng)一個應(yīng)用程序?qū)⑾l(fā)送到一個主題,該消息被定向到從那里它可以被消費(fèi)者閱讀相應(yīng)的訂閱。消費(fèi)者的過程可以檢索使用相同的語義消息隊(duì)列(訂閱是一個邏輯隊(duì)列)從一個訂閱消息。

圖 3 示出了使用的 Azure 服務(wù)總線主題和訂閱的解決方案

圖3 - 實(shí)現(xiàn)與 Azure 的服務(wù)總線主題和訂閱優(yōu)先級隊(duì)列

在圖3中的應(yīng)用程序創(chuàng)建多個消息和每個消息與價值分配被稱為優(yōu)先級的自定義屬性,無論是高還是低。該應(yīng)用程序的帖子,這些消息的一個話題。這個主題有兩個相關(guān)的訂閱,這兩個濾波器的消息通過檢查優(yōu)先級屬性。一位接受認(rèn)購,其中優(yōu)先級屬性設(shè)置為高的消息,而其他接受其中優(yōu)先級屬性設(shè)置為低的消息。消費(fèi)者池讀取每個訂閱的消息。高優(yōu)先認(rèn)購有較大的游泳池,而這些消費(fèi)者可能會更強(qiáng)大(且昂貴)的計(jì)算機(jī)上運(yùn)行有提供比消費(fèi)者在低優(yōu)先級池的更多資源。

請注意,沒有什么特別的高,低優(yōu)先級消息在這個例子中指定。這些僅僅是指定為每個消息中的屬性的標(biāo)簽,并用于引導(dǎo)消息發(fā)送到一個特定的訂閱。如果附加的優(yōu)先級是必需的,它是比較容易地創(chuàng)建進(jìn)一步的訂閱和消費(fèi)者進(jìn)程池來處理這些優(yōu)先級。

在可用于此引導(dǎo)代碼時 Queue 解決方案包含這種方法的一個實(shí)現(xiàn)。該解決方案包含一個名為 PriorityQueue.High 和 PriorityQueue.Low 兩個工作角色的項(xiàng)目。這兩個輔助角色繼承的類被稱為 PriorityWorkerRole 它包含用于連接到一個指定的預(yù)訂中 OnStart 方法的功能。

該 PriorityQueue.High 和 PriorityQueue.Low 輔助角色連接到不同的預(yù)訂,他們的配置設(shè)置來定義。管理員可以配置每個角色的不同數(shù)量要運(yùn)行;通常會有比 PriorityQueue.Low 工作者角色的 PriorityQueue.High 輔助角色更多的實(shí)例。

在 PriorityWorkerRole 類的 Run 方法安排虛擬 ProcessMessage 的方法(在 PriorityWorkerRole 類定義)的隊(duì)列中接收到的每個消息被執(zhí)行。下面的代碼顯示了運(yùn)行和 ProcessMessage 的方法。在類的 QueueManager,在 PriorityQueue.Shared 項(xiàng)目定義,提供了輔助方法使用的 Azure 服務(wù)總線隊(duì)列。

public class PriorityWorkerRole : RoleEntryPoint  
{  
  private QueueManager queueManager;  
  ...  
?
  public override void Run()  
  {  
    // Start listening for messages on the subscription.  
    var subscriptionName = CloudConfigurationManager.GetSetting("SubscriptionName");  
    this.queueManager.ReceiveMessages(subscriptionName, this.ProcessMessage);  
    ...;  
  }  
  ...  
?
  protected virtual async Task ProcessMessage(BrokeredMessage message)  
  {  
    // Simulating processing.  
    await Task.Delay(TimeSpan.FromSeconds(2));  
  }  
}

該 PriorityQueue.High 和 PriorityQueue.Low 輔助角色既覆蓋 ProcessMessage 的方法的默認(rèn)功能。下面的代碼顯示了 ProcessMessage 的方法為 PriorityQueue.High 輔助角色。

Copy  
?
?
protected override async Task ProcessMessage(BrokeredMessage message)  
{  
  // Simulate message processing for High priority messages.  
  await base.ProcessMessage(message);  
  Trace.TraceInformation("High priority message processed by " +  
    RoleEnvironment.CurrentRoleInstance.Id + " MessageId: " + message.MessageId);  
}

當(dāng)一個應(yīng)用程序?qū)⑾l(fā)布到與所使用的 PriorityQueue.High 和 PriorityQueue.Low 輔助角色的訂閱相關(guān)聯(lián)的主題,它指定了優(yōu)先使用優(yōu)先級的自定義屬性,如在下面的代碼示例。此代碼(這是在 PriorityQueue.Sender項(xiàng)目 WorkerRole 類實(shí)現(xiàn)),使用的 QueueManager 類的 SendBatchAsync 輔助方法發(fā)帖分批的話題。

// Send a low priority batch.   
var lowMessages = new List<BrokeredMessage>();  
?
for (int i = 0; i < 10; i++)  
{  
  var message = new BrokeredMessage() { MessageId = Guid.NewGuid().ToString() };  
  message.Properties["Priority"] = Priority.Low;  
  lowMessages.Add(message);  
}  
?
this.queueManager.SendBatchAsync(lowMessages).Wait();  
...  
?
// Send a high priority batch.  
var highMessages = new List<BrokeredMessage>();  
?
for (int i = 0; i < 10; i++)  
{  
  var message = new BrokeredMessage() { MessageId = Guid.NewGuid().ToString() };  
  message.Properties["Priority"] = Priority.High;  
  highMessages.Add(message);  
}  
?
this.queueManager.SendBatchAsync(highMessages).Wait();
以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號