2009-08-12 5 views
15

Я начинающий брокер службы Sql Server, и я пытаюсь понять, как лучше всего установить Service Broker для (казалось бы) простого использования: я хочу создать простую рабочую очередь, где одно приложение бросает рабочие элементы в очередь, и отдельное приложение захватывает рабочие элементы из этой очереди и обрабатывает их. Нет необходимости, чтобы первое приложение получало сообщения статуса со второго. Я хочу, чтобы очередь работала в одном экземпляре сервера Sql.Sql Server Service Broker: как структурировать разговоры для простого сценария очереди?

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

  • Каждый раз, когда я устанавливаю рабочий элемент, я начинаю новый разговор. Поэтому каждый разговор заканчивается тем, что в нем есть только одно сообщение.
  • Во время развертывания я вручную создаю один сеанс бесконечной продолжительности жизни. Когда пришло время поставить в очередь рабочий элемент, я всегда отправляю его как часть этого единственного разговора.

Каковы будут последствия перехода любого из этих маршрутов?

Кроме того, в первом случае мне кажется, что мне нужно сделать некоторые КОНЕЦ КОНЕЦ, чтобы сервер Sql мог очищать ресурсы внутри. Есть ли какие-либо указания относительно того, когда было бы правильным местом для их размещения? (Или, возможно, в будущем лучше будет полагаться на тайминги разговоров?)

+0

Вы, кажется, говорите об одной очереди, но ... http://stackoverflow.com/questions/14643015/why-do-i-need-two-sql-server-service-broker-quees-for-a-simple-task – cja

ответ

26

Вы должны начать с каждого рабочего элемента в своем собственном разговоре. Производитель (инициатор) начинает диалог и отправляет сообщение, описывающее рабочий элемент, а затем совершает. Пользователь (цель) получает сообщение (или активируется), проверяет полезную нагрузку, чтобы понять детали рабочего элемента, выполняет работу, затем завершает диалог и фиксирует. Полученное сообщение EndDialog отправляется обратно в очередь обслуживания инициатора, и активированная процедура в очереди инициатора отвечает на него, завершая диалог со стороны инициатора.

Это простейшее развертывание, и его запуск и работа гарантируют, что у вас будет хорошая основа для развития. Не разрезайте углы и не завершайте диалог со стороны инициатора, начиная с того момента, когда производитель задает рабочий элемент, это fire-and-forget and has several draw backs.

Если у вас высокие требования к производительности (более 200 запросов в секунду), вам нужно будет начать управлять разговорами более явно. У меня есть запись в блоге на reusing conversations for performance reasons. На стороне приема я рекомендую читать Writing Service Broker Procedures.

У меня также есть запись в блоге, которая в значительной степени делает то, что вам нужно, хотя оно не расписывает рабочие элементы, а вместо этого запускает пользовательскую процедуру: Asynchronous procedure execution.

Если вы решите использовать рабочие элементы из активированного контекста, таким образом, используя хорошие возможности самостоятельной балансировки активации, вам необходимо установить understand the EXECUTE AS context under which activation occurs.

+0

Другим преимуществом повторного использования разговоров является то, что вы избегаете проблемы, описанной в «Внутренний запрос на работу 642585», (не публичный). А именно, каждый разговор, который вы создаете и уничтожаете, пропускает небольшое количество выделенного пространства в TempDB, которое не будет выпущено до тех пор, пока вы не отскочите экземпляр. В приложениях с высокой пропускной способностью это может вывести размер TempDB и заставить вас перезапустить экземпляр, чтобы сжать его снова. –

+0

Одной из проблем с использованием отдельного разговора с каждым сообщением является то, что разговоры могут появляться на другом конце не в порядке. Это может произойти, если у вас есть только один поток на принимающей стороне. Помните, что Service Broker гарантирует последовательность внутри разговора. Вся причина для разговоров - управлять секвенированием, когда на принимающем конце очереди есть несколько потоков. Если разговоры сохранялись в последовательности, а также сообщениях, это запрещало бы использование нескольких потоков приема. –

9

Мне очень нравится ответ Ремуса, хотя он особо не касается , почему вы можете предпочесть начать отдельную беседу за рабочий элемент, вместо того, чтобы помещать все рабочие элементы в один разговор.Две заметки, связанные с этим:

Во-первых, включение всех рабочих элементов в один разговор может вызвать проблемы с параллелизмом, если у вас есть несколько потоков/процессов, обрабатывающих рабочие элементы. Сервисные процессы брокера работник, как правило, выглядит следующим образом (в псевдокод):

begin transaction 
receive top n work items from queue 
process work items 
commit transaction 

(К не совершая пока рабочие элементы не будут обработаны, вы убедитесь, что, например, если ваш процесс умирает, то элементы работы он получил но еще не обработано, не будет удалено из очереди.)

Проблема параллелизма возникла бы из-за того, что сервисный брокер запрограммирован таким образом, что каждая команда RECEIVE получает эксклюзивную блокировку чтения для всех сообщений в очереди, которые используют один и тот же сеанс (или группа разговора), как те, которые были RECEIVEd. Эта блокировка сохраняется до тех пор, пока транзакция не будет выполнена. (См. Conversation Group Locks.) Поэтому, если все рабочие элементы в очереди находятся в одном разговоре, тогда, когда один рабочий процесс находится в шаге «work work», никакие другие рабочие процессы не могут выполнять какую-либо работу.

Вторая проблема, заключающаяся в том, что количество отдельных предметов в одном разговоре состоит в том, что оно увеличивает количество рабочих элементов, которые вы можете потерять или которые должны быть обработаны в определенных условиях ошибки. Чтобы правильно описать это, я откладываю на Ремуса; см. его Recycling Conversations, особенно часть, в которой говорится, что «повторное использование одного диалогового окна для отправки всех ваших сообщений [...] - это как положить все яйца в одну корзину». Возможно, вы сможете восстановить некоторые из этих ситуаций с ошибками, но, вероятно, это приведет к большей сложности вашего кода.

Есть, вероятно, еще несколько аргументов против использования одного разговора для всех рабочих элементов, но я не знаком с ними.

Это не означает, что правильным решением всегда является отдельный разговор для каждого рабочего элемента. Однако, прочитав сообщения Ремуса, его совет кажется звуковым; начните с одного рабочего элемента для разговора, а затем добавьте сложность, если потребуется. (Но, вероятно, ни в коем случае не следует доводить до конца все сообщения в одном разговоре.)