确认 EndDialog 后,启动器从未激活

Initiator never activated when acknowledged of EndDialog

我希望在我的 SSB 实现中遵循 Remus Rusanu 的对话回收技术。我为启动器队列编写了一些激活程序,以便从目标中钩回 EndDialog 消息并从已关闭的对话句柄中清除 Dialog table。

尽管如此,虽然EndDialog ack正确地到达了启动端,但没有触发激活,所以我的消息处理程序无法操作和清理这个地方。

CREATE PROCEDURE fdwh.ProcessResponse
AS
BEGIN
    DECLARE @dlgId UNIQUEIDENTIFIER;
    DECLARE @msgTypeName SYSNAME;
    DECLARE @msgBody VARBINARY(MAX);
    DECLARE @payloadHistoryId   INT;

    BEGIN TRY
        BEGIN TRANSACTION

        WAITFOR(
            RECEIVE TOP(1)
                @dlgId = [conversation_handle],
                @msgTypeName = message_type_name,
                @msgBody = message_body
            FROM [fdwh].[SenderQueue]), TIMEOUT 10;

        -- Message is regular end of conversation, terminate it
        IF (@msgTypeName = N'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog')
        BEGIN
            END CONVERSATION @dlgId;

            DELETE FROM DWH_BOARD.dbo.Dialog
            WHERE (DbId = DB_ID()) AND
                  (DialogId = @dlgId);
        END

        -- Message is error, extracts and logs number and description
        IF (@msgTypeName = N'http://schemas.microsoft.com/SQL/ServiceBroker/Error')
        BEGIN
[...]

我希望触发队列激活并处理 http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog 消息,但事实并非如此。 EndDialog ACK 不是常规消息吗?

请在下面找到自我解释的 Profiler 跟踪屏幕截图:

示例是纯本地的(单个 instance/two 数据库)。

谢谢,

更新 失败队列的更多指标: `SELECT que.[name], que.is_activation_enabled, que.is_receive_enabled, que.is_poison_message_handling_enabled, que.activation_procedure, que.max_readers, [execute_as] = (SELECT pri.[name] FROM sys.database_principals pri WHERE pri.principal_id = que.execute_as_principal_id) FROM sys.service_queues que WHERE que.[name] = 'SenderQueue' ; 开始

SELECT conversation_handle, to_service_name, message_type_name, is_conversation_error, is_end_of_dialog, enqueue_time, transmission_status 来自 sys.transmission_queue; 开始

SELECT [姓名], is_broker_enabled, log_reuse_wait_desc 来自 sys.databases WHERE database_id = 8; 开始

执行sp_spaceused'fdwh.SenderQueue'; 开始

SELECT * 来自 sys.dm_broker_activated_tasks 其中 database_id=8; 开始

SELECT [state], last_activated_time, tasks_waiting FROM sys.dm_broker_queue_monitors WHERE database_id = 8; 走 `

仅当新消息到达时才会激活。

"When STATUS = ON, the queue starts the stored procedure specified with PROCEDURE_NAME when the number of procedures currently running is less than MAX_QUEUE_READERS and when messages arrive on the queue faster than the stored procedures receive messages."

https://docs.microsoft.com/en-us/sql/t-sql/statements/alter-queue-transact-sql?view=sql-server-2017

激活过程预计会继续使用消息,直到队列为空,并在其 WATFOR ... RECEIVE 期间保持为空。

您的激活程序缺少循环。它正在接收一条消息并退出。因此,每次新消息到达时,都会消耗一条旧消息。这可能 看起来 可以工作一段时间,但如果您遇到积压的消息,您将永远赶不上。