我們通過表上的觸發器將消息放入SQL Server消息隊列中。 (當一個字段被更新時,我們建立一些XML,並在下面調用觸發器)。SQL Message Broker在發送隊列中留下消息
CREATE PROCEDURE [dbo].[up_CarePay_BrokerSendXml]
-- Add the parameters for the stored procedure here
@Data VARCHAR(MAX)
AS
BEGIN
DECLARE @InitDlgHandle UNIQUEIDENTIFIER
DECLARE @RequestMessage VARCHAR(1000)
BEGIN TRY
BEGIN TRAN
BEGIN DIALOG CONVERSATION @InitDlgHandle
FROM SERVICE [//IcmsCarePay/Service/Initiator]
TO SERVICE N'//IcmsCarePay/Service/Target'
ON CONTRACT [//IcmsCarePay/Contract]
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION @InitDlgHandle
MESSAGE TYPE [//IcmsCarePay/Message/Request] (@Data);
COMMIT TRAN;
END TRY
BEGIN CATCH
ROLLBACK TRAN;
DECLARE @Message VARCHAR(MAX);
SELECT @Message = ERROR_MESSAGE();
PRINT @Message
END CATCH;
END
This works。消息放入隊列中。
然後將消息發送到同一服務器上的接收隊列 - 不同的數據庫。然後,我們每分鐘運行一次proc,從目標隊列中抓取消息,並將其處理到臨時表中進行處理。該消息然後不在目標隊列中,並且這一切都沒有錯誤地工作。
但是......
當我檢查initiaitor隊列,當消息來自,它填補了消息。
SELECT TOP 1000 *, casted_message_body =
CASE message_type_name WHEN 'X'
THEN CAST(message_body AS NVARCHAR(MAX))
ELSE message_body
END
FROM [ICMS].[dbo].[IcmsCarePayInitiatorQueue] WITH(NOLOCK)
我曾經想過,當消息從發起者到目標,發起者會消失。但它似乎正在填補。
我注意到,發起者中的消息具有2的'message_type_id','E'的'驗證'以及消息正文和被轉換的消息正文爲NULL。這裏都有一個message_type_name'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'。
在目標數據庫端,這裏所採用的程序來從隊列中的消息:
CREATE PROCEDURE [dbo].[up_CarePayBrokerReceiveXml]
AS
BEGIN
SET NOCOUNT ON;
DECLARE @XML XML, @Response XML = 'OK', @ConversationHandle UNIQUEIDENTIFIER, @message_type_name SYSNAME, @message_body VARBINARY(MAX), @source_table VARCHAR(100)
DECLARE @Message VARCHAR(MAX), @Line INT, @Proc VARCHAR(MAX), @Exception VARCHAR(MAX)
WHILE (1 = 1)
BEGIN
-- Clear variables, as they may have been populated in previous loop.
SET @message_type_name = NULL
SET @message_body = NULL
SET @ConversationHandle = NULL
SET @source_table = NULL
BEGIN TRY
BEGIN TRAN
WAITFOR ( -- Pop off a message at a time, and add to storage table.
RECEIVE TOP (1)
@message_type_name = message_type_name
, @message_body = message_body
, @ConversationHandle = conversation_handle
, @source_table = CAST([message_body] AS XML).value('(/row/@SourceTable)[1]', 'varchar(50)')
FROM dbo.IcmsCarePayTargetQueue
), TIMEOUT 3000;
IF @@ROWCOUNT = 0
BEGIN
ROLLBACK -- Complete the Transaction (Rollback, as opposeed to Commit, as there is nothing to commit).
BREAK
END
-- Code removed for example, but the fields are saved to a staging table in the database here...
-- Respond to Initiator
SEND ON CONVERSATION @ConversationHandle MESSAGE TYPE [//IcmsCarePay/Message/Response](@Response);
END CONVERSATION @ConversationHandle;
COMMIT -- End of Transaction
END TRY
BEGIN CATCH
-- End the conversation
END CONVERSATION @ConversationHandle WITH CLEANUP
-- Get details about the issue.
SELECT @Exception = ERROR_MESSAGE(), @Line = ERROR_LINE(), @Proc = ERROR_PROCEDURE(), @Message = 'proc: ' + @Proc + '; line: ' + CAST(@Line AS VARCHAR) + '; msg: ' + @Exception
SELECT @Message -- Displays on Concole when debugging.
-- Log the issue to the Application Log.
INSERT INTO dbo.ApplicationLog
(LogDate ,
Thread ,
Level ,
Logger ,
Message ,
Exception
)
VALUES (GETDATE() , -- LogDate - datetime
'None' , -- Thread - varchar(255)
'FATAL' , -- Level - varchar(50)
'____up_CarePayBrokerReceiveXml' , -- Logger - varchar(255)
@Message , -- Message - varchar(4000)
@Exception -- Exception - varchar(2000)
)
COMMIT -- We have stored the erronous message, and popped it off the queue. Commit these changes.
END CATCH
END -- end while
END
爲什麼這些消息呆在那裏?消息
細節保留在啓動器隊列是:
Status: 1
Priority: 5
queuing_order: 395
mess_sequence_number: 0
service_name: //IcmsCarePay/Service/Initiator
service_contract_name: //IcmsCarePay/Contract
message_type_name: http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog
message_type_id: 2
validation: E
message_body: NULL
casted_message_body: NULL
Thanks @RogerWolf - 我想選擇1.我不是100%確定'Handle EndDialog messages'是什麼意思。上述程序是否需要該代碼? – Craig
我修改了問題以顯示接收方的閱讀過程。 – Craig
我已添加END CONVERSATION @InitDlgHandle;在啓動過程中,在SEND之後,這已經「解決」了問題,因爲在啓動隊列中不再有消息出現,並且系統按照預期工作。這是好的,因爲我沒有處理來自目標隊列的任何響應? – Craig