Инициатор никогда не активировался при подтверждении EndDialog

Я хочу соблюдать метод повторного использования диалогов Ремуса Русану в своей реализации SSB. Я написал некоторую процедуру активации для очереди инициатора, чтобы перехватить сообщение EndDialog обратно от цели и очистить таблицу Dialog от дескриптора закрытого диалога.

Тем не менее, хотя подтверждение EndDialog правильно достигает стороны инициатора, активация не запускается, поэтому мой обработчик сообщений не может работать и очищать место.

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, который не требует пояснений: Трассировка профилировщика.

Пример чисто локальный (один экземпляр/две БД).

Спасибо,

Обновление Еще несколько показателей для сбойной очереди: `SELECT que.[имя], que.is_activation_enabled, que.is_receive_enabled, que.is_poison_message_handling_enabled, que.activation_procedure, que.max_readers, [execute_as] = (SELECT pri.[имя] ОТ sys.database_principals pri ГДЕ pri.principal_id = que.execute_as_principal_id) ОТ sys.service_queues que ГДЕ que.[имя] = 'SenderQueue'; ИДТИ

ВЫБЕРИТЕ дескриптор_беседы, to_service_name, message_type_name, is_conversation_error, is_end_of_dialog, enqueue_time, transfer_status FROM sys.transmission_queue; ИДТИ

ВЫБЕРИТЕ [имя], is_broker_enabled, log_reuse_wait_desc FROM sys.databases WHERE database_id = 8; ИДТИ

EXEC sp_spaceused 'fdwh.SenderQueue'; ИДТИ

SELECT * FROM sys.dm_broker_activated_tasks WHERE database_id=8; ИДТИ

ВЫБЕРИТЕ [состояние], last_activated_time, tasks_waiting FROM sys.dm_broker_queue_monitors, ГДЕ database_id = 8; ВПЕРЕД `

Результаты


person tivivi    schedule 08.08.2019    source источник
comment
Проверьте журнал ошибок SQL Server на наличие сообщений, связанных с ошибками активации.   -  person Dan Guzman    schedule 10.08.2019
comment
Спасибо @DanGuzman. Ничего ценного в журнале ошибок. Кстати, моя хранимая процедура активации активируется во всех остальных случаях (исходящее сообщение об ошибке, пользовательская реализация ping). Я посмотрел на какую-то ветку от Remuses, посвященную устранению неполадок с активацией, но безуспешно. Я могу предоставить дополнительные показатели, касающиеся моей очереди виновных.   -  person tivivi    schedule 12.08.2019
comment
Забыл сказать, что я также запускал сеанс мониторинга xevent, устанавливая область действия для события активации очереди, и ни одно событие не было перехвачено для случая EndDialog, в то время как для других случаев все работает нормально.   -  person tivivi    schedule 12.08.2019


Ответы (1)


Активация происходит только при поступлении новых сообщений.

"Когда STATUS = ON, очередь запускает хранимую процедуру, указанную в PROCEDURE_NAME, когда количество запущенных процедур меньше MAX_QUEUE_READERS и когда сообщения поступают в очередь быстрее, чем хранимые процедуры получают сообщения."

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

Ожидается, что процедура активации будет продолжать потреблять сообщения до тех пор, пока очередь не станет пустой, и остается пустой в течение времени WATFOR ... RECEIVE.

В вашей процедуре активации отсутствует цикл. Он ПОЛУЧАЕТ одно сообщение и выходит. Таким образом, каждый раз, когда приходит новое сообщение, потребляется одно старое сообщение. Это может казаться какое-то время эффективным, но если у вас когда-нибудь возникнет скопление сообщений, вы никогда не наверстаете упущенное.

person David Browne - Microsoft    schedule 12.08.2019
comment
Здравствуйте, @david-browne-microsoft. Спасибо за ценный отзыв. Действительно, в моей процедуре активации есть утечка, связанная с процессом многократного повторения сообщений подряд. Я исправлю это. Тем не менее, это не причина, по которой я помечаю эту тему как решенную. Я заметил, что до сих пор не осознавал, что я неожиданно выполнял обмен сообщениями по принципу «запустил и забыл» :( Завершение разговора должно быть инициировано либо целью, либо инициатором при ответе на входящее уведомление об ошибке от цели. Во-первых, никогда от инициатора, если только активация никогда не сработает. - person tivivi; 16.08.2019