Хранилище очередей Azure не отправляет сообщение очереди

Я использую лазурное хранилище очереди для отправки электронных писем. Электронные письма хранятся в хранилище очереди, и очередь отправляет 20 писем за раз.

//Checks for messages inn the queue
foreach (CloudQueueMessage msgin sendEmailQueue.GetMessages(20, TimeSpan.FromSeconds(50)))
   {
        ProcessQueueMessage(msg);

   }

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

private void ProcessQueueMessage(CloudQueueMessage msg)
{
  try
  {
    //We try to send an email
    SendEmail(emailRowInMessageTable, htmlMessageBodyRef, textMessageBodyRef);

  } catch (SmtpException e)
  {
    string err = e.Message;

    //When an error occurs we check to see if the message failed to send certain no. of      
      times
    if (msg.DequeueCount > 10)
    {
      //We delete the message from queue
      sendEmailQueue.DeleteMessage(msg);

      return;
    } else
    {
      //delete from top of queue
      sendEmailQueue.DeleteMessage(msg);

      //insert into end of queue
      sendEmailQueue.AddMessage(msg);

      return;
    }
  }
 }

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

Каким было бы лучшее решение в этой ситуации?


person Kaladin    schedule 09.01.2014    source источник


Ответы (2)


На самом деле вам не нужно удалять сообщение и добавлять его. По истечении visibility timeout периода сообщения (в вашем случае 50 секунд) оно автоматически возвращается в очередь. Таким образом, ваша логика DequeueCount также будет работать, когда одно и то же сообщение будет исключено из очереди и снова поставлено в очередь.

Обратите внимание, что очереди Windows Azure - это лучший FIFO ... поэтому это не всегда необходимо, и что сообщения будут выбираться в зависимости от времени, когда они были добавлены. Вы могли бы сделать несколько вещей:

  • Уменьшите количество повторных попыток (в настоящее время у вас их 10, вы можете уменьшить их до 5) или
  • Проверьте фактическое исключение. Если процесс завершился неудачно из-за неправильных учетных данных, он завершится ошибкой в ​​следующий раз и в следующий раз после этого. Нет смысла повторять это сообщение. Вы можете просто переместить это сообщение в подозрительную очередь, чтобы потом проверить его.
person Gaurav Mantri    schedule 09.01.2014
comment
Насколько я понимаю, если первые 30 сообщений блокируют очередь (т.е. неправильный пароль), следующие 20 правильных сообщений не будут отправлены, поскольку первые 30 сообщений всегда находятся в очереди. Вот почему я хочу удалить первые 30 сообщений и добавить их в конец очереди, чтобы можно было отправить 20 правильных сообщений. - person Kaladin; 09.01.2014
comment
Обновил свой ответ. HTH. - person Gaurav Mantri; 09.01.2014
comment
Мы уже проверяем наличие плохих сообщений, таких как неправильный идентификатор электронной почты и т. Д., И перемещаем их в подозрительную очередь. Неправильный пароль был просто примером, я больше думал о том, когда серверы SMTP не работают и т. Д. Я объясню наше решение более подробно. У нас есть несколько SMTP-серверов, и мы решили использовать две очереди для обработки сообщения. Первый попытается отправить сообщение 5 раз, а в случае неудачи переместит его во вторую очередь. Первая очередь будет проверять сообщение каждую минуту, а во второй очереди мы хотим проверять сообщение каждые 60 минут. - person Kaladin; 13.01.2014
comment
.... Мы хотим использовать для этого только одну рабочую роль. Есть идеи о том, какое будет лучшее решение? Спасибо за помощь, кстати. - person Kaladin; 13.01.2014
comment
Вы, безусловно, можете сделать это в одной рабочей роли. Похоже, вам нужна функция типа cron задания, с помощью которой вы можете запускать 2 задания: одно срабатывает каждую минуту, а другое - каждые 60 минут. Взгляните на библиотеку Quartz.net (quartznet.sourceforge.net). Вы также можете найти этот пост полезным для реализации запланированных задач: gauravmantri.com/2013/01/23/. HTH. - person Gaurav Mantri; 13.01.2014

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

Здесь используется структура: http://www.31a2ba2a-b718-11dc-8314-0800200c9a66.com/2010/12/running-multiple-threads-on-windows.html для запуска нескольких потоков внутри одной рабочей роли.

person Kaladin    schedule 15.01.2014