Azure Storage Queue - сопоставьте ответ на запрос - PullRequest
8 голосов
/ 17 февраля 2012

Когда веб-роль помещает сообщение в очередь хранения, как оно может опросить конкретный коррелированный ответ? Мне бы хотелось, чтобы внутренняя рабочая роль помещала сообщение в очередь ответов с намерением, чтобы вызывающий абонент поднял ответ и пошел оттуда.

Наша цель - использовать Очередь, чтобы переложить тяжелую обработку на внутренние рабочие роли, чтобы обеспечить высокую производительность веб-ролей. Однако мы не хотим отвечать на запросы HTTP до тех пор, пока серверные рабочие не закончат работу и не ответят.

Ответы [ 6 ]

4 голосов
/ 20 февраля 2012

Я на самом деле в процессе принятия аналогичного решения. В моем случае у меня есть служба WCF, работающая в веб-роли, которая должна загружать вычисления в рабочие роли. Когда результат будет вычислен, веб-роль вернет ответ клиенту.

Мои базовые знания структуры данных говорят мне, что я должен избегать использования чего-то, что было спроектировано как очередь без очереди. Это означает, что очередь всегда должна обслуживаться как FIFO. Таким образом, в основном, если используются очереди как для запросов, так и для ответов, потоки, ожидающие возврата данных клиенту, должны будут ждать, пока сообщение вычисления не окажется в «верхней части» очереди ответа, что не является оптимальным. При хранении ответов с использованием таблиц Azure потоки опрашивают сообщения, создавая ненужные издержки

То, что я считаю возможным решением этой проблемы, это использование очереди для запросов. Это позволяет использовать модель конкурирующих потребителей и, таким образом, балансировать нагрузку. Для сообщений, отправляемых в эту очередь, вы устанавливаете свойство correlationId для сообщения. Для ответа используется часть pub / sub ("themes") служебной шины Azure вместе с корреляционным фильтром . Когда ваш сервер обработал запрос, он опубликовал результат в "responseSubject" с correlationId, указанным в исходном запросе. Теперь этот ответ может быть получен вашим клиентом с помощью вызова CreateSubscribetion (извините, я не могу опубликовать более двух ссылок, по-видимому, Google) с использованием этого фильтра корреляции, и он должен получать уведомления при публикации ответа. Обратите внимание, что часть CreateSubscribetion должна быть выполнена один раз в методе OnStart. Затем вы можете выполнить асинхронный BeginRecieve для этой подписки, и роль будет уведомлена в данном обратном вызове, когда будет доступен ответ на один из его запросов. Параметр correlationId сообщит вам, для какого запроса нужен ответ. Итак, ваша последняя задача - вернуть этот ответ потоку, поддерживающему соединение клиента.

Этого можно достичь, создав словарь с корреляционным идентификатором (вероятно, GUID) в качестве ключа и ответами в качестве значения. Когда ваша веб-роль получает запрос, она создает guid, устанавливает его как correlationId, добавляет его в хэш-набор, запускает сообщение в очередь и затем вызывает Monitor.Wait () для объекта Guid. Затем попросите метод recieve, вызванный подпиской на тему, добавить ответ в словарь и затем вызовите Monitor.Notify () для того же объекта guid. Это пробуждает ваш исходный поток запросов, и теперь вы можете вернуть ответ своему клиенту (или что-то в этом роде. По сути, вы просто хотите, чтобы ваш поток спал и не использовал ресурсы во время ожидания)

3 голосов
/ 17 февраля 2012

Для решения на основе служебной шины доступны примеры для реализации шаблона запросов / ответов с очередями и темами (pub-sub)

3 голосов
/ 17 февраля 2012

Очереди на служебной шине Azure имеют гораздо больше возможностей и парадигм, включая возможности pub / sub , которые могут решать проблемы, связанные с обслуживанием очереди в нескольких экземплярах.

Один подход с pub / sub - это иметь одну очередь для запросов и одну для ответов.Каждый запрашивающий экземпляр также подписывался на очередь ответов с фильтром в заголовке, так что он получал бы только ответы, предназначенные для него.Сообщение с запросом, конечно, будет содержать значение, помещенное в заголовок ответа для управления фильтром.

2 голосов
/ 17 февраля 2012

Обратите внимание на использование SignalR между рабочей ролью и клиентом браузера.Таким образом, ваша веб-роль помещает сообщение в очередь и возвращает результат в браузер (что-то простое, например, «ожидание ...») и подключает его к рабочей роли с помощью SignalR.Таким образом, ваша веб-роль выполняет другие функции и не должна ждать результата от асинхронной обработки, а только браузер.

2 голосов
/ 17 февраля 2012

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

Тогда WebRoles просто нужно выполнить поискТаблица с нужным значением correlationId (RowKey) & PartitionKey

1 голос
/ 17 февраля 2012

Нет ничего присущего очередям Windows Azure, которые бы выполняли то, что вы просите. Тем не менее, вы могли бы сделать это самостоятельно довольно легко. Включите идентификатор сообщения (GUID) в отправку в очередь, и, когда обработка будет завершена, попросите рабочего отправить новое сообщение с этим идентификатором сообщения в очередь канала ответа. Ваше веб-приложение может опрашивать эту очередь, чтобы определить, когда обработка для данной команды завершена.

Мы сделали нечто подобное и собираемся использовать что-то вроде SignalR, чтобы помочь ответить клиенту после завершения команд.

...