Sql-Server

您將如何為 Service Broker 隊列的多個使用者實施對話組/鎖定?

  • May 24, 2012

您如何使用他們自己的使用者應用程序實例為多個使用者實施對話組,但將相關消息發送到服務代理隊列?這種實現有什麼好的例子嗎?原以為可以自己設置對話組ID,保證各個使用者的某組消息是相關的,但是好像這個值會自動生成為UNIQUEIDENTIFIERS…這還是最好的辦法嗎去做吧?

我想確保擷取並鎖定相關消息,例如“同一團隊”的兩個使用者一起競標同一個項目,以便伺服器應用程序邏輯可以一起正確處理這些相關消息(基本上只有第一個將被接受,而第二個將被拒絕,直到使用者的視圖可以更新,以便他們知道另一個使用者已經更改了出價)。

流向是從使用者 A、B、C 向隊列發送 xml 消息,然後是出隊服務,該服務將 xml 發送到外部 Web 服務。我們發送的消息是結構化的 xml 消息,這些消息將在出隊後修改外部 Web 服務上不同項目的訂單。

謝謝!

如果您正在嘗試這樣做,您不能使用對話組來排除應用程序實例。如果 Instance A 只需要為 Instance A 接收來自隊列的消息,而 Instance B 只需要為 Instance B 接收消息,那麼instance A 需要使用 queue A 而 instance B 需要使用 queue B。僅當實例 A 和實例 B 都可以處理任何消息,但您希望將它們排除在並發處理相關消息之外時,才可以使用會話組。每次我看到有人試圖預先生成對話組 ID,這個想法總是很糟糕。

更新

發起者無法控制目的地(目標)的會話組。即使 A 和 B 在發起者站點的同一個會話組中,這並不意味著它們在目標站點上是相同的,因為會話組是一個本地概念並且不會隨消息一起傳播。如果您希望 A 和 B 發送的消息屬於目標端的同一對話組,則必須以“相反”的順序開始對話:目標開始對話並將它們放在一個對話組,然後目標開始在此對話上發送消息。因此,對話就像發送消息的“邀請”,邏輯“目標”充當實際的“發起者”。

更新#2。

從理論上講,這就是它的工作原理:假設您有 10000 種產品。要執行“反向”模式,當使用者想要參與應用程序時,它需要“加入”。因此他開始與伺服器進行對話並發送消息“我想加入”(稱為“對話 0” ‘)。伺服器通過與每個產品的新使用者開始對話來處理此消息. 現在使用者有 10000 個對話,它可以發送“出價”。對於產品 A,它使用會話 1,對於產品 B 會話 2 等。當使用者 B 想要加入時,它也會開始與伺服器的新會話並發送“我想加入”消息。伺服器通過與該新使用者開始 10000 次對話來響應,每個產品再次對話一次,並確保每個人都在產品的相應組中,因此產品 A 與使用者 1 的對話與產品對話在同一組中a 用於使用者 2。

現在顯然任何人都會認為這個方案是有缺陷的:它需要 number_of_products X number_of_user 對話,它使添加和刪除產品變得很痛苦(必須維護所有這些使用者對話!)等等。一種替代方法是每次對話多路復用產品。假設伺服器只與每個使用者開始 10 次對話,並且使用者使用與產品 id 的最後一位數字對應的對話(因此產品 1 進入對話 1,但產品 11 或 101 也是如此)。這是更可行的,它需要更少的對話,並且在添加或刪除產品時不需要特殊的對話管理。您可能會認為這是一個缺點,因為現在伺服器鎖定的不是產品 1 的所有消息,而是產品 11 的所有消息、所有 101 等的消息,但請考慮這一點:只有當您有伺服器上的處理執行緒數超過每個使用者的會話數。如果您有 5 個執行緒,那麼鎖定 1、11、101 無關緊要,其他 4 個執行緒仍有消息要處理。僅當您有 11 個執行緒時才重要,因為第 11 個執行緒沒有要處理的內容。

現在我不提倡完全部署這個,我只是指出一些可能性。在大多數情況下,CG 鎖定將針對每個使用者,而不是每個產品,並且添加使用 CG 鎖定以避免每個產品上的並發問題的額外維度有點不正統。

並且不要忘記,在 SSB 中保證順序的唯一構造是對話。因此,如果使用者必須在會話 1 上發送對 A 的出價,然後在會話 2 上發送對 B 的出價,則不能保證在處理B 的出價會處理對 A的出價。唯一的保證是,如果使用者 1 為 A 發送了兩次出價,它們將按照發送的順序進行處理。

此外,如果兩個不同的使用者為產品 A 發送投標,則無法保證這些投標的處理順序。但是,如果產品 A 的投標最終出現在相同的 CG 上,則可以保證只有一個“處理器執行緒”會同時看到使用者 1 的投標和使用者 2 的投標,但要小心,因為不能保証投標在 RECEIVE 結果集中按照它們被接收的順序呈現。RECEIVE 僅保證:

  • 結果集中的所有消息都來自同一個CG
  • 屬於對話的消息是有序的

結果中的對話順序基本上是隨機的(由對話句柄順序驅動,一個 GUID)。

在我忘記之前:請記住,還存在MOVE CONVERSATION但依賴 MOVE(而不是直接在正確的 CG 中開始對話)非常容易陷入僵局。

引用自:https://dba.stackexchange.com/questions/18355