En esta sección se muestran las diferentes alternativas para realizar tareas en background en ambas plataformas, detallando particularidades de diseño y de implementación.
APP ENGINE
Las tareas en background se pueden disparar ante un evento temporal o ante el cambio de una condición en el sistema.
Para disparar tareas en background utilizando un evento temporal, se pueden utilizar el servicio Cron Jobs.
Un Cron Job se define utilizando el archivo cron.xml
<?xml version="1.0" encoding="UTF-8"?>
<cronentries>
<cron>
<url>/url_target</url>
<description>Una Descripcion</description>
<schedule>qué día, a que hora, cada cuanto</schedule>
</cron> </cronentries>
Código Fuente 7-16
Cada Cron Job, apunta un Servlet determinado a través de la url. Los Cron Job se pueden utilizar tanto en las instancias backend como en las instancias front-end. No hay diferencia en el código de un Servlet entre una instancia FrontEnd o una instancia Backend. Como se mencionó en el capítulo anterior, la diferencia radica en el límite de capacidad de procesamiento de uno y de otro.
Un Backend se define utilizando el archivo Backend.xml
75 <backend name="backend1">
<class>B1</class>
<instances>1</instances> <options>
<dynamic>true</dynamic> </options>
</backend> </backends>
Código Fuente 7-17
Un backend puede ser dinámico o residente. Un Backend dinámico permanece inactivo, hasta que se activa ante un evento, como la ejecución de un Cron Job, y una vez que realiza la tarea, vuelve a estar inactivo. En cambio un Backend residente, una vez que se activa permanece activo, hasta que se desactiva utilizando la consola de administración. El tipo de instancia Backend no está destinada a hacer una única tarea, sino que se pueden programar para que se ejecuten múltiples Jobs sobre la misma. Para ello solo es necesario que diferentes Cron Job apunten al mismo backend utilizando el tag “target”.
<?xml version="1.0" encoding="UTF-8"?>
<cronentries>
<cron>
<url>/url_target1</url>
<description>Una Descripcion</description>
<schedule>qué día, a que hora, cada cuanto</schedule> <target>backend1</target>
</cron>
<cron>
<url>/url_target2</url>
<description>Otra Descripcion</description>
<schedule>qué día, a que hora, cada cuanto</schedule> <target>backend1</target>
</cron> </cronentries>
Código Fuente 7-18
La cantidad de tareas a asignarle a un Backend dependerá de que éste no se
sobrecargue de modo que no pueda atender todas las tareas. En tal caso, se pueden incrementar la cantidad de instancias para el mismo Backend, o bien agrupar lógicamente ciertas tareas en un Backend, y otras tareas en otro Backend.
En definitiva, la decisión de usar las instancias backend o FrontEnd para tareas en
background siempre estará relacionada con el tiempo de procesamiento que lleve la tarea en cuestión.
76
Para tareas cortas, se puede utilizar las instancias de FrontEnd perfectamente, para tareas que lleven mayor tiempo de procesamiento, y mayor poder de procesamiento, sin dudas las instancias BackEnd serán las que hay que utilizar.
WINDOWS AZURE
Al igual que en App Engine, las tareas se pueden disparar ante un evento temporal o ante el cambio de una condición del sistema.
Para disparar eventos temporales en Windows Azure se puede utilizar el servicio Job Scheduller disponible desde la Consola de Administración, Figura 7-1.
Figura 7-1 - Configuración de un job en Windows Azure
Cada Cron Job programado al llegar el momento de ejecutarse, invoca a un script asociado, el cual puede delegar tareas utilizando el servicio de colas de mensajes.
functionscript_job() {
var azure = require('azure');
var queueService = azure.createQueueService("myaccount", "mykey"); queueService.createQueueIfNotExists("queue", function(error){ }); queueService.createMessage("queue", "TareaParaHacer", function(error){}); }
77 Código Fuente 7-19
Para realizar las tareas lanzadas por el Job Scheduller podemos utilizar un Worker Role. Para crear un Worker Role solo es necesario crear una clase que herede de
RoleEntryPoint.
Esta clase tiene 3 métodos principales
OnStart: es un método que se ejecuta cuando se activa el Worker Role
Run: es el método principal donde se deberá programar el trabajo a realizar por el Worker Role
OnStop: es un método que se ejecuta cuando se desactiva el Worker Role.
Los 3 métodos describen el ciclo de vida de un Worker Role, es decir, un comienzo, algo que hacer, y el final. Un Worker Role por defecto no corre indefinidamente. Una vez que se termina de ejecutar el método Run, el Worker Role se desactiva. Para evitar esto, se utiliza un while(true) con una llamada al método Sleep para dormirlo por un tiempo determinado y volver a chequear luego si tiene trabajo para realizar.
Ejemplo de Worker Role:
publicclass WorkerRole : RoleEntryPoint {
public override bool OnStart() {
return base.OnStart(); }
public override void Run() {
while (true) {
// Aca va el código a ejecutar de una tarea concreta. // ...
//
Thread.Sleep(60000); }
}
public override bool OnStop() {
return base.OnStop(); }
78 }
Código Fuente 7-20
Si bien, el objetivo del Worker Role es análogo al tipo de instancias Backend de App
Engine, tienen un modelo de activación y ejecución diferente, que obliga a programarlos
de otra forma. El código del Worker Role no se activa ante requerimientos, sino que se activa al momento de subirlo junto con toda la aplicación, o bien se puede activar desde la consola de administración de Windows Azure una vez subido.
Se puede utilizar un tipo de Worker Role separado para cada tipo de tarea, donde cada instancia de Worker Role utilizará recursos dedicados, o bien, para mejorar la utilización de los recursos existe la posibilidad de utilizar el mismo Worker Role para múltiples
tareas. Para poder dividir el trabajo en un Worker Role, la mejor opción es utilizar una cola de trabajo. Para realizar esto el Worker Role cada cierto intervalo de tiempo, por ejemplo cada 5 minutos, verifica si hay elementos en la cola trabajo, si lo hay, extrae el elemento, que por lo general es un string indicando el nombre de la tarea a realizar, y mediante un
switch, se dispone a ejecutar la tarea correspondiente.
Public class WorkerRole : RoleEntryPoint {
Public override void Run() {
var account =
CloudStorageAccount.Parse(ConfigurationManager.AppSettings["StorageConnection"]);
var queue = account.CreateCloudQueueClient().GetQueueReference("queue"); queue.CreateIfNotExists(); while (true) { var msg = queue.GetMessage(); if (msg != null) { switch (msg.AsString) { Case "xxx": Case "yyy": default: break; }
79 } Thread.Sleep(10000); } } ... } Código Fuente 7-21
La utilización de procesos en background facilita la realización de tareas asincrónicas, y permite aislar el comportamiento que más tiempo de CPU conlleva, para que la aplicación online tenga mejores tiempos de respuesta. Tanto App Engine como Windows Azure ofrecen estos mecanismos para ejecutar este tipo de tareas, junto con los mecanismos de sincronización, como las colas de trabajo.
En esta sección se analizaron diferentes cuestiones relacionadas con la arquitectura de la aplicación del Sistema de Alertas, que permiten entender la complejidad técnica de una solución SaaS multi-tenant. La implementación de la configurabilidad, la elección del esquema de la base de datos, el diseño de la escalabilidad y la implementación de tareas en background son los requisitos técnicos más importantes y los que primeros que se deben evaluar y analizar como paso previo a la construcción de una solución SaaS multi- tenant.
En la siguiente sección se analizarán diferentes cuestiones técnicas relacionadas con cierta funcionalidad crítica del Sistema de Alertas y cómo estas se pueden implementar sobre una plataforma como servicio.