簡體   English   中英

Sql Server Service Broker:如何構建簡單隊列方案的對話?

[英]Sql Server Service Broker: How to structure Conversations for a simple queue scenario?

我是一個Sql Server Service Broker新手,我正在嘗試掌握為一個(看似)簡單的用例設置Service Broker的最佳方法:我想創建一個簡單的工作隊列,其中一個應用程序將工作項丟棄到隊列和單獨的應用程序從該隊列中獲取工作項並處理它們。 第一個應用程序不需要從第二個應用程序返回狀態消息。 我希望隊列存在於單個Sql Server實例中。

最令我困惑的是對話/對話與這種情況的關系。 我知道你只能在對話/對話的上下文中發送/接收消息,但由於這兩個應用程序之間沒有來回的喋喋不休,我對於何時是創建新會話的正確時間感到迷茫。 兩種極端的替代方案似乎是:

  • 每次我排隊工作項目,我都會開始一個新的對話。 因此,每個對話最終都只有一條消息。
  • 在部署時,我手動創建一個無限壽命對話。 在將工作項排入隊列時,我總是將其作為單個對話的一部分發送。

走這些路線的后果是什么?

此外,在第一種情況下,似乎我需要進行一些END CONVERSATION,以便Sql Server能夠在內部清理資源。 什么時候將它們放入正確的地方是否有任何指導? (或者最終依靠對話超時可能會更好?)

您應該從每個工作項開始進行自己的對話。 生產者(發起者)開始一個對話框並發送描述工作項的消息,然后提交。 使用者(目標)接收消息(或被激活),檢查有效負載以了解工作項詳細信息,執行工作,然后結束對話並提交。 生成的EndDialog消息將被發送回啟動器服務隊列,並且啟動器隊列上的激活過程通過在發起方端結束對話來響應它。

這是最簡單的部署,啟動和運行將確保您有一個良好的基礎來構建。 當生產者將工作項排入隊列時,不要偷工減料並結束發起人一側的對話,這是一次又一次的冒險並且有幾個缺點

如果您有高性能要求(每秒超過200個請求),那么您將不得不更明確地開始管理對話。 出於性能原因,我有一篇關於重用會話的博客文章。 在接收方面,我建議閱讀寫作服務經紀人程序

我還有一個博客條目,幾乎可以滿足您的需求,雖然它不會安排工作項,而是啟動自定義過程: 異步過程執行

如果您決定從激活的上下文中使用工作項,從而利用激活的良好自平衡功能,那么您需要了解發生激活的EXECUTE AS上下文

我真的很喜歡Remus的回答,盡管它並沒有特別說明為什么你可能更喜歡為每個工作項啟動一個單獨的對話,而不是將所有工作項放在一個對話中。 與此相關的兩個注釋:

首先,如果您有多個線程/進程處理工作項,將所有工作項放入單個對話可能會導致並發問題。 服務代理工作進程往往看起來像這樣(偽代碼):

begin transaction
receive top n work items from queue
process work items
commit transaction

(通過不提交直到工作項成功處理為止,例如,您確保如果您的流程終止,那么它已收到但尚未處理的工作項將不會從隊列中刪除。)

並發問題將出現,因為服務代理被編程為使得每個RECEIVE命令獲取隊列中與RECEIVEd共享相同會話(或會話組)的所有消息的獨占讀鎖定。 該鎖定一直持續到事務提交為止。 (請參閱對話組鎖定 。)因此,如果隊列中的所有工作項都在一個對話中,那么當一個工作進程處於“進程工作項”步驟中時,沒有其他工作進程可以執行任何工作。

將大量項目放入單個對話的第二個問題是,它會增加您可能丟失或必須在某些錯誤條件下重新處理的工作項數量。 為了正確描述這一點,我推遲到Remus; 看看他的回收對話 ,特別是“重復使用單個對話框發送所有信息的部分[...]就像將所有雞蛋放在一個籃子里一樣。” 您可能能夠從某些錯誤情況中恢復,但它可能會為您的代碼帶來更多復雜性。

對於所有工作項使用單個對話可能還有一些爭論,但我對它們並不熟悉。

這並不是說正確的解決方案始終是為每個工作項啟動單獨的對話。 在閱讀了Remus的帖子之后,他的建議似乎很合理; 從每個對話開始一個工作項,然后根據需要添加復雜性。 (但在任何情況下,您都不應該將所有消息放在一個對話中。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM