SQL Server Service Broker-подробный, используемый пример внешнего консольного приложения
мне нужно руководство от всех, кто развернул реальное приложение в производстве, которое использует механизм внешней активации SQL Server Service Broker (через внешний активатор Service Broker из пакета функций).
нынешнее мышление:
мои спецификации довольно просты (или, по крайней мере, я так думаю), поэтому я думаю о следующем основном потоке:
order-like сущность вставляется в Table_Orders С состояние "подтверждено"
-
SP_BeginOrder выполняется и делает следующее:
- начинается транзакция
- запускает диалог из Service_HandleOrderState to Service_PreprocessOrder
- сохраняет дескриптор разговора (отныне PreprocessingHandle) в определенном столбце заказы стол
- отправляет сообщение типа Message_PreprocessOrder содержащий идентификатор заказа с помощью PreprocessingHandle
- завершает транзакцию
обратите внимание, что я не заканчивая разговор, я не хочу!--46-->"выстрелил-забыл"
-
уведомление о событии на 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)
- внутренняя активация на 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
(конец ДИАЛОГ):- завершает разговор, относящийся к дескриптору разговора сообщения
- завершает транзакцию
- уведомление о событии на Queue_ProcessOrderItem активирует экземпляр ProcessOrderItem.exe (максимальное одновременное 1) которое делает следующее:
- начинается SqlTransaction
- получает первое сообщение от Queue_ProcessOrderItem
- если тип сообщения Message_ProcessOrderItem (формат XML):
- устанавливает состояние элемента заказа в "обработка" в Table_OrdersItems используя идентификатор элемента заказа в теле сообщения, затем:
- загружает коллекцию параметров элемента заказа
- делает HttpRequest URL-адрес, используя параметры
- сохраняет HttpResponse в формате PDF на файловая система
- если возникли ошибки в выше действия, устанавливает предмет того, состояние на "ошибки", иначе "ОК"
- выполняет поиск в разделе Table_OrdersItems чтобы определить, обрабатываются ли все элементы заказа (состояние "ОК" или "ошибка")
- если все детали заказа обрабатываются:
- отправляет сообщение типа Message_ProcessingDone, содержащий код заказа, используя ProcessOrderItemsHandle
- завершает разговор, относящийся к ProcessOrderItemsHandle
- устанавливает состояние элемента заказа в "обработка" в Table_OrdersItems используя идентификатор элемента заказа в теле сообщения, затем:
- фиксирует SqlTransaction
- выходит с окружающей средой.Выход(0)
Примечания:
- спецификации определяют совместимость MSSQL 2005 до 2012, поэтому:
- нет групп разговора
- нет разговора Приоритет
- нет POISON_MESSAGE_HANDLING (статус = выкл)
- Я стремлюсь достичь общей целостности потока и непрерывности, а не скорости
- учитывая, что таблицы и SPs находятся в DB1 в то время как объекты Service Broker (сообщения, контракты, очереди, услуги) находятся в в DB2, в DB2 установлен надежный
вопросы:
- есть ли какие-либо серьезные недостатки дизайна в описанной архитектуре ?
- отслеживание состояния завершения заказа не кажется правильным. Есть ли лучший способ ? Может быть, с помощью удержания очереди ?
- моя интуиция говорит мне, что ни в коем случае активированный внешний exe не должен завершаться кодом выхода, отличным от 0, поэтому должно быть
try{..}catch(Exception e){..} finally{ Environment.Exit(0) }
в Main. Правильно ли это предположение ? - как бы вы организовали обработку ошибок в коде БД ? Достаточно ли таблицы журнала ошибок?
- как бы вы организовать обработку ошибок во внешнем коде exe c#? Тот же журнал ошибок стол ?
- Я видел образцы продуктов SQL Server Service Broker, но интерфейс Service Broker кажется излишним для моего, казалось бы, более простого случая. Любые альтернативы для более простой объектной модели Service Broker ?
- любой "портативный" инструмент администрирования кросс-версии для Service Broker, способный, по крайней мере, сливать ядовитые сообщения ?
- у вас есть достойные образцы кода для любого из наверху ?
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. Это может быть или не быть приемлемым для вас.