SQL Server Service Broker. Диагностика и решение проблем. Начало.
Данную статью меня сподвигла написать проблема, которую я недавно решал у одного из заказчиков. Более точно сказать было даже несколько проблем, которые, как обычно, наслоились друг на друга (или их "наслоили" администраторы пытавшиеся решить проблему). Статья не ставит перед собой целью всестороннее и подробнейшее описание всей системы Service Broker, со всеми ее возможностями. Здесь лишь описана среда, с которой я сталкивался наиболее часто в ходе решения проблем.
Наверное все, кто читают данный блог знают, что такое Service Broker в SQL Server, но, для того чтобы начать с одной исходной точки, я скажу пару слов об этой штуковине.
Впервые эта полезная вещь появилась в SQL Server 2005, и с тех пор не сильно изменилась. Точнее сказать она приросла некоторыми новыми возможностями, но принципы, заложенные в те годы, так и остались неизменными.
Итак.
Как следует из https://technet.microsoft.com/ru-ru/library/ms166049(v=sql.105).aspx, компонент Service Broker помогает создавать асинхронные слабосвязанные приложения, в которых независимые компоненты совместно выполняют ту или иную задачу. Эти компоненты обмениваются сообщениями, которые содержат данные, необходимые для выполнения задачи. В этом разделе описываются следующие аспекты компонента Service Broker:
- диалоги;
- упорядочение и координация сообщений;
- асинхронное программирование на основе транзакций;
- поддержка слабосвязанных приложений;
- составные части компонента Service Broker.
Основными строительными кирпичиками системы являются:
- Сообщения. Блоки информации, которыми обмениваются участники.
- Контракт. Сообщения собираются в контракт для того, что бы обмен сообщениями был более формализован.
- Очереди. Сообщения для отправки и при получении помещаются в специальные очереди, которые есть как у отправителя, так и у получателя.
- Сервис. Все вышеперечисленные компоненты соединяются сервисом, который и является единицей взаимодействия в системе.
- Маршруты. Для доставки сообщений на сервисы создаются маршруты доставки.
- Диалог. Программируемый способ отправки сообщения от инициатора к получателю и обратно.
- Транзакции. Вся обработка данных при передаче и получении производится по транзактному принципу, исключающему утрату данных.
Надо сказать, что инфраструктура Service Broker оказалась настолько успешной, что она широко используются в SQL Server для реализации других возможностей, таких как Query Notification, AlwaysOn Availability Group и некоторых других компонент SQL Server.
Давайте пошагово разберемся как происходит формирование и передача сообщений в системе Service Broker. Для целей демонстрации я использовал скрипты, очень похожие на те, что опубликованы здесь https://technet.microsoft.com/en-us/library/bb839483(v=sql.105).aspx.
Моя тестовая среда включает в себя:
- Два экземпляра SQL Server установленных на разных виртуальных машинах
- Контроллер домена.
- Точки доступа (Endpoints) настроены для использования Windows аутентификации.
- На обоих серверах созданы пользователи без логинов, использующие сертификаты для взаимной аутентификации.
- Сертификаты скопированы на оба сервера с использованием backup.
Как это все работает вместе. Ниже приведена упрощенная схема обмена сообщениями и ее описание.
1. При отправке с инициатора сообщение попадает во внутреннюю очередь передачи представляющую собой внутреннюю системную таблицу sys.sysxmitqueue, выполнив запрос к ней мы получим, то, что ожидали.
Для просмотра сообщений, находящихся в очереди, во вне "выставлено" динамическое представление sys.transmission_queue, выполнив запрос к которому вы получите почти тот же результат. Однако в этом представлении есть очень полезный элемент, это столбец transmission_status, содержащий информацию об ошибке, возникшей при передаче и обработке сообщения.
Например: "Connection attempt failed with error: '10061(No connection could be made because the target machine actively refused it.)'."
Также сообщение логируется в журнале транзакций, что обеспечивает его транзактную обработку.
Все сообщения от всех создаваемых сервисов проходят через эту внутреннюю таблицу и соответственно через просмотр, и при отсутствии ошибок передаются далее. Перед передачей сообщения могут шифроваться с использованием сертификатов. Будут сообщения шифроваться или нет зависит от настроек диалога инициирующего соединение.
2. После помещения сообщения в очередь передачи (sys.transmission_queue) выполняется его классифицирование.
Суть классификации состоит в том, чтобы определить, где размещен сервис, которому это сообщение адресуется. Для определения направления передачи используются маршруты доставки,созданные на этапе развертывания сервиса. В данном случае настроено два маршрута. Один указывает на удаленный сервис-получатель, другой указывает на локальный экземпляр SQL Server для доставки локальных оповещений.
Мы можем увидеть выполнение этапа классификации с помощью трасс SQL Profiler, если выберем события относящиеся к Service Broker. Обращаю внимание, что часть событий относящихся к Service Broker размещены в разделе Security Audit.
3. После выполнения классификации сообщения, устанавливается соединение с удаленной (как в данном случае) точкой соединения (Endpoint). В данном случае - это сервер использующий протокол TCP, с именем SQL2014-I1 и номером порта (Endpoint) 4022. Если при выполнении соединения возникнет ошибка, то она появится в трассе (как показано ниже) и в столбце transmission_status просмотра sys.transmission_queue.
4. На следующем этапе происходит отправка сообщения сервису получателю и его подтверждение от принимающей стороны. Если на донном этапе выполнить запрос к представлению transmission_queue, то оно возвратит пустой результат, поскольку все данные из очереди отправителя переданы.
В трассе на инициаторе и отправителе мы увидим подтверждение передачи.
5. Поскольку сообщение доставлено до получателя, то оно должно появиться во входной очереди получателя.
По правде говоря, имя очереди получателя, к которой мы в данном случае сделали запрос, это виртуальный объект типа просмотр (View). Реально, данные на получателе сохраняются системной таблице, доступ к которой можно получить через DAC.
В данном случае это внутренняя таблица queue_messages_293576084. Выполнив запрос к которой мы получим почти те же данные, что и при обращении к очереди InstTargetQueue.
И так. Мы прошли по всей цепочке от момента формирования сообщения до получения его целевым сервисом.
Далее, целевой сервис должен прочитать сообщения из очереди (желательно по одному) и отправить подтверждение о получении инициатору диалога. Делается эта процедура с использованием специального синтаксиса, который есть в прилагаемых скриптах https://technet.microsoft.com/en-us/library/bb839483(v=sql.105).aspx.
По мере чтения данных из очереди она пустеет, а отправителю посылается подтверждающие сообщения (или не посылаются) форма, состав которых, а также посылаются они, или нет, зависит от разработчика сервиса.
Если по мере чтения очереди программируется отправка подтверждающих сообщений, то они проходят тот же путь, что и от получателя, только в обратном порядке.
В данном блоге мы достаточно подробно рассмотрели весь путь от отправителя до получателя и в следующем начнем рассмотрение вопросов связанных с решением проблем с Service Broker на каждом из этапов обработки и передачи..
Александр Каленик, Senior Premier Field Engineer (PFE), MSFT (Russia)