2012-06-07 2 views
6

Можно запустить поток из метода WebRole.cs OnStart() таким образом, чтобы мы могли получить к нему доступ через страницу aspx для выполнения фоновой работы? Я знаю, что правильный способ сделать это - использовать роль рабочего, но я хочу поддерживать текущие расходы как можно ниже.Фоновая тема в Azure Web Role

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

+0

Как бы это снизить эксплуатационные расходы? Каким образом вы хотите отличаться от одного единственного сервера параллельного доступа? – Paparazzi

+3

@Blam - Запуск фоновых задач в роли Web позволяет объединить операции в один набор экземпляров виртуальной машины. Это в отличие от размещения фоновых операций в отдельном наборе экземпляров ролей. Объединение в одну роль позволит сэкономить затраты, поскольку каждая роль должна иметь хотя бы один экземпляр. Для малообъемных сайтов это очень экономичная архитектура.Если существует риск того, что фоновые задачи будут голодать на веб-сайте, или необходимо отдельно масштабировать внешние и фоновые задачи (или иметь разные потребности в размерах VM), стоит рассмотреть переход к отдельной роли. –

+0

@DavidMakogon Спасибо, что я не знал, что роль рабочего требует отдельный экземпляр. И я не пытался ответить на этот вопрос. +1 Я многому научился из этого вопроса. – Paparazzi

ответ

10

Я бы suggets решение, которое отличается от решения Леона и Давида: решение

  • Давида в порядке, но не является устойчивым. Что это экземпляр/процесс отключается во время обработки задачи?
  • Решение Леона в основном относится к запланированным заданиям, но отправка электронной почты не всегда запланирована (возможно, вы хотите отправить электронное письмо, когда кто-то регистрируется в вашем приложении).

Другого вариант, вы должны смотреть на это с помощью Windows Azure Storage очередей (они очень дешевы) в этом сценарии:

  • Вашего веб-приложениях: Отправка сообщений в очередь (например, «отправить по электронной почте to [email protected] ')
  • WebRole.cs: запускать новый поток при запуске экземпляра и прослушивать сообщения из этой очереди. Всякий раз, когда приходит сообщение, обработайте его. В случае успеха удалите сообщение из очереди.

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

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

using System; 
using System.Collections.Generic; 
using System.Linq; 
using Microsoft.WindowsAzure; 
using Microsoft.WindowsAzure.Diagnostics; 
using Microsoft.WindowsAzure.ServiceRuntime; 
using Microsoft.WindowsAzure.StorageClient; 
using System.Threading.Tasks; 

namespace MvcWebRole1 
{ 
    public class WebRole : RoleEntryPoint 
    { 
     public override bool OnStart() 
     { 
      Task.Factory.StartNew(InitializeQueueListener); 
      return base.OnStart(); 
     } 

     private void InitializeQueueListener() 
     { 
      Microsoft.WindowsAzure.CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) => 
      { 
       configSetter(Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetConfigurationSettingValue(configName)); 
      }); 


      var storageAccount = CloudStorageAccount.FromConfigurationSetting("DataConnectionString"); 
      var queueStorage = storageAccount.CreateCloudQueueClient(); 
      var queue = queueStorage.GetQueueReference("myqueue"); 
      queue.CreateIfNotExist(); 

      while (true) 
      { 
       CloudQueueMessage msg = queue.GetMessage(); 
       if (msg != null) 
       { 
        // DO SOMETHING HERE 
        queue.DeleteMessage(msg); 
       } 
       else 
       { 
        System.Threading.Thread.Sleep(1000); 
       } 
      } 
     } 
    } 
} 
+0

Кажется, лучшее решение для той работы, которую я готов выполнить, в любом случае я планировал иметь очереди для «разговоров» с локальным приложением, поэтому это будет не так дорого ... Можете ли вы подробнее рассказать о том, как «порождать новый поток при запуске экземпляра и прослушивать сообщения из этой очереди»? ** Было бы здорово, если бы вы могли привести мне пример или указать мне пример, который объясняет часть потока, участвующую в запуске прослушивающего потока в WebRole.cs **. Спасибо – ToinoBiclas

+0

Согласовано - очереди очень устойчивы. Мое намерение заключалось в том, чтобы указать на жизнеспособность создания потоков (что не всегда очевидно). –

+0

@Sandrino Сообщите мне, если это встроено в ваше решение ... создайте поток в WebRole.OnStart() 'новой теме (новый ThreadStart (ClassListeningToQueue.Method0) ", затем внутри Method0 напишите бесконечный цикл или цикл с условием что только изменяется через WebRole.OnStop() 'while (true) {try {CloudQueueMessage msg = queue.GetMessage(); if (msg! = null) {' finnaly выполнить задачу в соответствии со значениями внутри msg, например, я мог бы есть поле, которое указывает, какой метод вызывать и параметры также. Безопасно ли вызывать другие потоки внутри основного потока? – ToinoBiclas

1

Я нашел это, когда я искал «лазурные запланированные задачи»: http://www.ronaldwidha.net/2011/02/23/cron-job-on-azure-using-scheduled-task-on-a-web-role-to-replace-azure-worker-role-for-background-job/

Похоже, именно то, что вы ищете.

+0

Пример, который вы указали для запуска запланированных заданий, как и crontabs в Linux. То, что я готов сделать, имеет поток, ожидающий передачи сигнала. – ToinoBiclas

+0

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

2

Абсолютно вы можете создать нить (или много их). Веб-роль - это в основном Windows 2008 Server. Для создания фоновой задачи вам не нужна отдельная роль рабочего. Конечно, у вас есть, у вас есть отдельная рабочая роль, которая позволит вам масштабировать эти экземпляры независимо от экземпляров веб-роли. Здесь вам нужно будет сбалансировать производительность/масштабирование со стоимостью.

+0

Можете ли вы рассказать мне, как это сделать? Как я могу получить доступ к переменной потока с одной из веб-страниц aspx, если она была объявлена ​​в WebRole: RoleEntryPoint? – ToinoBiclas

+2

Если вам нужно взаимодействовать с потоками с ваших страниц aspx, почему бы не начать потоки с global.asax? RoleEntryPoint будет запускаться в отдельном AppDomain, поэтому у вас не будет взаимодействия между приложением и потоком. –

+0

Честно говоря, никогда об этом не думал. Я попытаюсь выполнить некоторое тестирование с пулом потоков, объявленным в global.asax. – ToinoBiclas

Смежные вопросы