2009-08-12 25 views
15

我是一個Sql Server服務代理新手,我試着去設置Service Broker(看似)簡單用例的最佳方法:我想創建一個簡單的工作隊列,其中一個應用程序放棄工作項目進入隊列,並且單獨的應用程序從該隊列中提取工作項並對其進行處理。第一個應用程序不需要從第二個應用程序獲取狀態消息。我希望隊列能夠存在於單個Sql Server實例中。Sql Server Service Broker:如何構造簡單隊列場景的對話?

讓我最困惑的是對話/對話與這種情況的關係。我知道你只能在對話/對話的上下文中發送/接收消息,但由於兩個應用程序之間沒有來回的交談,所以我失去了創建新對話的正確時間。兩種極端的選擇似乎是:

  • 每次我排隊工作項目,我開始一個新的談話。所以每個對話最終都只有一條消息。
  • 在部署時,我手動創建一個無限生命期對話。當需要排隊工作項目時,我總是將它作爲單個對話的一部分發送出去。

什麼將要去這兩種路線的後果是什麼?

此外,在第一種情況下,好像我需要做一些結束對話,以便爲SQL Server能夠在內部清理資源。有什麼指導什麼時候將這些放在正確的位置? (也可能是潛在更好地依靠對話最終超時?)

+0

您似乎在討論單個隊列,但是... http://stackoverflow.com/questions/14643015/why-do-i-need-two-sql-server-service-broker-queues-for-a-simple-task – cja 2013-02-01 09:19:26

回答

26

你應該對自己的談話每個工作項目啓動。生產者(發起者)開始對話併發送描述工作項目的消息,然後提交。消費者(目標)接收消息(或被激活),檢查有效負載以瞭解工作項目詳細信息,執行工作,然後結束對話並提交。得到的EndDialog消息被髮送回發起者服務隊列,並且發起者隊列上的激活過程通過結束髮起者側的對話來響應它。

這是最簡單的部署,啓動和運行將確保您擁有堅實的基礎。從生產者入列工作項目開始,不要偷工減料並結束對話,這是fire-and-forget and has several draw backs

如果你有很高的性能要求(超過每秒200個請求),那麼你就必須開始更明確地管理對話。我有一個關於reusing conversations for performance reasons的博客條目。在接收方,我建議閱讀Writing Service Broker Procedures

我也有一個博客條目,幾乎不需要你做什麼,儘管它不安排工作項目,而是啓動一個自定義程序:Asynchronous procedure execution

如果您決定從激活的上下文中消耗工作項目,從而利用激活的良好自我平衡功能,那麼您需要understand the EXECUTE AS context under which activation occurs

+0

重複使用對話的另一個好處是避免了「Microsoft Internal Work Request 642585」中描述的問題(不公開)。也就是說,您創建和銷燬的每個對話都會泄漏TempDB中的少量分配空間,直到您退回實例纔會釋放這些空間。在高吞吐量的應用程序中,這會浪費TempDB的大小,並迫使您重新啓動實例以再次縮小它。 – 2011-10-28 18:28:36

+0

與每條消息使用單獨對話的一個問題是,對話可能會在另一端出現亂序。如果在接收端只有一個線程,則甚至會發生這種情況。記住Service Broker只保證會話內的序列。對話的全部原因是在隊列的接收端有多個線程時管理排序。如果會話保持順序以及消息,它將禁止使用多個接收線程。 – 2011-12-09 12:55:54

9

我真的很喜歡Remus的答案,儘管它沒有特別的觸摸爲什麼您可能希望開始每個工作項目的單獨談話,而不是將所有工作項目在一個單一的談話。與此相關的有兩點需要注意:

首先,將所有工作項目到一個會話可能會導致併發的問題,如果你有多個線程/進程處理的工作項目。服務代理工作進程往往是這樣的(僞代碼):

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

(如果不承諾,直到工作項目成功處理,可以確保,例如,如果你的進程死掉了,然後工作項目,已收到但尚未處理的數據不會從隊列中丟失。)

併發問題會出現,因爲服務代理被編程爲使得每個RECEIVE命令都獲得隊列中共享相同對話的所有消息的獨佔讀鎖定(或談話小組)作爲被接受者。該鎖一直持續到事務提交。 (見Conversation Group Locks。)所以,如果隊列中的所有工作項目都在一個單一的談話,然後在一個工作進程中的「過程的工作項目」的步驟,沒有其他工作進程可以做任何工作。

與投入大量的項目到一個會話的第二個問題是,它增加了你可能會失去,或者在某些錯誤情況下重新處理工作項目的數量。爲了恰當地描述這一點,我遵從Remus;請參閱他的Recycling Conversations,尤其是「重複使用單個對話框發送所有消息[...]」的部分就像將所有雞蛋放在一個籃子中一樣。「您可能能夠從這些錯誤情況中恢復,但它可能會給代碼帶來更多複雜性。

有要對使用的所有工作項目單個對話可能做出一些更多的爭論,但我不熟悉他們。

這並不是說正確的解決方案總是開始單獨談話的每一個工作項目。雖然讀過Remus的帖子,但他的建議聽起來很合理;從每個對話中的一個工作項開始,然後根據需要添加複雜性。 (但是,在任何情況下,您都不應該將所有消息放在一個對話中。)

相關問題