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.

 





No comments:

Post a Comment