Skip to content
May 3, 2012 / ahriman hpc mode

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

Одним из сценариев использования очередей Windows Azure является использование алгоритма, называющегося Simple Capped Exponential Back-Off for Queues. За длинным и мудрёным названием скрывается в общем приближении не очень хитрая суть.

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

Итак, типичным паттерном для работы с очередями (и не только Windows Azure) является опрос очереди в бесконечном цикле, при этом каждую итерацию обработчик сначала некоторое время спит (например, 10 секунд), после чего опрашивает очередь, после чего опять засыпает. Чем это плохо? В принципе ничем, за исключением того, что алгоритм этот прост как дважды два, но его можно немного усовершенствовать. Привести это может к тому, что уменьшится количество транзакций, а, соответственно, вместо с уменьшением количества транзакций уменьшится количество трафика и общая стоимость.

Для примера давайте посмотрим, как опрашивается очередь в стандартном случае.

while (true)
{
CloudQueueMessage msg = queue.GetMessage();
if (msg != null)
{
string msgContent = msg.AsString;
//Работа по обработке сообщения
queue.DeleteMessage(msg);
}
else
{
System.Threading.Thread.Sleep(1000);
}
}

Пример прозрачен – в бесконечном цикле сначала происходит забор сообщения из очереди и, если сообщение не равно null, осуществляется его обработка. Если же Null – обработчик спит.

Обсуждаемый же алгоритм можно реализовать несколькими способами – в зависимости от того, по сути, как нравится разработчику.

Способ простой.

int intervalFloor = 1; int currentInterval = intervalFloor; int intervalCeiling= 60; CloudStorageAccount account = CloudStorageAccount.DevelopmentStorageAccount; CloudQueueClient queueClient = account.CreateCloudQueueClient(); CloudQueue queue = queueClient.GetQueueReference("myqueue"); queue.CreateIfNotExist(); while (true) CloudQueueMessage msg = queue.GetMessage(); if (msg != null) { queue.DeleteMessage(msg); if (useGradualDecrease) if (currentInterval > intervalFloor) currentInterval = currentInterval /2;

Trace.WriteLine(string.Format("Интервал стал равен {0} секунд", currentInterval)); else currentInterval = intervalFloor; else currentInterval = intervalFloor; } else { if (currentInterval < intervalCeiling) currentInterval = currentInterval * 2;

Trace.WriteLine(string.Format("Обработчик заснул на {0} секунд", currentInterval * 1000)); Thread.Sleep(currentInterval * 1000); } }

Изначально интервал опроса, например, 3 секунды. Если опрос ничего не возвращает, интервал опроса будет умножен на 2 – до 6 секунд, затем до 12 и так далее, до максимального значения (60 секунд). Часто пользуются изначальным интервалом в 2 секунды, однако это не критично.

Как только опрос возвращает сообщение, интервал опроса проверяется и уменьшается вдвое – если это 6 секунд, то до 3, если 4 секунды, то до 2.

Аналогично, но немного более красиво, можно описать другим кодом. 

int intervalFloor = 1;

int currentInterval = intervalFloor;

int exponent = 2;

int intervalCeiling= 60;

CloudStorageAccount account = CloudStorageAccount.DevelopmentStorageAccount;

CloudQueueClient queueClient = account.CreateCloudQueueClient();

CloudQueue queue = queueClient.GetQueueReference("myqueue");

queue.CreateIfNotExist();

while (true) { var msg = queue.GetMessage(); if (msg != null) { queue.DeleteMessage(msg); currentInterval = intervalFloor; Trace.WriteLine(string.Format("Интервал стал равен {0} секунд", currentInterval )); } else { Trace.WriteLine(string.Format("Обработчик заснул на {0} секунд", currentInterval*1000)); Thread.Sleep(currentInterval*1000); currentInterval = Math.Min(intervalCeiling, currentInterval * exponent); } }

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

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: