Almacenamiento local en los roles de Windows Azure

En determinadas ocasiones es posible que necesitemos hacer uso del almacenamiento local del servidor donde estamos ejecutando nuestra aplicación. Si bien el uso del mismo debería ser de forma temporal puede ser útil en determinadas ocasiones.

En Windows Azure, dependiendo del tamaño de nuestra máquina virtual, tendríamos la siguiente capacidad:

Tamaño de la VMEspacio en el disco local
*Extra small 20 GB
Small250 GB
Medium500 GB
Large1.000 GB
Extra Large2.000 GB

*Este tamaño fue anunciado en el PDC 2010, aunque aún no está disponible para su uso. Al entrar en vigor dicho tamaño el resto de las máquinas virtuales se verán ligeramente modificadas.

 Lo primero que debemos tener en cuenta es que este espacio está solamente disponible para la instancia del rol. Es decir, si nosotros tenemos varias instancias de un mismo rol (varios frontales) cada uno tendría su propio almacenamiento local y  no sería accesible por el resto de las instancias. Otro punto a tener en cuenta es que si esa instancia, por cualquier motivo, deja de funcionar de forma inesperada se perderían los datos almacenados en este espacio.

Entonces, si este espacio es volátil y por lo tanto no se trata de un sitio fiable para mantener información en él ¿Qué uso podríamos dar a dicho espacio?
Cuando necesitamos almacenar información en un medio fiable en la nube podríamos hacerlo usando Blobs, Tablas o bien SQL Azure, ya que sería la forma más común de compartir esa información con todas las instancias de nuestros roles. Aunque estos mecanismos serían los adecuados, las transacciones a estos supone un problema de latencia. Por ello, si utilizamos el almacenamiento local para almacenar aquellos elementos que son frecuentemente accedidos podríamos aumentar la velocidad a los datos, ya que el almacenamiento local está en nuestra propia instancia.
 

 Configurando el almacenamiento local

 Para poder configurar el almacenamiento local en un rol, haremos doble click en el rol indicado en la carpeta Roles de nuestro proyecto en Visual Studio, para poder visualizar la interfaz de configuración.

Como podemos ver en la imagen anterior, podemos crear varios registros para el almacenamiento local, lo cual significa que podemos crear varios espacios destinados a distintos fines con una cuota establecida por nosotros en megas. Además, vemos que tenemos una última opción llamada Clean on Role Recycle la cual se utiliza para indicar si queremos mantener o no los datos cuando un rol es reciclado (o lo que es lo mismo, cuando un rol es reiniciado).

Esta misma información también puede ser definida a través del archivo ServiceDefinition.csdef donde se añade un nuevo apartado llamado LocalResources.

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="LocalStorage" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRoleLocalStorage">
    <InputEndpoints>
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
    </InputEndpoints>
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" />
    </ConfigurationSettings>
    <LocalResources>
      <LocalStorage name="Images" cleanOnRoleRecycle="false" sizeInMB="100" />
      <LocalStorage name="Videos" cleanOnRoleRecycle="true" sizeInMB="500" />
    </LocalResources>
  </WebRole>
</ServiceDefinition>

Usando el almacenamiento local

Para mostrar las distintas opciones, he creado un pequeño rol donde lo único que hacemos es recuperar un archivo a través de un control del tipo FileUpload y simulamos la subida a la instancia que está atendiendo nuestra petición.

Para poder comprobar ambos casos (qué ocurre cuando se reinicia un role con cleanOnRoleRecycle), he creado además un combo donde podemos elegir a qué espacio queremos enviar el archivo. Para recuperar la ruta del espacio destinado a nuestro recurso podríamos hacerlo a través del siguiente código:

using System;
using System.IO;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace WebRoleLocalStorage
{
    public partial class _Default : System.Web.UI.Page
    {

        protected void btnUpload_Click(object sender, EventArgs e)
        {
            var localResource = RoleEnvironment.GetLocalResource(ddlResource.SelectedValue);
            var newFile = File.Create(localResource.RootPath + FileUploadFile.FileName);

            FileUploadFile.FileContent.CopyTo(newFile);

            newFile.Flush(true);
        }
    }
}

RoleEnviroment es una clase que pertenece a la librería Microsoft.WindowsAzure.ServiceRuntime y GetLocalResource es el método que nos permite recuperar información relativa al recurso seleccionado. Al hacer la llamada nos devolverá un objeto del tipo LocalResource el cual nos aportará información como el nombre, el tamaño máximo del recurso en megas y el path del recurso.

Supongamos que subimos dos archivos, uno al recurso Images y otro a Videos. Para poder visualizar en el entorno de desarrollo estos recursos podemos acceder a través del GUI del Development Fabric y, seleccionamos la opción Open local store… de una de las instancias.

Al pulsar sobre esta opción se nos abrirá una nueva ventana con una serie de carpetas. Para acceder al apartado que nos interesa, pulsamos sobre la llamada directory.

¡Y voilà!

Vemos dos carpetas con el nombre de nuestros recursos y una imagen en cada una correspondientes a las que acabamos de subir 😀

Por último, para comprar qué ocurriría si reiniciamos dicha instancia podemos hacerlo a través de la interfaz del Development Fabric posicionando el ratón sobre el rol y pulsando en la tecla de reinicio.

Si volvemos a comprobar las carpetas de los recursos, vemos que el recurso Videos estaría vacío al haber indicado clearOnRoleRecyle 🙂

¡Saludos!