Friday, December 6, 2013

Elegir el tamaño de una VM para desarrollo o pruebas

Al crear una nueva VM para nuestro ambiente de desarrollo o pruebas siempre surge la duda de cual es el tamaño apropiado, a fin de balancear costos con capacidad de proceso.

Lógicamente, mayor capacidad de proceso significa mayor costo. Si analizamos la tabla de precios por hora publicada en el sitio de Windows Azure es muy considerable el salto que existe entre una instancia Extra Small a una instancia Small.


Esta diferencia de cierta forma es justificada debido que estamos pasando de una instancia donde el procesador es compartido entre varias instancias, a una instancia con procesador propio y mas del doble de memoria. No obstante, resulta muy difícil determinar a primera vista cual es la opción que mejor balance nos dará entre costo y desempeño.

Sucede que estamos acostumbrados a que los equipos en los que habitualmente desarrollamos tienen una potencia mucho mayor a lo expresado en la tabla: hoy en día cualquier desarrollador cuenta con 8gb de memoria y cuatro procesadores en su notebook. Sin embargo tenemos que tener en cuenta no son parámetros comparables.

Las VMs generadas en Windows Azure se encuentran muy optimizadas para realizar específicamente las tareas de procesamiento que necesitamos, dejando de lado muchos "lujos" que nos damos en nuestra notebook o computador de escritorio y que hacen uso intensivo de los recursos del ordenador. Así mismo ocurre con el hardware en donde se encuentran virtualizadas esos computadores. Por lo que el rendimiento de una máquina pequeña en Windows Azure puede llegar a sorprendernos (para bien), de acuerdo a nuestra percepción (distorsionada) de lo que siginifican 768Mb de memoria RAM.

Esta percepción distorsionada puede collevar implicancias mucho mayores.

Imaginemos la siguiente situación. Nuestra aplicación requiere una consulta de base de datos de cierta complejidad donde es necesario relacionar datos de varias tablas mediante inner joins. En principio vemos que la consulta tiene un buen desempeño en nuestro ambiente de desarrollo (ej. un notebook I7 con 8Gb), aún cuando observando que la cantidad de datos sería similar a lo que esperaríamos tener en producción.

Esta percepción es muy engañosa ya que el optimizador de queries de Sql Server puede elegir caminos muy diversos dependiendo de los recursos con los que cuenta el sistema. En el caso de nuestra poderosa notebook, puede ocurrir que determinadas falencias en nuestro modelo queden ocultas detrás de tanta potencia (ejemplo, carencia de ciertos índices clave).

Una buena forma de descubrir estas falencias es utilizar un ambiente de pruebas pequeño. 

De esta forma rápidamente saltarán a la vista las funcionalidades de nuestra aplicación que podrían ser mejoradas desde el punto de vista de desempeño (ej. consultas lentas, bloqueos, páginas pesadas, etc.), dándonos la oportunidad de investigar y reimaginar la forma en que resolvemos determinados problemas con el objetivo de lograr un desempeño óptimo.

Conclusiones.

  • No subestimar el poder de una máquina pequeña, muchas veces una instancia Extra Small es mas que suficiente para nuestro ambiente de pruebas o desarrollo
  • Siempre tenemos la oportunidad de agregar mas capacidad en el futuro sin que esto signifique un impacto en la aplicación (esa es la gran ventaja de Windows Azure)
  • Un ambiente sobre-dimensionado puede llevarnos a sobre-utilizar recursos 
  • Un ambiente restringido en recursos nos facilita identificar las oportunidades de mejora de desempeño y a la larga nos vuelve mas creativos a la hora de hacer nuestra aplicación mas performante.




 












Tuesday, December 3, 2013

Aplicaciones Híbridas: IoC con Windows Azure Service Bus Relay (Parte II)

Intro

En el post anterior (http://brmcc.blogspot.com/2013/12/aplicaciones-hibridas-ioc-con-windows.html) explicamos conceptualmente como a través de Windows Azure Service Bus es posible exponer servicios on-premises en la nube.

El presente post tiene por objetivo ilustrar con un ejemplo de código como hacer esto posible. Para ello hemos desarrollado una solución de ejemplo que contiene dos proyectos. El primer proyecto es un sitio web ASP.NET tradicional. El segundo proyecto contiene un web service WCF con el cual la aplicación web interactúa.

A diferencia de otros ejemplos similares donde el servicio es expuesto en una aplicación de consola, en nuestro ejemplo utilizaremos un servicio expuesto en Internet Information Services dado que es un escenario más típico. Esto nos permitirá ademas explicar algunos detalles y consideraciones a tener en cuenta relacionados con la activación del servicio.

La aplición puede ser descargada de aquí: http://sdrv.ms/1dNOHob

Pasos a seguir (resumen)

Los pasos a seguir para publicar un web service mediante un Relay en Windows Service Bus son los siguientes:
  1. Crear un nuevo namespace en  Windows Azure Service Bus
  2. Crear un web service y publicarlo en IIS
  3. Consumir el web service desde una aplicación Web
  4. Configurar un endpoint al servicio para que se registre en el bus
  5. Crear una clase para la activación automática del servicio
  6. Configurar el application pool del servicio para inicio y activación automáticos
  7. Configurar un endpoint en la aplicación Web para que accedea al servicio mediante el bus
  8. Crear una clase para la recuperación automática del servicio

1. Crear un nuevo namespace en  Windows Azure Service Bus

El primer paso consiste en crear un nuevo espacio de nombres que será utilizado para conformar las direcciones de nuestros servicios expuestos en el bus. 



En la sección Service Bus basta con seleccionar "Relay" y luego "quick create". Allí deberemos definir el prefijo que tendrá nuestro namespace y al cual se le agregará automáticamente el sufijo "servicebus.windows.net".

2. Crear un web service y publicarlo en IIS.

Este paso consiste básicamente en tomar el web service de la aplicación de ejemplo y publicarlo en IIS.

Para ello se debe crear un sitio web em IIS que apunte a la carpeta donde se encuentra el Web Service.



Para no dependeer de la IP o nombre del computador, resulta conveniente definir un host name y luego agregar la entrada en el archivo c:\windows\system32\drivers\etc\hosts.

Luego, abrir la solución en Visual Studio y en las propiedades del proyecto actualizar la configuración "Web" para que el web service ejecute y pueda debuggearse en IIS:



Luego de compilar y con el servicio en IIS, verificar que el mismo quede funcionado navegado al archivo .svc correspondiente.


La página de bienvenida al servicio debería desplegarse correctamente:


3. Consumir el Web Service desde una aplicación Web.

Para consumir el web service es necesario agregar una "Service Reference" al proyecto. En la aplicación de ejemplo esto ya está realizado, basta verficar en la carpeta Service References:



La aplicación de ejemplo es muy simple y en su página Default.aspx contiene una grilla, la cual es llenada con datos luego de consultar al web service. Para ello se disponen dos textbox para disparar consultas de clientes por ID y por razón social. Adicionalmente hay un checkbox para decidir si la consulta será realizada pasando por Azure Service Bus o directamente al web service. Dado que aún no hemos configurado el web service en el Service Bus, solo podemos optar por dejar esta opción sin chequear.



4. Configurar un endpoint al servicio para que se registre en el bus

Para que el servicio se registre en el service bus es necesario configurar un nuevo endpoint que utilice el binding "netTcpRelayBinding". Este binding y otros elementos vienen incluidos en Windows Azure ServiceBus SDK, el cual puede descargarse en forma gratuita como un paquete de NuGet. Esto puede hacerse ingresando al menú contextual del proyecto (click-derecho) y seleccionar la opción "Manage NuGet Packages". Allí mismo buscar "Service Bus" en el cuadro de búsqueda para que aparezca el SDK a instalar:


La aplicación de ejemplo ya cuenta con el package instalado y puede observarse en la configuración (web.config) que al instalarse el paquete se agregan automaticamente varias entradas para la extensión de bindings y behaviors de WCF:


Estas extensiones son las que permiten que nuestro web service pueda configurarse para ser invocado desde el Service Bus. Para ello es necesario agregar un nuevo endpoint en la seccion <service/> correspondiente:


Este nuevo endpoint tiene que especificar como dirección la URI definida en el namespace del paso 1 y agregándole al final un nombre identificatorio del servicio. El binding a utilizar debe ser "netTcpRelayBinding". Al iniciar el servicio, el binding intentará registrar la direccion configurada como un "Relay" en el Service Bus y se quedará "escuchando" a las peticiones que lleguen desde la nube.
En el momento de la registración el Service Bus solicitará al web service que se autentique, de forma tal de identificar al web service como un destino Relay válido. La autenticación se realiza mediante un behavior especial a configurar en el endpoint mediante el atributo behaviorConfiguration el cual hace referencia a la siguiente configuración:


El atributo issuerSecret corresponde a una clave simétrica asignada por Windows Azure Service Bus y la cual puede obtenerse accediendo al portal de administración:


Esta opción despliega un panel con toda la información de conexión, incluida la clave requerida ("default key").

Si ahora iniciáramos la aplicación y ejecutáramos el servicio (sin pasar por Service Bus), este se registrará automáticamente como Relay en Azure. Incluso en el portal de administración de Windows Azure deberíamos observar en la sección Service Bus que hay un nuevo Relay en estado "listening":



De acuerdo al funcionamiento por defecto de WCF, el servicio es iniciado cuando recibe la primera invocación, la cual en este ejemplo realizamos sin pasar por el service bus. Este comportamiento no resulta conveniente ya que lo ideal sería que el servicio se registre en el service bus previo a la primer invocación. En el paso siguiente veremos como lograr esto.

5. Crear una clase para la activación automática del servicio

Para que nuestro servicio inicie automáticamente al iniciar el application pool, deberemos extender el funcionamiento de este último implementando la interfaz System.Web.Hosting.IProcessHostPreloadClient. Esta interfaz expone el método "Preload", el cual será invocado al inicial el application pool.
En la aplicación de ejemplo podemos encontrar la clase ConsultaClienteAutostart que implementa dicha interfaz y se asegura de que el web service se encuentre disponible al iniciar.



6. Configurar el application pool del servicio para inicio y activación automáticos

Una vez que implementada la interfaz y con la clase compilada, podemos configurar el Application Pool que alojará a nuestro web service para que se autoinicie. Para ello deberemos editar un archivo de configuración que se encuentra en la ruta C:\Windows\System32\Intersrv\Config\applicationHost.config
Este archivo contiene entre otras cosas las configuraciones de los application pools de nuestro servidor, entre ellos el que alojará a nuestro web service.
Dentro de la sección <system.applicationHost/> deberemos agregar una nueva sección <serviceAutoStartProviders/> en la cual declararemos la clase creada en el punto 5:

<serviceAutoStartProviders>
    <add name="ConsultaClientesAutoStart" 
        type="AzureRelayTest.ConsultaClientesAutostart, AzureRelayTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</serviceAutoStartProviders>

Así mismo, en la sección correspondiente al sitio web que aloja al web service, es necesario configurar el switch para habilitar el "autostart" y hacer referencia a la clase.

...
<site name="AzureRelayTest" id="8">
    <application path="/" 
            applicationPool="AzureRelayTest" 
            serviceAutoStartEnabled="true" 
            serviceAutoStartProvider="ConsultaClientesAutoStart">
    <virtualDirectory path="/" physicalPath="C:\Code\AzureRelayTestSolution\AzureRelayTest" />
    </application>
...

Con estas configuraciones ya podemos reiniciar el application pool y automáticamente nuestro servicio se iniciará y se registrará con el Service Bus de Azure.

7. Configurar un endpoint en la aplicación Web para que accedea al servicio mediante el bus

Finalmente para que la aplicación consuma el servicio pasando por el Service Bus, es necesario configurar un endpoint cliente a la dirección definida en el paso 4. Esto debe configurarse en la sección <system.serviceModel/> del web.config de la aplicación Web:



Así mismo también es importante configurar el behavior correspondiente para que el cliente pueda autenticarse al service bus, tal como se observa en la figura.

Si ahora ejecutamos la aplicación y chequeamos para invocar a través del Service Bus, notaremos que el tiempo de ejecución será un poco mas largo (2.5 segundos aprox.) lo cual es esperable ya que estamos haciendo gran round-trip para lograr la invocación:



8. Crear una clase para la recuperación automática del servicio

En un escenario real, puede ocurrir que nuestro service host falle por una excepción inesperada y se desconecte del Service Bus. Ante esta situación basta con reciclar el application pool para que se cree un nuevo host. Sin embargo este escenario podría dejar sin servicio a nuestra aplicación por un buen tiempo, lo cual no es deseable.
Para poder brindar funcionalidad de auto-recuperación  ante un fallo, basta con aplicar el patrón de factory de WCF para crear nuestra propia factoría del service host. Esto es precisamente lo que hace la clase del ejemplo ConcultaClientesServiceHostFactory:


Por último, es necesario instruir a WCF que utilice la factory que acabamos de crear cada vez que necesite crear una nueva instancia del host de servicio. Esto podemos configurarlo en el archivo ConsultaClientesService.svc:



Conclusiones finales.

Windows Azure Service Bus es una gran herramienta de plataforma a partir de la cual podemos empezar a pensar nuevas arquitecturas híbridas que aprovechen lo mejor de ambos mundos, la nube y on-premises.
Si bien muchas integraciones podemos (y debiéramos) pensarlas y diseñarlas como mensajerías asincrónicas, pueden existir escenarios en donde un patrón de intercambio request-response sea lo que necesitamos. 
La extensibilidad y flexibilidad de WCF junto con el SDK de Windows Azure Service Bus nos proporcionan todos los elementos para lograr este tipo de integraciones evitando mayores impactos en la lógica de nuestra aplicación.

 





Monday, December 2, 2013

Aplicaciones Híbridas: IoC con Windows Azure Service Bus Relay (Parte I)

Intro

Windows Azure Service Bus es un gran servicio de plataforma que nos permite (entre otras cosas) "enchufar" a la nube cualquiera de nuestros web services que hoy se encuentren ejecutando on-premises.

¿Por qué querríamos hacer algo así? Imaginemos que quisiéramos llevar a la nube una aplicación que requiere acceder a determinados web services que se encuentran dentro de nuestra red corporativa (ej.  detrás de un firewall y otros dispositivos de comunicaciones). Una solución posible sería configurar acceso de redes y firewalls entre nuestro Cloud Service y nuestro datacenter para que la aplicación simplemente acceda directamente a los web services que requiera. Incluso hasta podríamos crear una VPN si quisiéramos agregar mayor seguridad.

Si bien esta solución es completamente feasible, requiere la intervención de administradores expertos de redes e infrarstructura para poder configurarla (y luego mantenerla). Otro punto y no menos importante, es la fragilidad que a veces tienen este tipo de configuraciones: la realidad nos dice que los nombres de computadores y las IPs suelen estar sujetas a cambios, lo cual dificulta garantizar que los endpoints de nuestros web services siempre se encontrarán disponibles en las URIs donde fueron configurados originalmente.




Inversión-de-Control o Principio de inversión de dependencias

Quiénes estén familiarizados con patrones de diseño de software habrán escuchado hablar del principio de inversión de dependencias, formulado hace un buen tiempo por Robert C. Martin (http://www.objectmentor.com/resources/articles/dip.pdf). Dicho principio sugiere "alivianar" el acoplamiento entre dos (o más) piezas de software mediante el uso de una interface conocida por ambas piezas. De acuerdo a esta técnica, ninguna pieza sabrá de la existencia de la otra en tiempo de diseño, sino que el acoplamiento entre ambas ocurrirá en tiempo de ejecución. De esta forma, si alguna de las piezas cambia la otra no se verá afectada en tanto se respete la interface definida previamente.

Desde hace ya un buen tiempo que los web services desarrollados en .NET requieren la definición de una interface o "contrato", oligando de alguna manera a respetar este principio de inversión de dependencias (sin ir mas lejos, el WSDL de un servicio es también un "contrato" o definición de interface). No obstante, a la hora de configurar los endpoints de nuestros servicios nos encontramos con las dificultades enunciadas anterioremente (VPNs, firewalls, DNS, etc). Esta complejidad se incrementa cuando además hay que considerar ambientes diferenciados para desarrollo, testing y producción.

Haciendo la analogía del principio de inversión de dependencias, Windows Azure Service Bus hace posible "invertir la dependencia" a los endpoints físicos de nuestros web services y conectando a éstos últimos al Service Bus. Luego, las aplicaciones cliente solo requerirán conectarse al Service Bus para realizar las invocaciones. 

La ventaja de este enfoque es que si en algún momento necesitáramos mover nuestros web services a otra infraestructura, esto no supondría ningún cambio en las configuraciones de los endpoints. Solo bastaría con poner en marcha nuestros web services en la nueva infraestructura para que automáticamente se conecten al Service Bus y vuelvan a estar disponibles para las aplicaciones clientes.

Una de las características de Windows Azure Service Bus que hacen posible que la nube actúe de intermediario entre las aplicaciones cliente y los web services son los "Relays". Y gracias a la arquitectura de Windows Communication Foundation es muy fácil utilizarlos mediante simples cambios de configuración en nuestra aplicación, e incluso sin necesidad de tener que cambiar código alguno.

Bindings y Behaviors

De acuerdo a la arquitectura WCF, los web services deben exponer "endpoints" de comunicación para que los clientes puedan acceder a ellos. Un "endpoint" consiste en una configuración en la cual se definen los siguientes elementos:
  • Address. Identificador único del recurso en la red (ej. URI) 
  • Binding. Detalles de los protocolos de comunicación y codificación.
  • Contract. Referencia a la interface o contrato que describe las operaciones expuestas en el endpoint.




Adicionalmente, es posible espeficar "behaviors" o componentes de lógica transversal que operen sobre los mensajes recibidos y devueltos por el servicio. Típicamente los behaviors son utilizados para dar tratamiento a necesidades transversales como la autenticación y la autorización.

Todos estos elementos hacen referencia a piezas provistas por WCF y que son habitualmente configurados en el archivo de configuración de la aplicación (.config) y pueden ser alterados sin que esto suponga un cambio de código o recompilaciones. De esta forma un mismo web service puede exponer sus operaciones utilizando varios endpoints en direcciones y protocolos diferentes, 

Adicionalmente, Windows Azure Service Bus provee un SDK con elementos adicionales para configurar los endpoints de un servicio de forma tal estos puedan recibir mensajes provenientes desde el bus. Puntualmente el SDK provee un nuevo binding denominado "netTcpRelayBinding" y que contiene la lógica de conectividad con el bus. A diferencia de otros bindings que se activan cuando un cliente intenta enviar un mensaje, este binding requiere ser activado al iniciar el web service y durante su activación establece un canal de comunicación directo con el Service Bus. Este canal se mantendrá en tanto el web service siga en ejecución, y por él llegarán los mensajes enviados desde el bus.Así mismo el netTcpRelayBinding puede ser utilizado por las aplicaciones cliente para invocar a los web services expuestos en el bus.



La parte interesante de todo esto es que dado la comunicación es originada inicialmente por el web service, no es necesario habilitar conexiones entrantes en nuestro firewall corporativo, sino que solo basta que el web service pueda establecer una conexión saliente hacia el datacenter de Windows Azure

Otro elemento necesario y provisto por el SDK es un behavior utilizado para lograr la autenticación con el Service Bus y de esta forma evitar que otro web service no autorizado pueda recibir mensajes que no le correspondan.

En el siguiente post exploraremos un ejemplo de como conectar un web service al service bus para después consumirlo desde nuestra aplicación.

Link a la segunda parte:
http://brmcc.blogspot.com/2013/12/aplicaciones-hibridas-ioc-con-windows_3.html