2013-09-03 3 views
4

У нас есть приложение pub/sub, в котором участвует внешний клиент, подписавшийся на издатель веб-роли через тему Azure Service Bus Topic. Наш текущий биллинговый цикл указывает, что мы отправили/получили> 25 тыс. Сообщений, а наша панель указала, что мы отправили < 100. Мы изучаем нашу реализацию и проверяем наши предположения, чтобы понять несоответствие.Azure Service Bus Подписчик регулярно звонит домой?

В рамках нашего расследования мы собрали провода для захвата клиента < => трафик служебной шины на клиентской машине. Мы заметили регулярную картину общения, которую мы не видели в документах и ​​хотели бы лучше понять. Следующий обмен происходит один раз каждые 50 секунд, если в автобусе нет активности:

  1. Клиент нажимает ~ 200B на служебную шину.
  2. Спустя 10 лет служебная шина нажимает клиенту ~ 800B. Клиент регистрирует получение пустого сообщения (определяется с помощью точки останова.)
  3. Клиент немедленно отвечает, нажимая ~ 1000B на служебную шину.

Некоторые соответствующая информация:

  • Это происходит, когда наш веб-роль не активно передавая данные на сервисной шине.
  • После получения достоверного сообщения из роли в Интернете шаблон, описанный выше, не будет повторяться до тех пор, пока не пройдут полные 50 секунд.
  • И клиент, и сервер подключаются к sb: // namespace .servicebus.windows.net через TCP.
  • Наши сообщения приложения являются < 64 KB

Вопросы

  1. Что отвечает за регулярное, 3-пакетов обмена сообщениями мы наблюдаем? Это какая-то живая жизнь?
  2. Выполняет ли каждый из 3-х пакетов как отдельно оплачиваемое сообщение?
  3. Является ли это поведение настраиваемым или иным образом документированным?

EDIT:

Это кодирует принимают сообщения:

private void Listen() 
    { 
     _subscriptionClient.ReceiveAsync().ContinueWith(MessageReceived); 
    } 

    private void MessageReceived(Task<BrokeredMessage> task) 
    { 
     if (task.Status != TaskStatus.Faulted && task.Result != null) 
     { 
      task.Result.CompleteAsync(); 
      // Do some things... 
     } 
     Listen(); 
    } 
+0

Какой код вы используете для получения сообщений? В частности, вы используете OnMessage или цикл с собственным вызовом для получения? Если вы используете Receive, какая перегрузка вы используете? – MikeWo

+0

Я добавил наш код получения на вопрос. Благодаря! –

ответ

7

Я думаю, что вы видите, получающий вызов в фоновом режиме. За кулисами звонки приема используются длительный опрос. Это означает, что они обращаются к конечной точке служебной шины и запрашивают сообщение. Служба Service Bus получает этот запрос, и если у него есть сообщение, оно немедленно вернет его. Если у него нет сообщения, он будет удерживать соединение открытым в течение периода времени в случае поступления сообщения. Если сообщение поступит в течение этого временного интервала, оно будет возвращено клиенту. Если сообщение не доступно к концу временного интервала, клиент отправляет ответ, указывая на то, что сообщения не было (ака, нулевой BrokeredMessage). Если вы вызываете «Получить» без перегрузок (например, вы сделали это), он немедленно сделает другой запрос. Этот цикл продолжается до тех пор, пока не будет получено сообщение.

Таким образом, вы видите, сколько раз клиент запрашивает сообщение, но там его нет. Длительный опрос делает его более приятным, чем то, что стоят очереди хранения Windows Azure, потому что они сразу же вернут нулевой результат, если нет сообщения. Для обеих технологий обычно требуется экспоненциальное отключение для запросов. Есть много примеров того, как это сделать. Это сокращает частоту проверки очереди и позволяет сократить количество транзакций.

Чтобы ответить на ваши вопросы:

  1. Да, это нормально ожидаемое поведение.

  2. Нет, это только одна транзакция. Для служебной шины вы получаете оплату транзакции каждый раз, когда вы помещаете сообщение в очередь, и каждый раз, когда запрашивается сообщение (что может быть немного непрозрачным, если Recieve делает вызовы несколько раз в фоновом режиме). Обратите внимание, что в документах указывается, что вы взимаете плату за каждую транзакцию бездействия (что означает нулевой результат при получении вызова).

  3. Опять же, вы можете реализовать отходную методологию, чтобы вы так часто не попадали в очередь. Еще одно предложение, которое я недавно услышал, - это если у вас есть очередь, которая не видит много трафика, вы также можете проверить глубину очереди, чтобы увидеть, было ли это> 0 перед входом в цикл для обработки, и если вы не получите никаких сообщений от вы можете вернуться к просмотру глубины очереди. Я не пробовал это, и вполне возможно, что вы можете получить дросселирование, если вы слишком часто проверяете глубину очереди, я думаю.

Если это ваши производственные номера, то ваша подписка на самом деле не обрабатывает много сообщений. Вероятно, было бы хорошей идеей отказаться от политики до времени, приемлемого для ожидания до его обработки. Например, если это нормально, что сообщение сидит более 10 минут, то создайте обратный подход, который в конечном итоге будет проверять сообщение каждые 10 минут, а затем, когда он получит один процесс, он и сразу же снова проверяет.

Ох, есть перегрузка получения, которая принимает тайм-аут, но я не 100%, это тайм-аут сервера или местный тайм-аут. Если он локальный, он все равно может выполнять вызовы каждые X секунд для службы. Я думаю, что это основано на значении OperationTimeout, установленном в Factory Factory Settings при создании SubscriptionClient. Тебе придется это проверить.

+0

Это потрясающий ответ, спасибо! Перегрузка 'ReceiveAsync()' с именем serverWaitTime' действует как тайм-аут на стороне сервера. Если я установил это на 15, то образец повторяется каждые 15 секунд, начиная с сервера, отправляющего нулевое сообщение. Спасибо также за мысли о политике отсрочки. Наше приложение таково, что мы должны быть немедленно уведомлены о событиях, которые происходят очень редко, так как я понимаю, что я должен придерживаться механизма долгого опроса? –

+0

Awesome. И теперь я тоже кое-что узнал. :) – MikeWo