SQL-брокер sys.conversation_groups не очищается после завершения разговора - PullRequest
1 голос
/ 02 апреля 2019


У меня SQL Server 2016 Broker включен в базе данных. В настоящее время я тестирую и вижу, что таблица sys.conversation_groups не очищается даже после завершения разговоров. Должен ли я беспокоиться об этом? Мне трудно понять роль этой таблицы во всем этом.

Обратите внимание, что я отправляю сообщение ОТ и В мою очередь запросов. Это плохая практика? Мне не нужен ответ. Я читаю сообщения в своем приложении на C # и заканчиваю разговор.

Вот мои настройки:

CREATE MESSAGE TYPE SomeMessageType VALIDATION=NONE;
CREATE MESSAGE TYPE SomeReplyType VALIDATION=NONE; 

CREATE CONTRACT MyMessageContract
(
 SomeMessageType SENT BY INITIATOR 
,SomeReplyType SENT BY TARGET 
);

CREATE QUEUE MyBrokerRequestsQueue

CREATE SERVICE BrokerRequestsServices
ON QUEUE MyBrokerRequestsQueue (MyMessageContract); 

Затем я отправляю сообщения таким образом (все еще на моем тестовом сервере, будет отправлено триггером после завершения тестов):

declare @count int;
set @count = 1;

declare @msg nvarchar(max);
set @msg = 'This is a test ';

while (@count <= 100)
begin
    DECLARE @handle UNIQUEIDENTIFIER;

    BEGIN DIALOG @handle
      FROM SERVICE BrokerRequestsServices
      TO SERVICE 'BrokerRequestsServices'
      ON CONTRACT MyMessageContract
      WITH ENCRYPTION = ON;

      set @msg = 'This is a test ' + convert(nvarchar(3), @count);

      SEND ON CONVERSATION @handle MESSAGE TYPE SomeMessageType  ( @msg );

      set @count = @count + 1
end

Программа на C # читает очередь следующим образом:

string SQL = string.Format(@"
        waitfor( 
            RECEIVE top (@count) conversation_handle,service_name,message_type_name,message_body,message_sequence_number 
            FROM [{0}] 
                ), timeout @timeout", queueName);
  SqlCommand cmd = new SqlCommand(SQL, con);

  SqlParameter pCount = cmd.Parameters.Add("@count", SqlDbType.Int);
  pCount.Value = maxMessages;

  SqlParameter pTimeout = cmd.Parameters.Add("@timeout", SqlDbType.Int);

  if (timeout == TimeSpan.MaxValue)
  {
    pTimeout.Value = -1;
  }
  else
  {
    pTimeout.Value = (int)timeout.TotalMilliseconds;
  }

  cmd.CommandTimeout = 0; //honor the RECIEVE timeout, whatever it is.


  return cmd.ExecuteReader();

И затем, когда он получает сообщение, читает дескриптор разговора и заканчивает его.

END CONVERSATION @ConversationHandle;

Я что-то здесь не так делаю?

1 Ответ

1 голос
/ 14 мая 2019

Хорошо, так что я думаю, что мои проблемы вызваны паттерном «огонь и забудь».Но в случае моего приложения, это действительно шаблон, который нам нужен.(Мы не обрабатываем никаких ошибок.) Кроме того, у нас есть служба, которая угрожает этим сообщениям, и если служба была остановлена, она реинициализируется сама и не нуждается в сообщениях, которые были сгенерированы, пока она не работала.

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

BEGIN DIALOG @handle
FROM SERVICE BrokerRequestsServices
TO SERVICE 'BrokerRequestsServices'
ON CONTRACT MyMessageContract
WITH ENCRYPTION = ON, LIFETIME = 120;

Таким образом, если служба работает, она прочитает сообщение и завершит разговор, и даже если разговор останется в состоянии «Разговор», он исчезнет через две минуты.А если служба не работает, она не будет читать старые сообщения после того, как вернется.

...