與多路復用服務代理訂單隊列中的一個目標隊列通信的多個服務使用相同的會話句柄是否有任何問題?
我問了一個關於在 SQL Service Broker 設置中實現對話組的問題,該設置有幾個使用者服務與伺服器服務通信(處理要發送到外部 Web 服務的 xml 數據請求)。但是由於會話組不保證處理中的順序,您是否認為對所有進入同一目標隊列的請求使用相同的會話句柄有什麼問題(保證無論來源如何發送它們的順序) ?
背景: 您將如何為 Service Broker 隊列的多個使用者實現對話組/鎖定?
正如Rusanu在回答中提到的那樣,
並且不要忘記,在 SSB 中保證順序的唯一構造是對話。因此,如果使用者必須在會話 1 上發送對 A 的出價,然後在會話 2 上發送對 B 的出價,則不能保證在處理 B 的出價後會處理對 A 的出價。唯一的保證是,如果使用者 1 為 A 發送了兩次出價,它們將按照發送的順序進行處理。
此外,如果兩個不同的使用者為產品 A 發送投標,則無法保證這些投標的處理順序。但是,如果產品 A 的投標最終出現在相同的 CG 上,則可以保證只有一個“處理器執行緒”會同時看到使用者 1 的投標和使用者 2 的投標,但要小心,因為不能保証投標在 RECEIVE 結果集中按照它們被接收的順序呈現。RECEIVE 僅保證:
* all messages in the result set are from the same CG * the messages belonging to a conversation are in order
但結果中的對話順序基本上是隨機的(由對話句柄順序驅動,一個 GUID)。
就像在真正的拍賣中一樣,我實際上希望隊列項目按照它們到達隊列的順序進行處理,使用者 A、使用者 B 和使用者 C 發送相同產品的“投標”。我正在考慮通過對同一產品上的所有對話使用相同的對話句柄來實現整個事情。
到目前為止我想我會嘗試什麼:
該機制將是伺服器應用程序將 N 個對話的對話啟動器(初始化)發送到 User_0(其中 N 是我們將擁有的“多路復用對話通道”的數量)——我們將對話句柄儲存在類似這樣的表中:
CREATE TABLE ConversationChannelStatus (ConversationChannel_pk numeric Primary Key, ConversationHandle UNIQUEIDENTIFIER)
USER_A 在發送“投標”時,將使用保存在 ConversationChannelStatus 表中的會話句柄從 User_A 服務向目標服務發送消息(由簡單的數字主鍵“ConversationChannels”索引)。
將會話句柄儲存在表中是否有問題,然後讓多個啟動器服務在向目標隊列發送消息時繼續使用相同的會話句柄?
謝謝你。
更新:抱歉對這些詞感到困惑,對話 ID,對話句柄。絕對不能使用相同的會話句柄,因為它對於發起者和目標是不同的。我想我指的是嘗試使用來自多個發起者的相同對話 ID 到同一個目標,以嘗試維護來自多個服務的隊列處理消息的順序。
更新 2:仍在努力,但我想解決方案將是這樣的,涉及對話句柄和對話組 ID。
- 首先初始化 N 個對話與使用者 0,並將對話組 ID 和對話句柄都儲存在頻道設置表中。
- 當 UserA、UserB、UserC 服務想要加入時,伺服器應用程序實際上會使用我們之前儲存在頻道設置表中的對話句柄與每個使用者服務發起 N 次對話。
- 然後,使用者服務(該消息的目標)將接收該消息並使用頻道設置表中的會話組 ID 進行回复,僅當使用者服務有“出價”要發送時。從而為使用者服務提供了一種簡單的方法來知道要使用哪個相關的會話組 ID,同時在伺服器上保持所需的會話順序APP服務隊列處理來自使用者 A、B、C 的消息(因為它正在回復由serverapp 服務)。我希望它有效!
競爭將是最大的問題。會話保證順序,但為了提供這種保證,SEND 動詞必須鎖定使用的會話句柄,直到事務結束(或者如果沒有使用顯式事務,則在語句期間)。實際上,這意味著在任何時候只有一個交易可以發送對產品 A 的出價。這是否可以接受完全取決於您的業務需求。
術語:對話有兩個端點,發起者和目標。每個對話都有一個唯一的 ID,即
conversation_id
(a guid),它在兩個端點上具有相同的值(即,它與消息一起線上路上傳播)。每個端點都有自己的句柄,即conversation_handle
與 SSB 動詞一起使用的(又是一個 guid)。句柄僅是本地的,並且永遠不會與消息一起傳播。所以你在更新中做對了;)我認為您在更新 2 中描述的內容還可以,但魔鬼總是在細節中。我建議你開始嘗試原型程式碼並交換真實的消息,一旦你看到它工作,你會得到更好的感覺。