Транзакции в NServicebus с использованием Azure Service Bus Transport
У меня есть несколько обработчиков сообщений в конкретной конечной точке, которые выполняют свою работу с базой данных SQL Azure (в данный момент все еще используется локальный экземпляр SQL 2012). У меня есть обработчик команд, который публикует 2 события, называя их X и Y. В одной и той же конечной точке у меня есть подписчик на X и подписчик на Y. Оба этих подписчика внутренне используют один и тот же компонент доступа к данным, называемую Z. Зависимость Внедрение настраивается для каждого вызова, а не для общего доступа.
Компонент Z использует Entity Framework 6 под занавес. У меня проблема в том, что простое открытие базы данных вызывает исключение SqlException и жалоб на эскалацию MSDTC.
Я временно обернул обработчики в TransactionScope.Suppress, и это остановило ошибку, но я считаю, что мне не хватает чего-то более фундаментального.
Это простой вопрос настройки конечной точки, чтобы она не была транзакционной? Я бы подумал, что это будет просто работать, поскольку я настроил использование служебной шины Azure в качестве транспортного механизма. Если я сделаю это, NServiceBus все еще попытается, если в обработчике сообщений возникнет исключение? (До границ SLR - не часть вопроса, я также понимаю проблемы идемпотентности).
2 ответа
@Фил,
Во-первых, вы не должны использовать MSDTC с SQL Azure - он не поддерживается. Функция предлагается, но только на рассмотрении. DTC не поддерживается в Azure. В качестве альтернативы вы могли бы рассмотреть следующее предложение использовать подход SqlTransaction.
Во-вторых, используемый вами транспорт не имеет никакого отношения к вашему доступу к данным. Поскольку вы используете служебную шину Azure, она не будет частью вашего кода обработчика. Делать обработчик транзакционным - это форсировать атомарное изменение или откат. Независимо от вашего обработчика, повторите попытку. Проблема заключается в том, что когда обработчик / конечная точка не является транзакционным, а в обработчике первая запись в БД выполнена успешно, а вторая - неудачно, первая запись не будет отменена. Что касается служебной шины Azure в качестве транспорта, она не является транзакционной по своей природе (то есть без кода DTC).
На какой версии NServiceBus.Azure вы работаете? Есть ли у вас трассировка стека исключения? Откуда это взялось?
Мы явно выталкиваем отправку и публикацию из области действия принимающей транзакции, чтобы предотвратить продвижение к DTC, чтобы транзакция была локальной для sql, поэтому я сомневаюсь, что это происходит здесь.
Из вашего описания похоже, что вы используете разные экземпляры доступа к данным для каждого обработчика (для каждой конфигурации контейнера вызовов), и у вас есть несколько обработчиков для одного сообщения. Если оба они откроют новое соединение с SQL, вы также увидите продвижение (даже если это тот же сервер)
Может ли это быть? Что это бросает на втором открытии?