Рекомендации по повышению производительности с помощью обмена сообщениями через служебную шину

В этой статье описано использование служебной шины Azure для оптимизации производительности при обмене сообщениями через брокер. В первой части статьи рассматриваются различные механизмы повышения производительности. Во второй части приведены инструкции по эффективному использованию служебной шины для достижения максимальной производительности при определенных условиях.

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

Планирование ресурсов и рекомендации

Как и при работе с любыми техническими ресурсами, разумное планирование — ключ к тому, что Служебная шина Azure будет обеспечивать ожидаемую производительность для вашего приложения. Правильная конфигурация или топология для пространств имен служебная шина зависит от ряда факторов, связанных с архитектурой приложения и способом использования каждого из служебная шина функций.

Ценовая категория

Служебная шина предоставляется в различных ценовых категориях. Рекомендуется выбрать соответствующий уровень для требований приложения.

  • Категория "Стандартный". Подходит для сред разработки и тестирования или сценариев, не требующих высокой пропускной способности, где приложения нечувствительны к регулированию.

  • Уровень "Премиум" — подходит для рабочих сред с различными требованиями к пропускной способности, в которых требуется прогнозируемая задержка и пропускная способность. Дополнительно можно включить автоматическое масштабирование пространств имен Служебной шины категории "Премиум", которое поможет адаптироваться к пиковой пропускной способности.

Примечание.

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

Регулирование не приводит к потере данных. Приложения, использующие пакет SDK служебная шина, могут использовать политику повторных попыток по умолчанию, чтобы гарантировать, что данные в конечном итоге принимаются служебная шина.

Расчет пропускной способности для категории "Премиум"

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

При определении требований к пропускной способности учитывайте данные, отправляемые в Служебную шину (входящий трафик), и данные, получаемые из Служебной шины (исходящий трафик).

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

Тесты производительности

Ниже приведен пример GitHub, который можно запустить, чтобы увидеть ожидаемую пропускную способность, полученную для пространства имен служебная шина. При выполнении тестов производительности мы наблюдали входящий и исходящий трафик примерно на уровне 4 МБ в секунду на единицу обмена сообщениями.

Пример тестирования не использует дополнительные функции, поэтому пропускная способность приложений отличается в зависимости от ваших сценариев.

Рекомендации по вычислениям

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

  1. Сеансы.
  2. Распределение на несколько подписок в одном разделе.
  3. Запуск множества фильтров в одной подписке.
  4. Запланированные сообщения.
  5. Отложенные сообщения.
  6. Транзакции.
  7. Дедупликация и время просмотра.
  8. Пересылка (от одной сущности к другой).

Если в приложении используется любая из перечисленных выше функций, и вы не получаете ожидаемой пропускной способности, вы можете просмотреть метрики использования ЦП и рассмотреть возможность масштабирования служебная шина пространства имен Premium.

Кроме того, можно выполнить автоматическое масштабирование пространства имен Служебной шины с помощью Azure Monitor.

Сегментирование между пространствами имен

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

В этом случае более оптимальным вариантом будет сегментировать сущности (очереди и разделы) в разных пространствах имен Служебной шины категории "Премиум". Можно также рассмотреть сегментирование между разными пространствами имен в разных регионах Azure.

Протоколы

Служебная шина позволяет клиентам отправлять и получать сообщения с помощью трех протоколов.

  1. Расширенный протокол управления очередью сообщений (AMQP)
  2. Протокол SBMP
  3. Протокол HTTP

Протокол AMQP является наиболее эффективным, так как поддерживает подключение к служебной шине. Он также реализует пакетную обработку и предварительную выборку. Если явно не указано иное, в этой статье предполагается использование протокола AMQP или SBMP.

Внимание

Протокол SBMP доступен только для платформы .NET Framework. AMQP используется по умолчанию для .NET Standard.

30 сентября 2026 года мы отставим от поддержки протокола SBMP для Служебная шина Azure, поэтому вы больше не сможете использовать этот протокол после 30 сентября 2026 года. Миграция на последние библиотеки пакета SDK Служебная шина Azure с помощью протокола AMQP, который предлагает критически важные обновления системы безопасности и улучшенные возможности до этой даты.

Дополнительные сведения см. в объявлении о выходе на пенсию в службу поддержки.

Выбор соответствующего пакета SDK для служебной шины .NET

Пакет Azure.Messaging.ServiceBus — это последний пакет SDK Служебной шины Azure для .NET, доступный по состоянию на ноябрь 2020 г. Существует два старых пакета SDK для .NET, которые будут продолжать получать критические исправления ошибок до 30 сентября 2026 года, но мы настоятельно рекомендуем использовать последний пакет SDK. Дополнительные сведения о том, как перейти с более старых пакетов SDK, см. в руководстве по миграции.

Пакет NuGet Основные пространства имен Минимальные платформы Протоколы
Azure.Messaging.ServiceBus (последняя версия) Azure.Messaging.ServiceBus
Azure.Messaging.ServiceBus.Administration
.NET Core 2.0;
.NET Framework 4.6.1
Mono 5.4
универсальная платформа Windows 10.0.16299.
AMQP
HTTP
Microsoft.Azure.ServiceBus Microsoft.Azure.ServiceBus
Microsoft.Azure.ServiceBus.Management
.NET Core 2.0;
.NET Framework 4.6.1
Mono 5.4
универсальная платформа Windows 10.0.16299.
AMQP
HTTP

Дополнительные сведения о минимальной поддержке платформы .NET Standard см. в разделе Поддержка реализации .NET.

30 сентября 2026 г. мы удалим библиотеки пакета SDK Служебная шина Azure WindowsAzure.ServiceBus, Microsoft.Azure.ServiceBus и com.microsoft.azure.servicebus, которые не соответствуют рекомендациям по пакету SDK Azure. Мы также завершим поддержку протокола SBMP, поэтому вы больше не сможете использовать этот протокол после 30 сентября 2026 года. Перейдите в последние библиотеки пакета SDK Azure, которые предлагают критически важные обновления системы безопасности и улучшенные возможности до этой даты.

Хотя старые библиотеки по-прежнему могут использоваться после 30 сентября 2026 года, они больше не будут получать официальную поддержку и обновления от Майкрософт. Дополнительные сведения см. в объявлении о выходе на пенсию в службу поддержки.

Повторное использование фабрик и клиентов

Служебная шина клиенты, взаимодействующие со службой, такие как ServiceBusClient, ServiceBusSender, ServiceBusReceiver и ServiceBusProcessor, должны быть зарегистрированы для внедрения зависимостей как одноэлементные (или экземпляры один раз и общий доступ). ServiceBusClient можно зарегистрировать для внедрения зависимостей с помощью ServiceBusClientBuilderExtensions.

Рекомендуется не закрывать или удалять эти клиенты после отправки или получения каждого сообщения. Закрытие или удаление объектов, зависящих от сущности (ServiceBusSender/получатель/процессор), приводит к разрыву ссылки на службу служебной шины. Удаление ServiceBusClient приведет к разрыву подключения к службе служебной шины.

Это руководство не относится к ServiceBusSessionReceiver, так как его время существования совпадает с самим сеансом. Для приложений, работающих с ServiceBusSessionReceiverэтим, рекомендуется использовать один экземпляр каждого сеанса ServiceBusClient , который охватывает новый ServiceBusSessionReceiver связанный с этим сеансом. После завершения обработки этого сеанса приложение должно удалить связанное ServiceBusSessionReceiver.

Следующее примечание относится ко всем пакетам SDK:

Примечание.

Установка подключения является ресурсоемкой операцией, которую можно исключить, если повторно использовать одну и ту же фабрику или клиентские объекты для нескольких операций. Вы можете безопасно использовать объекты клиента для параллельных асинхронных операций из нескольких потоков.

Параллельные операции

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

Клиент планирует параллельные операции за счет выполнения асинхронных операций. Следующий запрос запускается до завершения предыдущего запроса. Вот пример фрагмента кода асинхронной операции отправки:

var messageOne = new ServiceBusMessage(body);
var messageTwo = new ServiceBusMessage(body);

var sendFirstMessageTask =
    sender.SendMessageAsync(messageOne).ContinueWith(_ =>
    {
        Console.WriteLine("Sent message #1");
    });
var sendSecondMessageTask =
    sender.SendMessageAsync(messageTwo).ContinueWith(_ =>
    {
        Console.WriteLine("Sent message #2");
    });

await Task.WhenAll(sendFirstMessageTask, sendSecondMessageTask);
Console.WriteLine("All messages sent");

Вот пример асинхронной операции получения.

var client = new ServiceBusClient(connectionString);
var options = new ServiceBusProcessorOptions 
{

      AutoCompleteMessages = false,
      MaxConcurrentCalls = 20
};
await using ServiceBusProcessor processor = client.CreateProcessor(queueName,options);
processor.ProcessMessageAsync += MessageHandler;
processor.ProcessErrorAsync += ErrorHandler;

static Task ErrorHandler(ProcessErrorEventArgs args)
{
    Console.WriteLine(args.Exception);
    return Task.CompletedTask;
};

static async Task MessageHandler(ProcessMessageEventArgs args)
{
    Console.WriteLine("Handle message");
    await args.CompleteMessageAsync(args.Message);
}

await processor.StartProcessingAsync();

Режим получения

При создании клиента очереди или подписки вы можете выбрать режим получения: блокировка для просмотра или получение и удаление. По умолчанию используется PeekLockрежим получения. При работе в режиме по умолчанию клиент отправляет запрос на получение сообщения от служебной шины. После получения сообщения клиент отправляет запрос на завершение сообщения.

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

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

Предварительная выборка

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

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

При использовании срока действия блокировки по умолчанию в 60 секунд хорошее значение PrefetchCount составляет 20 раз, чем максимальное значение всех получателей фабрики. Например, фабрика создает трех получателей, каждый из которых может обработать до 10 сообщений в секунду. Количество объектов предварительной выборки не должно превышать 20 × 3 × 10 = 600. По умолчанию установлено значение 0, что означает, PrefetchCount что дополнительные сообщения не извлекаются из службы.

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

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

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

Дополнительные сведения см. в следующих свойствах PrefetchCount:

Значения этих свойств можно задать в ServiceBusReceiverOptions или ServiceBusProcessorOptions.

Предварительная выборка и ПолучениеMessagesAsync

Хотя основные понятия, связанные с выборкой нескольких сообщений, имеют схожую семантику в отношении обработки сообщений в пакете (ReceiveMessagesAsync), есть некоторые небольшие отличия, которые следует учитывать при совместном использовании этих подходов.

Предварительная выборка — это конфигурация (или режим) в ServiceBusReceiver и ReceiveMessagesAsync операция (которая имеет семантику ответа на запрос).

При совместном использовании этих подходов рассмотрим следующие случаи.

  • Предвыборка должна быть больше или равна количеству сообщений, которые ожидается получить в ReceiveMessagesAsync.
  • При выборке в секунду может обрабатываться не более n/3 от общего количества сообщений, где n — продолжительность блокировки по умолчанию.

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

Несколько очередей или разделов

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

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

Уровень используемой службы влияет на прогнозируемость производительности. При выборе уровня "Стандартный " пропускная способность и задержка лучше всего работают над общей мультитенантной инфраструктурой. Другие клиенты в одном кластере могут повлиять на пропускную способность. При выборе уровня "Премиум" вы получаете ресурсы, которые обеспечивают прогнозируемую производительность, а несколько очередей или разделов обрабатываются из этого пула ресурсов. Дополнительные сведения см. в разделе Ценовые категории.

Секционированные пространства имен

При использовании секционированных пространств имен уровня "Премиум" несколько секций с более низкими единицами обмена сообщениями (MU) обеспечивают более высокую производительность по одной секции с более высокими единицами MUS.

Сценарии

Далее описываются стандартные сценарии обмена сообщениями и приводятся рекомендации по настройкам служебной шины. Пропускная способность бывает небольшой (менее 1 сообщения в секунду), средней (1 сообщение в секунду или больше, но не более 100 сообщений в секунду) и высокой (100 сообщений в секунду или больше). Количество клиентов бывает небольшим (5 и меньше), средним (более 5, но не более 20) и большим (более 20).

Очередь с высокой пропускной способностью

Цель: максимально повысить пропускную способность одной очереди. Количество отправителей и получателей: небольшое.

  • Чтобы увеличить общую скорость отправки сообщений в очередь, используйте несколько фабрик обмена сообщениями для создания отправителей. Для каждого отправителя используйте асинхронные операции или разделение на потоки.
  • Чтобы увеличить общую скорость получения сообщений из очереди, используйте несколько фабрик обмена сообщениями для создания получателей.
  • Используйте асинхронные операции, чтобы воспользоваться преимуществами пакетной обработки на стороне клиента.
  • Не отключайте пакетный доступ к хранилищу. Этот доступ повысит общую скорость записи сообщений в очередь.
  • Для количества элементов предварительной выборки установите значение, в 20 раз превышающее максимальную скорость обработки всех получателей фабрики. Это снизит число передач по протоколу клиента служебной шины.

Несколько очередей с высокой пропускной способностью

Цель: максимально повысить общую пропускную способность нескольких очередей. Пропускная способность одной очереди: средняя или высокая.

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

Очередь с небольшой задержкой

Цель: минимизировать время задержки в очереди или разделе. Количество отправителей и получателей: небольшое. Пропускная способность очереди: низкая или средняя.

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

Очередь с большим числом отправителей

Цель: максимально повысить пропускную способность очереди или раздела с большим количеством отправителей. Каждый отправитель отправляет сообщения со средней скоростью. Количество получателей: небольшое.

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

Чтобы повысить пропускную способность, выполните следующие действия.

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

Очередь с большим числом получателей

Цель: максимально повысить скорость получения в очереди или подписке с большим количеством получателей. Каждый получатель получает сообщения со средней скоростью. Количество отправителей: небольшое.

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

Чтобы повысить пропускную способность, следуйте приведенным ниже рекомендациям.

  • Если каждый получатель размещается в отдельном процессе, используйте только одну фабрику для каждого процесса.
  • Получатели могут использовать синхронные и асинхронные операции. Учитывая умеренную скорость получения у отдельного получателя, пакетная обработка на стороне клиента в отношении запросов на завершение не повлияет на пропускную способность получателя.
  • Не отключайте пакетный доступ к хранилищу. Это снизит общую нагрузку на сущность. Это также повысит общую скорость записи сообщений в очередь или раздел.
  • Для количества элементов предварительной выборки установите небольшое значение (например, PrefetchCount = 10). Это позволит избежать ситуации, когда одни получатели простаивают, а другие получают множество кэшированных сообщений.

Раздел с несколькими подписками

Цель: максимально повысить пропускную способность раздела с несколькими подписками. Сообщение получается несколькими подписками. Это означает, что общая скорость получения во всех подписках будет больше, чем скорость отправки. Количество отправителей: небольшое. Получателей в каждой подписке так же немного.

Чтобы повысить пропускную способность, следуйте приведенным ниже рекомендациям.

  • Чтобы увеличить общую скорость отправки сообщений в раздел, используйте несколько фабрик обмена сообщениями для создания отправителей. Для каждого отправителя используйте асинхронные операции или разделение на потоки.
  • Чтобы увеличить общую скорость получения сообщений из подписки, используйте несколько фабрик обмена сообщениями для создания получателей. Для каждого получателя используйте асинхронные операции или разделение на потоки.
  • Используйте асинхронные операции, чтобы воспользоваться преимуществами пакетной обработки на стороне клиента.
  • Не отключайте пакетный доступ к хранилищу. Это повысит общую скорость записи сообщений в раздел.
  • Для количества элементов предварительной выборки установите значение, в 20 раз превышающее максимальную скорость обработки всех получателей фабрики. Это снизит число передач по протоколу клиента служебной шины.

Раздел с большим количеством подписок

Цель: максимально повысить пропускную способность раздела с большим количеством подписок. Сообщение получается несколькими подписками. Это означает, что общая скорость получения во всех подписках будет больше, чем скорость отправки. Количество отправителей: небольшое. Получателей в каждой подписке так же немного.

Разделы с большим количеством подписок обычно обеспечивают низкую общую пропускную способность, если все сообщения направляются во все подписки. Это потому, что получение каждого сообщения выполняется много раз, а все сообщения в разделе и все подписки раздела хранятся в одном хранилище. Предположим, что количество отправителей и число получателей на подписку невелико. Служебная шина поддерживает до 2000 подписок на раздел.

Чтобы максимально повысить пропускную способность, попробуйте выполнить следующие шаги:

  • Используйте асинхронные операции, чтобы воспользоваться преимуществами пакетной обработки на стороне клиента.
  • Не отключайте пакетный доступ к хранилищу. Это повысит общую скорость записи сообщений в раздел.
  • Задайте для предварительной выборки значение 20 раз ожидаемой частоты получения сообщений. Это снизит число передач по протоколу клиента служебной шины.