Статьи

Все, что нужно знать о службе обмена сообщениями Azure Service Bus (часть 3)


Если вы оставались с нами в этом путешествии, вы уже знаете, что существует много информации об обмене сообщениями через Azure Service Bus. Несмотря на то, что мы проделали большую часть наземных работ, о служебной шине еще многое нужно знать. В этой 3-ей и последней части мы рассмотрим некоторые из расширенных функций и шаблонов обмена сообщениями, а также безопасность и лучшие практики. Вы можете легко набрать скорость с областями, уже охваченными в  Части 1 и  Части 2 .

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

·  Пакетная обработка

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

·  Транзакции

·  Мертвая надпись

·  Авто-пересылка

·  Безопасность

·  Лучшие практики


Пакетная обработка

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

Также важно отметить, что пакетирование доступно только через протокол обмена сообщениями служебной шины (SBMP). Прежде чем вы начнете опускаться до факта, что HTTP не был упомянут, понимая, что при использовании клиентской библиотеки Service Bus по умолчанию вы используете SBMP, если вы явно не установите протокол HTTP.

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

Сторона клиента

Отправка сообщений в пакетном режиме

Напоминание, чтобы сосредоточиться на теме, обработка исключений была удалена. Помните, как .Net обрабатывает исключения, когда дело касается  задач .

Как вы можете ожидать, с отправкой пакета сообщений не так много:

List<BrokeredMessage> messages = new List<BrokeredMessage>();
BrokeredMessage taylorSwift = new BrokeredMessage("Taylor Swift Request");
BrokeredMessage justinBieber = new BrokeredMessage("Justin Bieber Request");
BrokeredMessage britneySpears = new BrokeredMessage("Britney Spears Request");

messages.Add(taylorSwift);
messages.Add(justinBieber);
messages.Add(britneySpears);

MessageSender messageSender = messagingFactory.CreateMessageSender(_topicName);

await messageSender.SendBatchAsync(messages);

Тем не менее, пакет сообщений также привязан к максимальному размеру сообщения (см.  Часть 1  относительно размера сообщения). Следовательно, пакетная обработка обрезает сообщения, которые превышают этот предел, и помещает их в качестве первых сообщений следующей партии. Кроме того, внутренне пакетная обработка обрабатывается на основе свойства BatchFlushInterval в MessagingFactory и по умолчанию имеет интервал 20 мс. Это может быть изменено, чтобы быть более эффективным, когда ситуация требует этого, изменив это свойство при создании MessagingFactory (см.  «Советы и  рекомендации» для точной настройки сценариев).

Это повлияет на всех клиентов, которые создают из этого MessagingFactory:

MessagingFactorySettings messagingFactorySettings = new MessagingFactorySettings
{
     NetMessagingTransportSettings = {BatchFlushInterval = TimeSpan.FromMilliseconds(100)}
};

MessagingFactory messagingFactory = MessagingFactory.Create(uriAddress, messagingFactorySettings );

Теперь этот параметр будет влиять на любой клиент (MessageSender, MessageReceiver, QueueClient, TopicClient, SubscriptionClient), созданный этим MessagingFactory. Для обновления на MessagingFactory см.  Часть 1 . Возможно, вы читаете этих клиентов и думаете: «Подождите, разве мы не говорим об отправке!» Это верно, но интервал пакетной очистки влияет как на отправку, так и на завершение сообщения, что самое время посмотреть на получение.

Получение сообщений партиями

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

MessageReceiver messageReceiver =  await _messagingFactory.CreateMessageReceiverAsync(queueName);
try
{
     while (!cancellationToken.IsCancellationRequested)
     {
         IEnumerable<BrokeredMessage> messages = await messageReceiver.ReceiveBatchAsync(batchCount).ConfigureAwait(false);
         if (messages != null)
         {
              foreach (var brokeredMessage in messages)
              {
                  if (brokeredMessage.LockedUntilUtc == DateTime.UtcNow) await brokeredMessage.RenewLockAsync();
                  await ProcessAndReleaseMessageAsync(brokeredMessage);
              }    
         }
                     
          await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
     }
}
catch (Exception ex)
{
     Console.WriteLine(ex.Message);
     throw;
}

private async Task ProcessAndReleaseMessageAsync(BrokeredMessage message)
{
     MessageProcessingAction action = MessageProcessingAction.Abandon;

    try
     {
         //Process Message

        action = MessageProcessingAction.Complete;
         await UpdateMessageState(message, action);
     }
     catch (Exception ex)
     {
         //log error
     }
     finally
     {
         //if something fails update with abandon    
         //C# 6.0 allows await calls in a finally blocks
         UpdateMessageState(message, action);
     }
}

private async Task UpdateMessageState(BrokeredMessage message, MessageProcessingAction action)
{
     switch (action)
     {
         case MessageProcessingAction.Complete:
               await message.CompleteAsync();
               break;
         case MessageProcessingAction.Abandon:
               await message.AbandonAsync();
               break;
         case MessageProcessingAction.Deadletter:
               await message.DeadLetterAsync();
               break;
         default:
               await message.AbandonAsync();
               break;
     }

}

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

Управление пакетной обработкой хранилища Azure

До сих пор вся наша пакетная обработка происходила на стороне клиента. Однако когда служба Service Bus получает сообщения, она имеет возможность пакетировать эти сообщения при отправке во внутреннее хранилище. Это относится только к операциям отправки и завершения. Для того, чтобы служебная шина могла сохранять постоянство своих сообщений во внутреннем хранилище, требуется только установить флаг EnableBatchedOperations в очереди, теме или подписке.

TopicDescription topicDescription = new TopicDescription(topicPath)
{
    EnableBatchedOperations = true
};

Это может быть предоставлено либо при создании темы (см.  Раздел « Создание тем» ), либо даже при обновлении существующей темы. Опять же, это всего лишь пример предоставления Темы, но также является доступным свойством для Очереди и Подписки.

Вы можете прочитать больше о пакетировании в этом   источнике MSDN .

Пакетирование является одной из тех областей, о которых обычно говорят, когда речь идет об улучшениях в эффективности приложений. Однако не все формы пакетирования эффективны, и я обсуждаю это в разделе «  Лучшие практики» . Еще одна особенность служебной шины, которая может непосредственно способствовать повышению эффективности и внести существенный вклад в эту область, — это предварительная выборка, тесно связанная с тем, что мы обсуждали. Мне нравится думать об этом как о более активной форме дозирования.

Предзагрузка

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

Вы не только увидите немедленное улучшение эффективности обработки доступных сообщений, поскольку вы получаете их из локального кэша, но и нет никаких изменений интерфейса, которые вам нужно вносить в способ получения сообщений. Единственное изменение происходит при создании клиента-получателя (QueueClient, SubscriptionClient или MessageReceiver) при настройке свойства PrefetchCount. Это также может быть установлено на уровне MessagingFactory и каскадно ко всем клиентам, созданным на фабрике.

MessageReceiver messageReceiver = await _messagingFactory.CreateMessageReceiverAsync(queueName);
messageReceiver.PrefetchCount = 200;

Счетчик PrefetchCount не является произвольным числом, но должен рассчитываться на основе рекомендованной Microsoft формулы (в качестве отправной точки). Формула в 20 раз превышает общее количество сообщений, которое один получатель может обработать в секунду. Так что если получатель может обрабатывать 5 сообщений / сек = 20 × 5 = 100 PrefetchCount. Если установить это на уровне MessagingFactory, число должно быть умножено на количество клиентов, создаваемых фабрикой. Поэтому может быть проще установить на уровне клиента, если число клиентов неизвестно.

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

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

Time taken to get message: 1126 in ms.
Time taken to get message: 79 in ms.
Time taken to get message: 157 in ms.

Но после настройки PrefetchCount

Time taken to get message: 750 in ms.
Time taken to get message: 0 in ms.
Time taken to get message: 0 in ms.

Я не могу объяснить, почему накладные расходы выше для первого сообщения первого пакета, где не происходит предварительной выборки. Однако, когда Prefetch включен, он будет иметь более высокие издержки для первого сообщения из-за увеличенного размера сообщения. Но, очевидно, мы можем увидеть падение во всех последующих полученных сообщениях. А теперь представьте это на большом количестве сообщений.

операции

Мы можем объединить наши Сервисные операции в транзакции, чтобы обеспечить сценарий «все или ничего», когда речь идет о выполнении ряда операций. Возьмем для примера необходимость убедиться, что либо все сообщения отправлены, либо нет. Например, если бы мы использовали шаблон корреляции, установив  свойство CorrelationId  для сообщения в сочетании с CorrelationFilter для подписки, мы могли бы захотеть убедиться, что все сообщенные сообщения доставлены или отсутствуют.

Как и в случае, когда у вас было несколько сообщений:

MessagingFactory factory = MessagingFactory.CreateFromConnectionString(AccountInfo.ConnectionString);
MessageSender messageSender = factory.CreateMessageSender(_topicName);

BrokeredMessage justinBieber = new BrokeredMessage() {CorrelationId = "Music Awards"};
justinBieber.Properties.Add("RequestedSinger", "Justin Bieber");

BrokeredMessage taylorSwift = new BrokeredMessage() {CorrelationId = "Music Awards"};
taylorSwift.Properties.Add("RequestedSinger", "Taylor Swifht");

BrokeredMessage britneySpears = new BrokeredMessage() {CorrelationId = "Music Awards"};
britneySpears.Properties.Add("RequestedSinger", "Britney Spears");

List<BrokeredMessage> messages = new List<BrokeredMessage>() {justinBieber, taylorSwift, britneySpears};

И вы хотели, чтобы они все отправили или ни одного;

using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))  {
    foreach (BrokeredMessage message in messages)
    {
        messageSender.SendAsync(message);
    }

     transaction.Complete();
}

Если возникнет исключение, ни одно из сообщений не будет опубликовано в теме. Обратите внимание на TransactionScope, который принимает перечисление TransactionScopeAsyncFlowOption. Это позволяет окружающим транзакциям проходить через продолжения потока, как описано на этой   странице MSDN .

Мертвая надпись

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

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

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

Неявное обслуживание Dead-Lettering

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

SubscriptionDescription subscription = new SubscriptionDescription(topicPath, subscriptionName)
{
    DefaultMessageTimeToLive = TimeSpan.FromSeconds(30),
    LockDuration = TimeSpan.FromSeconds(90),
    EnableDeadLetteringOnMessageExpiration = true,
    EnableDeadLetteringOnFilterEvaluationExceptions = true
};

Примечание . Показано SubscriptionDescription, но также применимо к QueueDescription и TopicDescription.

Здесь вы увидите, что на самом деле может быть установлено не только одно свойство, связанное с мертвой буквой. EnableDeadLetteringOnMessageExpiration позволяет службе служебной шины перемещать сообщения, срок действия которых истек, на основе их свойства TimeToLive. В то время как EnableDeadLetteringOnFilterEvaluationExceptions разрешает захват сообщений, когда выбрасывает условие правила подписок и исключение при оценке сообщения. Существует также еще один момент, когда служба неявно перемещает сообщение в очередь недоставленных сообщений. Это когда количество доставок сообщения равно свойству MaxDeliveryCount очереди, темы или подписки.

Явная потребительская надпись

Помимо службы, перемещающей сообщения в очередь недоставленных сообщений, приложение-потребитель имеет возможность определить, следует ли переместить сообщение в очередь недоставленных сообщений. Это легко сделать, вызвав метод Abandon / AbandonAysnc для сообщения. Вы на самом деле уже видели это, когда мы получали и обрабатывали сообщения в ряде различных примеров:

await message.DeadLetterAsync();

или укажите причину и описание:

await message.DeadLetterAsync("Popularity", "Number of request for singer has not reached minimum");

Получение мертвых сообщений

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

string deadLetterPath = SubscriptionClient.FormatDeadLetterPath(topicPath, subscriptionName);
MessageReceiver messageReceiver = await _messagingFactory.CreateMessageReceiverAsync(deadLetterPath);

Обратите внимание, что мы вызываем статический   метод FormatDeadLetterPath из  SubscriptionClient .

Приобретение MessageReceiver должно выглядеть знакомо, и отсюда мы можем получать любые сообщения в очереди Dead-Letter.

Авто-Forwarding

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

Понимаете, реализовать Auto-Forwarding очень просто. Это просто установка   свойства ForwardTo для очереди, темы и подписки. Он делает именно то, на что это похоже, автоматически пересылает полученные сообщения на пункт назначения. Однако мощь этой функции демонстрирует использование автоматической пересылки в вашей архитектуре. Давайте рассмотрим это немного ближе, чтобы понять как.

TopicDescription topic = new TopicDescription(topicPath);
await _namespaceManager.CreateTopicAsync(topic);

SubscriptionDescription subscription = new SubscriptionDescription(topicPath, subscriptionName)
{
    ForwardTo = topic.Path,
};

await _namespaceManager.CreateSubscriptionAsync(subscription, ruleDescription);

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

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

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

With our example, we could have hundreds or thousands of local distribution centers.  Currently a topic’s subscription limit is 2,000.  Therefore, instead of requiring a single topic to process messages of upwards of 2,000 subscriptions significantly reducing throughput, we can disperse that workload across 5 subscriptions that in turn will forward to a topic who will be responsible for a smaller subset of local distribution center subscriptions.  Not only will we achieve an exponentially better throughput because we have reduced the number of subscriptions to process against for a single topic, but we also will remove the subscription limitation of 2,000.

This also can demonstrate the scale out capabilities that Auto-Forwarding provides.  If a new local or regional distribution center comes online, the ease in which to add that subscription to the proper topic and update/add rules to account for the new distribution center is fairly straight forward.

Auto-Forward coupled with Rules is one of the most powerful Service Bus features turning Service Bus from a host of queues and topics to a smart hub that manages the flow of messages.


Security

In Part 1 we actually had a quick taste of some of the security protocols that Service Bus provides out-of-the-box in the form of a TokenProvider.  The TokenProvider is the governing piece that will allow us to implement the form of security controls that we want.  Whether that be in the form of Shared Access Signatures which we have talked about at length for other services, or backed by a Access Control Service such as Identity Providers (Windows Live ID, Google, Yahoo…etc.) or Federation services such as AD FS 2.0.

However, that being said, you can read Microsoft’s view on Service Bus security and how they have recently (Sept. 2014) changed it to heavily favor Shared Access Signatures (SAS) here.  Therefore, we will also scope this security discussion around Shared Access Signatures as well.  At the end of this portion, I’ll make some additional information available for those interested in other security controls.

If you have been following my previous topics on Azure Services such as Blob and Table Storage just to name a few, you will be somewhat familiar with the concept of Shared Access Signatures.  If you are not, read up on the MSDN version.  A Shared Access Signature (SAS) provides a granular level of access control to specific resources. They allow you to specify what access rights a consumer has for a specific resource for a given amount time.  As in other Azure services the Shared Access Signature is a string that is made up of the details of the access along with a hash that is used by the Azure service to authenticate the Shared Access Signature being passed to the service.

Instead of repetitiously defining exactly what rights a signature grants to a consumer of the Shared Access Signature, we can use predefined policies that are stored on Azure.  These policies act as templates for providing privileges to a specific Service Bus resource. as well as allow us to easily revoke access by removing individual stored policies.  The resources that we can provide access to constitute two levels within the Service Bus; the Namespace and Entities.

The Namespace resource is the same one we define in Part 1 while the entities constitute resources such as Topics and Queues.  However, since programmatically creating stored policies at the Service Bus Namespace requires working with uploaded Certificates through the Azure Portal, I am focus mainly on creating Shared Access Policies for entities.  However, if you are interesting in learning about uploading a certificate and creating Namespace Shared Access Policies you can check out this MSDN article and the related links on that site.

However, you can easily create a Namespace level Shared Access Policy through the portal by going to the Configure section under the Service Bus Namespace you created as shown below:

It is here in the portal that you can create Namespace level policies that can provide any combination of Manage, Send, or Listen privileges. external client.

Creating Stored Policies

Following the Principle of Least Privilege, let’s look at creating and saving stored Policies at the entity level.  Then we can look at consuming those policies to create a Shared Access Signature which can be used or provided to a consumer.  When it comes to creating a policy there isn’t much to it.

TopicDescription topicDescription = await _operations.CreateOrRetrieveTopicAsync(topicPath);
topicDescription.Authorization.Add(new SharedAccessAuthorizationRule(“SendSingerRequests”,
SharedAccessAuthorizationRule.GenerateRandomKey(), new[] { AccessRights.Send ));

await _namespaceManager.UpdateTopicAsync(topicDescription );

Again, CreateOrRetrieveTopicAsync is just a helper method to either pass back an existing TopicDescription or create it if it doesn’t exist.  From there we simply are adding a new AuthorizationRule as a SharedAccessAuthorizationRule to the Authorization property of the TopicDescription.  This SharedAccessAuthorizationRule is created by providing the name of the policy as well as an array of AccessRights enumerations.

In this case we are creating a Stored Policy with the name “SendSingerRequests” with the right to send on the topic which we can see if we navigate to the Topic under the Namespace for the Service Bus in the Azure portal:

Now that we have created a stored policy for a Topic, we can easily generate a Shared Access Signature which can be provided to a consumer for authenticity.

Generating Shared Access Signatures from Policies

Generating a Shared Access signature just requires the service knowing the endpoint URI, policy name and either the primary or secondary key along with a timespan of how long the Shared Access Signature is valid.

Uri serviceUri = ServiceBusEnvironment.CreateServiceUri("sb", "shopit", string.Empty);
string generatedSaS = SharedAccessSignatureTokenProvider.GetSharedAccessSignature(
        policyName,
        policyKey,
        serviceUri.ToString().Trim('/'),
        TimeSpan.FromHours(8));

A lot of this should already look very familiar to you back in Part 1 where we showed various ways to create the NamespaceManager.  From here we can provide the string Shared Access Signature to a consumer to use in creating their TokenProvider.

Consuming a Shared Access Signature

Having the generated Shared Access Signature in hand, we can provide it to a consumer that might want to send messages to our Topic which they can go about consuming it when they generate a TokenProvider:

TokenProvider tokenProvider = TokenProvider.CreateSharedAccessSignatureTokenProvider(generatedSaS);

MessagingFactory factory = MessagingFactory.Create("sb://<yourNamespace>.servicebus.windows.net", tokenProvider);
MessageSender messageSender = factory.CreateMessageSender(_topicName);

From here they can send messages to the topic for as long as the Time-To-Live was set for the Shared Access Signature when it was generated above (example of 8 hrs.).

Additional Resources

As I mentioned, there is other Access Control Services available Identity Providers, Federation services to name a couple.  Below are some additional resources for more information on those extended areas of access control:

1.  http://blogs.msdn.com/b/jimoneil/archive/2012/04/24/fun-with-the-service-bus-part-1.aspx

2.  http://azure.microsoft.com/en-us/documentation/articles/active-directory-dotnet-how-to-use-access-control/

3.  http://blogs.msdn.com/b/servicebus/archive/2014/09/03/change-to-azure-service-bus-portal-default-authentication-mechanism-for-service-bus-namespaces-now-sas.aspx

4.  http://www.developerfusion.com/article/121561/integrating-active-directory-into-azure/

Best Practices

Protocols

There are number of protocols that the Service Bus can operate under.  By default the SDK utilizes the Service Bus Messaging Protocol which provides the best performance and features.  Unless yours or your consumers operations are limited to HTTP/S, then utilize the SBMP.  Check out this article for more information on available protocols.

Factories, Clients and Abstractions

I haven’t mentioned this before, but there is a significant amount of overhead when creating factories such as MessagingFactory and clients such as QueueClient, TopicClient and SubscriptionClient as well as their MessageSender and MessageReceiver abstractions.  Therefore, when creating these resource, attempt to fully utilize them without needlessly recreating.  An example would be recreating a MessageSender for every message that you need to send.

Furthermore, understand that when you terminate a factory such as a MessagingFactory, it also closes all the entities it was responsible for creating.

Abstractions

When you absolutely don’t need to utilize the direct clients such as QueueClient, TopicClient and SubscriptionClient use their abstractions MessageSender and MessageReceiver.  Doing so, you don’t need to worry about whether you sending to a queue or to a topic, receiving from a queue or a subscription.

Operations

At the beginning of this series I mentioned it, but I thought it was worth repeating the importance of taking advantage and utilizing the asynchronous operations provided by the SDK when possible.  There is a significant performance improvement when using the provided asynchronous methods.

Message Size

Finally, the default of a message size is 256kb total which includes both the body and properties (system and custom) with a max property size of 64kb.  While conceivably you can increase this size, proceed with caution.  If there is any reason or possibility that a future requirement or current client that will need to utilize HTTP as their protocol, this can have a negative impact. Service Bus messages are designed for efficiency and Service Bus messages are designed to be compatible with  HTTP header size specifications

Batching

It’s not quite 1 or 0, true or false, black or white when it comes to batching and being efficient.  Batching is only available for send and completion operations But here are some performance considerations.

Low Throughput – Disable batching by setting the batch flush interval to 0.

High Throughput – Set the BatchFlushInterval to 50ms

Multiple Senders/Receivers – When using multiple senders/receivers, set the BatchFlushInterval to 100ms.

To adjust the flush interval for batch processing, you set the BatchFlushInternval property on the MessagingFactorySettings object that is then passed into the creation of a MessagingFactory (see Batching):

Conclusion

This has been one long series on a very large Azure Service that I wish I could say I have covered every corner regarding the service, but the truth is that there is just so much to talk about that it would take more than a 3 part series to do that.  However, be assured that you have been shown a vast majority of the features of Azure Service Bus.  Now, there are closely related topics that are services built on top of Azure Service Bus such as Event and Notification hub as well as service bus patterns that weren’t covered such as request-response patterns just to name a few.  But, hopefully the information you have garnished from the three part series will teach you more than just the basics of using Azure Service Bus.

If you liked this post, follow me @maxrmccarty

Everything You Need to Know About Azure Service Bus Part 3 first appeared on LockMeDown.com