Full IIS en Windows Azure

Una de las novedades del Sdk 1.3 de Windows Azure es el soporte completo a Internet Information Server (Full IIS), que permite disponer de todas las característica de IIS en Windows Azure.

Antes de la salida de esta versión, Windows Azure ya disponía de WebRoles que podían exponer endpoints HTTP.

Windows Azure para realizar esta labor no empleaba un IIS, por lo que no podíamos hacer uso de todas las características que este producto ofrece; directorios virtuales, múltiples sites, exponer múltiples endpoints, endpoints TCP etc…

Windows Azure hacía uso del componente Hosted Web Core (HWC), que como su nombre indica, es en núcleo del IIS, por lo que ofrece las características más importantes de IIS, pero no todas. Seguramente en muchos escenarios con la funcionalidad ofrecida por HWC sería más que suficiente.

Por ejemplo, usando la versión completa del IIS podremos tener varios sites dentro del mismo webrole, podremos tener múltiples endpoint (HTTP/HTTP/TCP) sobre el mismo WebRoles, directorios y aplicaciones virtuales etc…

Desde el punto de vista de la arquitectura este diagrama muestra cómo es el comportamiento de la aplicación cuando se hace uso del HWC y cuando se hace uso de la versión completa del IIS.

FullIIS

A nivel funcional, sí que habrá pequeñas diferencias, como por ejemplo, que desde el WebEntryPoint no se tendrá acceso al fichero de configuración de la aplicación (web.config) si se está en el modo Full IIS.

Por defecto, cuando se crea un nuevo WebRole se empleará la versión completa del IIS, aunque si queremos podríamos configurarlo para que haga uso únicamente del HWC. De este modo el comportamiento sería el mismo que tenía un WebRole con la versión anterior del Sdk.

Si creamos una aplicación nueva y añadimos un WebRole, una de las primeras cosas que podremos ver es que en la configuración de los endpoint pueden configurarse tantos endpoints como se quiera, pudiendo elegir tres tipos de protocolos; HTTP, HTTPS o TCP. Con la versión anterior, un WebRole sólo podía tener dos endpoints como mucho, uno HTTP y otro HTTPS.

image

La siguiente peculiaridad la encontraremos en el fichero ServiceDefinition.csdef, que contendrá lo siguiente:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole">
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>

Fijaros en el XML anterior que éste contiene la definición de los sites que contiene el WebRole y los endpoints asociados. En este caso existe un único site asociado un endpoint http que emplea el puerto 80.

El site “Web” se considera que el site por defecto y es el único en el que no debe indicarse la propiedad “physicalDirectory”. Si por ejemplo le cambiamos el nombre al site tendremos que añadir dicha propiedad, para indicar la ruta física dónde se encuentra.

Las rutas son path relativos al fichero ServiceDefinition.csdef. (WebRole es el nombre que le he dado al role)

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole" 
      xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole">
    <Sites>
      <Site name="MyCustomWebSite" physicalDirectory="..WebRole">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>

Sobre este fichero podremos hacer las modificaciones que consideremos para añadir más sites, directorios virtuales o lo que consideremos. Los conceptos son los mismos que manejamos al trabajar con IIS.

Por ejemplo, en el XML siguiente se configura un WebRole con dos sites. Los dos sites se encuentras asociados al mismo endpoint.

Se ha uso de la propiedad “hostHeader” que site debe responder en cada momento. En función de la URL de la que venga la petición, contestará un site u otro…lógicamente, en este caso es el mismo.

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole" 
      xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole">
    <Sites>
      <Site name="MyFirstCustomWebSite" physicalDirectory="..WebRole">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.myfirstsite.com"/>
        </Bindings>
      </Site>
      <Site name="MySecondCustomWebSite" physicalDirectory="..WebRole">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.mysecondsite.com"  />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>

Para poder probar en local este escenario es necesario modificar el fichero “host” de vuestro equipo, para que las URLs configuradas en el hostHeader apunten a la dirección 127.0.0.1.

Una vez configurado este escenario y si damos a F5 en Visual Studio, encontraremos el siguiente error:  “HTTP 400 Bad Request”.

El problema es que al haber cambiado la configuración por defecto, Visual Studio y el Compute Emulator no son capaces de encontrar el site por defecto que debe resolver la petición. Es por este motivo por el que toca realizar más cambios…

Si abrimos la herramienta del configuración del IIS  (con el modo depuración de Visual Studio arrancado) veremos que tenemos 2 sites temporales como los siguientes: (uno por cada site de la aplicación)

image

Tenemos que cambiar el binding de estos sites para que apunten a un puerto válido..y que no se esté usando!! Si ponemos www.myfirstsite.com:8081 en el navegador ya tendremos la aplicación contestando peticiones.

image

Para seguir viendo más características he añadido un nuevo proyecto a la solución de tipo WebApplication. No es un nuevo WebRole, es simplemente un nuevo proyecto web llamado SecondWebApp.

image

Podemos configurar cada site para que apunte a un proyecto diferente:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole" 
      xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole">
    <Sites>
      <Site name="MyFirstCustomWebSite" physicalDirectory="..SecondWebApp">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.myfirstsite.com"/>
        </Bindings>
      </Site>
      <Site name="MySecondCustomWebSite" physicalDirectory="..WebRole">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" hostHeader="www.mysecondsite.com"  />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>

Y si ejecutamos la aplicación (F5), veremos que en función de la URL que pongamos en el navegador contestará una aplicación u otra.

image

image

Otra posibilidad que tenemos es la de crear directorios o aplicaciones virtuales. En este ejemplo se ve cómo crear una aplicación virtual dentro de un site.

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="SampleWebRole" 
      xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebRole">
    <Sites>
      <Site name="Web" physicalDirectory="..WebRole">
        <VirtualApplication name="SecondApp" physicalDirectory="..SecondWebApp"></VirtualApplication>
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1"/>
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
    </Imports>
  </WebRole>
</ServiceDefinition>

Y vemos como poniendo la URL base me sale la aplicación principal y cómo si ponemos la URL de la aplicación virtual me responde la segunda aplicación.

image

En la URL añado el nombre de la aplicación virtual.

image

Espero que os haya sido de utilidad!

Ibon Landa

bon Landa lleva más de 15 años dedicado al desarrollo de software. Durante este tiempo ha trabajado en diferentes empresas en las cuáles ha podido trabajar en diferentes entornos y tecnologías. Actualmente está focalizado principalmente en tareas de desarrollo, arquitectura, en las herramientas del ciclo de vida y en todo lo relacionado con la plataforma de Cloud Computing Microsoft Azure, área en el que ha sido reconocido como MVP. Participa de forma activa en la comunidad, escribiendo su blog, manteniendo un portal sobre Microsoft Azure y colaborando con Microsoft y grupos de usuarios en eventos de formación, talleres y giras de producto.

Una respuesta a “Full IIS en Windows Azure”

  1. Hola Javier,

    Cuando defines dos sitios dentro del mismo rol tiene que indicar el atributo hostHeader dentro de la configuración, para indicar cuando debe contestar uno y cuándo el otro.

    El hostheader indica el dominio desde el cuál viene la petición.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *