Service Broker 應用程式大綱
大部分的 Service Broker 應用程式會遵循相同的基本步驟來接收和處理訊息:
應用程式開始交易。
如果應用程式維持狀態,應用程式會取得交談群組識別碼。應用程式會使用此識別碼從狀態資料表還原狀態。如果交談群組沒有準備接收的訊息,應用程式會回復交易並結束。
應用程式會從佇列接收一個或多個訊息。如果應用程式具有交談群組識別碼,應用程式會使用交談群組識別碼,來為該交談群組接收訊息。如果沒有任何訊息可供接收,應用程式會認可交易並傳回至步驟 1。
應用程式會根據訊息類型名稱驗證訊息內容。
應用程式會根據訊息類型名稱和訊息內容來處理訊息。
應用程式會傳送因為處理所產生的任何訊息。
如果應用程式維持狀態,應用程式會更新狀態資料表,使用交談群組識別碼做為資料表的主要索引鍵。
應用程式會傳回步驟 3,以檢查是否有更多的訊息可使用。
應用程式的精確結構取決於應用程式的需求、應用程式的通訊樣式、應用程式是目標服務或起始服務,Service Broker 是否啟動應用程式。
例如,起始應用程式會在開始上一個步驟所述的處理迴圈之前,先傳送訊息。起始服務可能會從另一個程式或是預存程序傳送訊息,然後為起始服務佇列使用啟動預存程序。例如,訂單輸入應用程式可以包括外部應用程式,以起始交談來輸入訂單。在輸入訂單之後,外部應用程式不需要繼續執行。當回應從訂單服務傳回時,起始服務的啟動預存程序會傳送訂單通訊。啟動預存程序也會處理任何由目標服務傳回的 Service Broker 錯誤訊息,並傳送無法確認的訂單之通知。
或者,起始應用程式與其從不同的程式傳送訊息,還不如傳送訊息,然後啟動處理迴圈做為相同程式的一部分。不論這些變化為何,基本的大綱仍然保持相同。
在相同的交談群組中處理大量訊息的應用程式,可能會保留接收的訊息計數,並在處理某些數目的訊息之後認可交易。這個計數和認可策略允許應用程式保持相當短暫的交易,並讓應用程式處理不同的交談群組。
範例
下列 Transact-SQL 範例會處理佇列 MyServiceQueue 上的所有訊息。會以最簡單的方式處理訊息。如果訊息是 EndDialog 或 Error 訊息,程式碼會結束交談。對於任何其他訊息,程式碼會建立訊息的 XML 表示,並且會產生包含交談處理常式、訊息類型名稱和 XML 的結果集。當有 500 毫秒沒有訊息可以使用時,程式碼會結束。
基於簡單原則,指令碼會為每個訊息產生結果集。如果在從佇列讀取時發生錯誤,指令碼會認可變更,而不會產生任何結果。因此,此指令碼將會以無訊息的方式移除任何造成錯誤的訊息。
[!附註]
因為指令碼只會顯示訊息,所以此指令碼不可能會有有害訊息。因此,指令碼並不會包含處理有害訊息的程式碼。應該撰寫生產應用程式以處理有害訊息。如需有關有害訊息的詳細資訊,請參閱<處理有害訊息>。
USE AdventureWorks ;
GO
-- Process all conversation groups.
WHILE (1 = 1)
BEGIN
DECLARE @conversation_handle UNIQUEIDENTIFIER,
@conversation_group_id UNIQUEIDENTIFIER,
@message_body XML,
@message_type_name NVARCHAR(128);
-- Begin a transaction, one per conversation group.
BEGIN TRANSACTION ;
-- Get next conversation group.
WAITFOR(
GET CONVERSATION GROUP @conversation_group_id FROM MyServiceQueue),
TIMEOUT 500 ;
-- Restore the state for this conversation group here
-- If there are no more conversation groups, break.
IF @conversation_group_id IS NULL
BEGIN
ROLLBACK TRANSACTION ;
BREAK ;
END ;
-- Process all messages in the conversation group.
WHILE 1 = 1
BEGIN
-- Get the next message.
RECEIVE
TOP(1)
@conversation_handle = conversation_handle,
@message_type_name = message_type_name,
@message_body =
CASE
WHEN validation = 'X' THEN CAST(message_body AS XML)
ELSE CAST(N'<none/>' AS XML)
END
FROM MyServiceQueue
WHERE conversation_group_id = @conversation_group_id;
-- If there is no message, or there is an error
-- reading from the queue, break.
IF @@ROWCOUNT = 0 OR @@ERROR <> 0
BREAK;
-- Process the message. In this case, the program ends the conversation
-- for Error and EndDialog messages. For all other messages, the program
-- produces a result set with information about the message.
SELECT @conversation_handle,
@message_type_name,
@message_body ;
-- If the message is an end dialog message or an error,
-- end the conversation. Notice that other conversations
-- in the same conversation group may still have messages
-- to process. Therefore, the program does not break after
-- ending the conversation.
IF @message_type_name =
'https://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
OR @message_type_name =
'https://schemas.microsoft.com/SQL/ServiceBroker/Error'
BEGIN
END CONVERSATION @conversation_handle ;
END ;
END ; -- Process all messages in conversation group.
COMMIT TRANSACTION ;
END ; -- Process all conversation groups.