SQL Server Service Broker-подробный, используемый пример внешнего консольного приложения

мне нужно руководство от всех, кто развернул реальное приложение в производстве, которое использует механизм внешней активации SQL Server Service Broker (через внешний активатор Service Broker из пакета функций).

нынешнее мышление:

мои спецификации довольно просты (или, по крайней мере, я так думаю), поэтому я думаю о следующем основном потоке:

  1. order-like сущность вставляется в Table_Orders С состояние "подтверждено"

  2. SP_BeginOrder выполняется и делает следующее:

    • начинается транзакция
    • запускает диалог из Service_HandleOrderState to Service_PreprocessOrder
    • сохраняет дескриптор разговора (отныне PreprocessingHandle) в определенном столбце заказы стол
    • отправляет сообщение типа Message_PreprocessOrder содержащий идентификатор заказа с помощью PreprocessingHandle
    • завершает транзакцию

    обратите внимание, что я не заканчивая разговор, я не хочу!--46-->"выстрелил-забыл"

  3. уведомление о событии на Queue_PreprocessOrder активирует экземпляр PreprocessOrder.exe (максимальное одновременное 1) которое делает следующий:

    • начинается SqlTransaction
    • получает первое сообщение от Queue_PreprocessOrder
    • если тип сообщения Message_PreprocessOrder (формат XML):
      • устанавливает состояние заказа в "предварительная обработка" в Table_Orders использование id заказа в тексте сообщения
      • загружает N коллекций данных, из которых вычисляет N-арных Carthesian продукта (через LINQ, которая, насколько мне известно это невозможно в T-SQL) определить коллекцию элементов заказа
      • вставляет строки элементов заказа в Table_OrderItems
      • отправляет сообщение типа Message_PreprocessingDone, содержащий тот же идентификатор заказа, используя PreprocessingHandle
      • завершает разговор, относящийся к PreprocessingHandle
    • совершает SqlTransaction
    • выходит с окружающей средой.Выход(0)
  4. внутренняя активация на Queue_HandleOrderState выполняет SP (max concurrent of 1), который:
    • начинается транзакция
    • получает первое сообщение от Queue_InitiatePreprocessOrder
    • если тип сообщения Message_PreprocessingDone:
      • состояние заказа "в обработке" в Table_Orders использование id заказа в тексте сообщения
      • запускает диалог из Service_HandleOrderState to Service_ProcessOrderItem
      • сохраняет дескриптор разговора (отныне ProcessOrderItemsHandle) в определенном столбце Table_Orders
      • создает курсор для строк в Table_OrderItems для текущего id заказа и для каждого ряд:
        • отправляет сообщение типа Message_ProcessOrderItem, содержащий идентификатор элемента заказа, используя ProcessOrderItemsHandle
    • если тип сообщения Message_ProcessingDone:
      • устанавливает состояние заказа в "обработано" в Table_Orders использование id заказа в тексте сообщения
    • если тип сообщения http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog (конец ДИАЛОГ):
      • завершает разговор, относящийся к дескриптору разговора сообщения
    • завершает транзакцию
  5. уведомление о событии на Queue_ProcessOrderItem активирует экземпляр ProcessOrderItem.exe (максимальное одновременное 1) которое делает следующее:
    • начинается SqlTransaction
    • получает первое сообщение от Queue_ProcessOrderItem
    • если тип сообщения Message_ProcessOrderItem (формат XML):
      • устанавливает состояние элемента заказа в "обработка" в Table_OrdersItems используя идентификатор элемента заказа в теле сообщения, затем:
        • загружает коллекцию параметров элемента заказа
        • делает HttpRequest URL-адрес, используя параметры
        • сохраняет HttpResponse в формате PDF на файловая система
      • если возникли ошибки в выше действия, устанавливает предмет того, состояние на "ошибки", иначе "ОК"
      • выполняет поиск в разделе Table_OrdersItems чтобы определить, обрабатываются ли все элементы заказа (состояние "ОК" или "ошибка")
      • если все детали заказа обрабатываются:
        • отправляет сообщение типа Message_ProcessingDone, содержащий код заказа, используя ProcessOrderItemsHandle
        • завершает разговор, относящийся к ProcessOrderItemsHandle
    • фиксирует SqlTransaction
    • выходит с окружающей средой.Выход(0)

Примечания:

  • спецификации определяют совместимость MSSQL 2005 до 2012, поэтому:
    • нет групп разговора
    • нет разговора Приоритет
    • нет POISON_MESSAGE_HANDLING (статус = выкл)
  • Я стремлюсь достичь общей целостности потока и непрерывности, а не скорости
  • учитывая, что таблицы и SPs находятся в DB1 в то время как объекты Service Broker (сообщения, контракты, очереди, услуги) находятся в в DB2, в DB2 установлен надежный

вопросы:

  1. есть ли какие-либо серьезные недостатки дизайна в описанной архитектуре ?
  2. отслеживание состояния завершения заказа не кажется правильным. Есть ли лучший способ ? Может быть, с помощью удержания очереди ?
  3. моя интуиция говорит мне, что ни в коем случае активированный внешний exe не должен завершаться кодом выхода, отличным от 0, поэтому должно быть try{..}catch(Exception e){..} finally{ Environment.Exit(0) } в Main. Правильно ли это предположение ?
  4. как бы вы организовали обработку ошибок в коде БД ? Достаточно ли таблицы журнала ошибок?
  5. как бы вы организовать обработку ошибок во внешнем коде exe c#? Тот же журнал ошибок стол ?
  6. Я видел образцы продуктов SQL Server Service Broker, но интерфейс Service Broker кажется излишним для моего, казалось бы, более простого случая. Любые альтернативы для более простой объектной модели Service Broker ?
  7. любой "портативный" инструмент администрирования кросс-версии для Service Broker, способный, по крайней мере, сливать ядовитые сообщения ?
  8. у вас есть достойные образцы кода для любого из наверху ?

1 ответов


Q: есть ли какие-либо серьезные недостатки дизайна в описанной архитектуре ?
A: пара незначительных преимуществ:
- ожидание завершения HTTP-запроса при удержании открытой транзакции плохо. Вы все равно не можете достичь согласованности транзакций между базой данных и HTTP, поэтому не рискуйте растягивать транзакцию в течение нескольких минут, когда HTTP медленный. Типичный шаблон - {begin tran/receive/начать разговор таймер / commit} затем выполните вызов HTTP без каких-либо DB xact. Если HTTP-вызов выполняется успешно, то {begin xact/send response/end conversation/commit}. Если HTTP не удается (или сбой клиента), то пусть время разговора активировать вас снова. Вы получите сообщение таймера (без тела), вам нужно забрать идентификатор элемента, связанный с дескриптором из вашей таблицы(ов).

Q: отслеживание состояния завершения заказа не кажется правильным. Есть ли лучший способ ? Может быть, с помощью удержания очереди ?
A: моя единственная критика вашего государства отслеживание-это зависимость от сканирования элементов заказа, чтобы определить, что текущий обработанный является последним (5.3.4). Например, вы можете добавить информацию о том, что это "последний" элемент, обрабатываемый в состоянии элемента, чтобы при его обработке вы знали, что вам нужно сообщить о завершении. Хранение полезно только при отладке или когда у вас есть логика, требующая запуска "логического отката" и компенсации действий при ошибке разговора.

Q: моя интуиция говорит мне, что ни в коем случае активированный внешний exe не должен завершаться кодом выхода, отличным от 0, поэтому должна быть попытка{..}catch (исключение e){..} наконец{ окружающая среда.Выход(0) } в Main. Правильно ли это предположение ?
A: самое главное, чтобы активированный процесс выдал оператор RECEIVE в очереди. Если это не удается сделать монитор очереди может войти в уведомленное состояние навсегда. Код выхода, если я правильно помню, не имеет значения. Как с любой фоновый процесс важен для отслеживания и регистрации исключений, иначе вы никогда даже не узнаете, что у него есть проблема, когда он начинает терпеть неудачу. В дополнение к дисциплинированным блокам try / catch, Hookup Application.ThreadException для UI приложений и AppDomain.UnhandledException для UI и не-UI приложений.

Q: Как бы вы организовали обработку ошибок в коде БД ? Достаточно ли таблицы журнала ошибок?
A: я буду следить за этим позже. Достаточно таблицы журнала ошибок по моему.

Q :Как бы вы организовали обработку ошибок во внешнем коде exe c#? Та же таблица регистрации ошибок ?
A: я создалbugcollect.com именно потому, что мне приходилось справляться с такими проблемами с моими собственными приложениями. Проблема больше, чем ведение журнала, вы также хотите некоторые агрегация и анализ (по крайней мере, обнаружение дубликатов отчетов) и подавление наводнений ошибок из некоторых неудач конфигурации развертывания "на поле". По правде говоря, в наши дни есть больше вариантов, например. exceptron.com. И, конечно, я думаю, что FogBugs также имеет возможности ведения журнала.

Q: я видел образцы продуктов SQL Server Service Broker, но интерфейс Service Broker кажется излишним для моего, казалось бы, более простого случая. Любые альтернативы для более простой объектной модели Service Broker ?
наконец, простой вопрос: Да, это перебор. Нет простой модели.

Q: любой кросс-версия "портативный" инструмент администратора для Service Broker способен, по крайней мере, сливать ядовитые сообщения ?
A: проблема с ядовитыми сообщениями заключается в том, что определение ядовитого сообщения изменяется с вашим кодом: ядовитое сообщение-это любое сообщение, которое нарушает текущие охранники, установленные на месте, чтобы обнаружить его.

Q: есть ли у вас достойные образцы кода для любого из вышеперечисленных ?
A: Нет

еще один момент: попытайтесь избежать любой ссылки из DB1 в DB2 (например. 4.3.4 активируется в DB1 и считывает таблицу items из DB2). Это создает перекрестные зависимости БД, которые ломаются, когда a) одна БД находится в автономном режиме (например. для обслуживания) или перегружен или б) вы добавляете зеркальное отображение базы данных для HA/DR, и одна БД завершается с ошибкой. Попробуйте заставить код работать, даже если DB1 и DB2 находятся на разных машинах (и не связаны с серверами). При необходимости добавьте дополнительные сведения в полезную нагрузку сообщений. И если вы создадите его таким образом, что DB2 можете быть на другой машине, и даже несколько машин DB2 могут существует для масштабирования работы записи HTTP / PDF.

и, наконец: этот дизайн будет очень медленно. Я говорю о низких десятках сообщений в секунду медленно, с таким количеством диалогов/сообщений и все с max_queue_readers 1. Это может быть или не быть приемлемым для вас.