Секционированные очереди и разделы

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

Примечание.

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

  • Секционирование доступно при создании сущности для всех очередей и разделов для номеров SKU уровня "Базовый" или "Стандартный". Пространство имен может содержать как секционированные, так и не секционированные сущности.
  • Секционирование доступно при создании пространства имен для SKU обмена сообщениями Premium, а все очереди и разделы в этом пространстве имен будут секционированы. Все ранее перенесенные секционированные сущности в пространствах имен Premium будут продолжать работать должным образом.
  • Если секционирование включено в номерах SKU "Базовый" или "Стандартный", мы всегда создадим 16 секций.
  • Если секционирование включено в номере SKU уровня "Премиум", во время создания пространства имен указывается количество секций.

Невозможно изменить параметр секционирования в любом существующем пространстве имен, очереди или разделе; Параметр можно задать только при создании сущности.

Как это работает

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

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

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

При отправке сообщения в секционированную очередь или раздел не взимается дополнительная плата.

Примечание.

Операция просмотра возвращает самое старое сообщение из секции на основе его порядкового номера. Для секционированных сущностей порядковый номер выдается в соответствии с секцией. Дополнительные сведения см. в статье Последовательность и метки времени сообщений.

Использование ключей секции

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

Использование ключа секции

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

В зависимости от сценария в качестве ключа секции используются разные свойства сообщения:

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

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

MessageId: если очередь или раздел были созданы с использованием функции обнаружения дубликатов, а свойства идентификатора сеанса и ключа секции не заданы, то значение свойства идентификатора сообщения выступает в качестве ключа секции. (Клиентские библиотеки Майкрософт автоматически присваивают идентификатор сообщения, если это не делает приложение-отправитель.) В этом случае все копии одного и того же сообщения обрабатываются одним и тем же брокером сообщений. Этот идентификатор позволяет служебной шине находить и исключать повторяющиеся сообщения. Если функция обнаружения дубликатов не включена, служебная шина не рассматривает свойство идентификатора сообщения как ключ секции.

Неиспользование ключа секции

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

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

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

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

Дополнительные разделы

Использование транзакций и секционированных сущностей

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

CommittableTransaction committableTransaction = new CommittableTransaction();
using (TransactionScope ts = new TransactionScope(committableTransaction))
{
    ServiceBusMessage msg = new ServiceBusMessage("This is a message");
    msg.PartitionKey = "myPartitionKey";
    await sender.SendMessageAsync(msg); 
    ts.Complete();
}
committableTransaction.Commit();

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

Использование транзакций в сеансах с секционированными сущностями

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

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

CommittableTransaction committableTransaction = new CommittableTransaction();
using (TransactionScope ts = new TransactionScope(committableTransaction))
{
    ServiceBusMessage msg = new ServiceBusMessage("This is a message");
    msg.SessionId = "mySession";
    await sender.SendMessageAsync(msg); 
    ts.Complete();
}
committableTransaction.Commit();

Автоматическая переадресация сообщений для секционированных сущностей

Служебная шина поддерживает автоматическую переадресацию сообщений в секционированные сущности, из них или между ними. Эту функцию можно включить при создании или обновлении очередей и подписок. Дополнительные сведения см. в разделе Включение пересылки сообщений. Если в сообщении указан ключ секции (SessionId, PartitionKey или MessageId), то этот ключ секции используется для сущности назначения.

Рекомендации и советы

  • Функции обеспечения высокого уровня согласованности. Если сущность использует такие функции, как сеансы, обнаружение дубликатов или явное управление ключом секционирования, то операции обмена сообщениями всегда направляются в конкретную секцию. При большом трафике в каком-либо из разделов или неработоспособности базового хранилища эти операции не выполняются и доступность снижается. В целом согласованность по-прежнему намного выше, чем непартийные сущности; В отличие от всего трафика, возникают проблемы только подмножества трафика. Дополнительные сведения см. в этом обсуждении доступности и целостности.
  • Управление. Операции создания, обновления и удаления должны быть выполнены для всех секций сущности. Если какая-то секция неработоспособна, это может привести к сбою данных операций. Для операции получения требуется сведение таких данных, как количество сообщений, по всем разделам. Если какая-либо секция неработоспособна, отображается ограниченный статус доступности сущности.
  • Сценарии сообщений с низким объемом: для таких сценариев, особенно при использовании протокола HTTP, может потребоваться выполнить несколько операций получения, чтобы получить все сообщения. Для запросов на получение внешний интерфейс осуществляет получение во всех секциях и кэширует все полученные ответы. Последующий запрос на получение в том же соединении будет выгодна от этого кэширования и задержки получения ниже. Однако если у вас несколько подключений или используется HTTP, для каждого запроса устанавливается новое подключение. Таким образом, нет никаких гарантий того, что он будет приземляться на одном узле. Если все имеющиеся сообщения блокируются и кэшируются в другом внешнем интерфейсе, операция получения возвращает значение NULL. Когда в конечном итоге срок действия сообщений истекает, их снова можно получать. Рекомендуется выполнить проверку активности HTTP. При использовании секционирования в сценариях с низким объемом операции получения могут занять больше времени, чем ожидалось. Поэтому мы не рекомендуем использовать секционирования в подобных сценариях. Для повышения производительности удалите все существующие секционированные сущности и создайте их заново, отключив секционирование.
  • Обзор/просмотр сообщений: операция просмотра не всегда возвращает число запрошенных сообщений. На это есть две распространенные причины. Одна из причин заключается в том, что совокупный размер коллекции сообщений превышает максимальный размер. Другая причина заключается в том, что в секционированных очередях или разделах может отсутствовать достаточное количество сообщений для возврата запрошенного количества сообщений. Как правило, если приложению требуется совершить обзор/просмотреть определенное количество сообщений, оно должно вызывать операцию просмотра итерационно, пока не получит желаемое количество сообщений или пока не закончатся сообщения, которые можно просмотреть. Дополнительные сведения, включая примеры кода, см. в разделе Просмотр сообщений.

Ограничения секционированных сущностей

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

  • Для секционированных пространств имен класса Premium размер сообщения ограничен 1 МБ при отправке сообщений по отдельности, а размер пакета ограничен 1 МБ при отправке сообщений в пакете.
  • Секционированные очереди и разделы не поддерживают отправку сообщений, принадлежащих разным сеансам, в одной транзакции.
  • служебная шина в настоящее время позволяет до 100 секционированных очередей или разделов на пространство имен для SKU "Базовый" и "Стандартный". Каждая секционированная очередь или раздел учитывается в квоте в 10 000 сущностей на пространство имен.

Следующие шаги

Секционирование можно включить с помощью портала Azure, PowerShell, интерфейса командной строки, шаблона Диспетчера ресурсов, .NET, Java, Python и JavaScript. Дополнительные сведения см. в разделе "Включение секционирования" ("Базовый" или "Стандартный")

Ознакомьтесь с основными понятиями спецификации расширенного протокола очереди сообщений (AMQP) 1.0 в руководстве по протоколу AMQP 1.0.