Me suggets una solución que es diferente de solución de León y de David: solución
- de David está bien pero no es elástico. ¿Qué parte de la instancia/proceso se desconecta mientras se procesa la tarea?
- La solución de Leon se aplica principalmente a trabajos programados, pero enviar un correo electrónico no siempre es algo programado (quizás quiera enviar un correo electrónico cuando alguien se registre en su aplicación).
Otra opción que usted debe tener en cuenta es el uso de Azure colas de almacenamiento de Windows (que son muy baratos) en este escenario:
- Su aplicación web: envía mensajes a la cola (como 'enviar un correo electrónico a [email protected] ')
- WebRole.cs: generar un nuevo hilo al iniciar la instancia y hacer que escuche los mensajes de esa cola. Cuando llega un mensaje, trátelo. Si tiene éxito, elimine el mensaje de la cola.
Esta solución tiene muchas ventajas. WebRole.cs se ejecuta en un proceso diferente al de su aplicación web, por lo que no afecta a los hilos de solicitud. Y además de eso, si el envío del correo falla por alguna razón, el mensaje permanecerá en la cola y se procesará la próxima vez. Esto asegurará que no perderá ninguna tarea para ejecutar si la aplicación o el proceso falla.
Aquí hay un ejemplo para comenzar. Tenga en cuenta que necesitará mejorar este código si quiere que esté listo para producción (política de reintento, manejo de excepciones, sondeo de rechazo, ...):
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);
}
}
}
}
}
¿Cómo eso reduciría los costos de funcionamiento? ¿Qué diferencia hay entre el servicio de simultaneidad único de una sola instancia? – Paparazzi
@Blam: la ejecución de tareas en segundo plano en un rol web permite la combinación de operaciones en un solo conjunto de instancias de máquina virtual. Esto está en contraste con colocar operaciones de fondo en un conjunto separado de instancias de rol. Combinar en una función ahorraría costos, ya que cada función debe tener al menos una instancia ejecutándose. Para sitios de bajo volumen, esta es una gran arquitectura que ahorra costos.Si existe el riesgo de que las tareas en segundo plano mueran de hambre en el sitio web, o si es necesario escalar las tareas de fondo y de fondo por separado (o tienen diferentes necesidades de tamaño de VM), vale la pena considerar el cambio a un rol separado. –
@DavidMakogon Gracias. No sabía que un Rol de Trabajador requería una instancia separada. Y no intenté responder la pregunta. +1 Aprendí mucho de esta pregunta. – Paparazzi