Español
Microsoft.com/Latinoamérica | Microsoft.com/Spain
Microsoft
Buscar en Microsoft.com:
| MSDN Library | Descarga | Centros de desarrollo | Eventos | Mapa | Países | Contacto
 
Artículos técnicos en Español 
   Inicio MSDN >  Artículos técnicos en español


Métodos Web asíncronos del lado del servidor

Matt Powell
Microsoft Corporation

2 de octubre de 2002

Resumen: Matt Powell muestra cómo hacer uso de métodos Web asíncronos en el lado del servidor para crear servicios Web de Microsoft ASP.NET de alto rendimiento. (8 páginas impresas.)


Introducción

En mi 3ª columna de septiembre (en inglés), escribí sobre las llamadas asíncronas a servicios Web a través de HTTP utilizando las funciones del lado del cliente de Microsoft® .NET Framework. Este enfoque resulta extremadamente útil para realizar llamadas a un servicio Web sin bloquear la aplicación ni generar un conjunto de subprocesos en segundo plano. Ahora vamos a considerar los métodos Web asíncronos que ofrecen funciones similares del lado del servidor. Los métodos Web asíncronos son similares al alto rendimiento que proporciona el enfoque HSE_STATUS_PENDING para escribir extensiones ISAPI, pero sin la sobrecarga de codificación necesaria para administrar su propio grupo de subprocesos y con todas las ventajas de su ejecución en código administrado.

Calificar
Buscar
Mi Panorama SOS
Escribe para Nosostros

En primer lugar, consideraremos los métodos Web de Microsoft® ASP.NET síncronos normales. La respuesta para un método Web síncrono se envía cuando se devuelve desde el método. Si una solicitud lleva un período de tiempo relativamente prolongado en completarse, el subproceso que esté procesando la solicitud se encontrará en uso hasta que finalice la llamada al método. Desafortunadamente, la mayor parte de llamadas prolongadas se deben, por ejemplo, a consultas extensas a la base de datos, o quizás a una llamada a otro servicio Web. Por ejemplo, si realiza una llamada a la base de datos, el subproceso actual espera a que se complete dicha llamada. El subproceso espera simplemente sin hacer nada hasta que recibe una respuesta de la consulta. Surgen problemas similares cuando un subproceso espera a que finalice una llamada a un socket TCP o a un servicio Web del servidor.

Los subprocesos en espera son problemáticos, sobre todo en situaciones de sobrecarga en servidores. Los subprocesos en espera no hacen nada productivo, como dar servicio a otras solicitudes. Lo que necesitamos es una forma de iniciar un proceso extenso en segundo plano en un servidor, pero devolver el subproceso actual al grupo de procesos de ASP.NET. A continuación, cuando finalice el proceso extenso en segundo plano, deberíamos invocar una función de devolución de llamada para que podamos finalizar el procesamiento de la solicitud y, de alguna manera, señalar la finalización de la solicitud a ASP.NET. Resulta que esta función proviene de ASP.NET con métodos Web asíncronos.

Funcionamiento de los métodos Web asíncronos

Cuando se escribe un servicio Web ASP.NET típico utilizando métodos Web, Microsoft® Visual Studio® .Net simplemente compila el código para crear el ensamblado que se llamará cuando se reciban solicitudes para sus métodos Web. El ensamblado mismo no tiene por qué saber nada acerca de SOAP. Por lo tanto, cuando se inicie la aplicación por primera vez, el controlador de ASMX debe reflejarse sobre el ensamblado para determinar qué métodos Web se exponen. Para solicitudes síncronas normales, es sólo cuestión de buscar los métodos con un atributo WebMethod asociado y de establecer la lógica para llamar al método apropiado basándose en el encabezado HTTP SOAPAction.

Para solicitudes asíncronas, durante la reflexión el controlador de ASMX busca los métodos Web con un tipo determinado de firma que reconoce como asíncronos. En concreto, busca un par de métodos que cumplan las reglas siguientes:

  • Hay un método Web BeginXXX y EndXXX donde XXX hace referencia a cualquier cadena que represente el nombre del método que desea exponer.
  • La función BeginXXX devuelve una interfaz IAsyncResult y toma como sus dos últimos parámetros de entrada un parámetro AsyncCallback y un objeto, respectivamente.
  • La función EndXXX toma como único parámetro una interfaz IAsyncResult.
  • Ambas deben estar marcadas con el atributo WebMethod.

Si el controlador de ASMX encuentra dos métodos que reúnan todos estos requisitos, expondrá el método XXX en su WSDL como si fuera un método Web normal. El método aceptará como entrada los parámetros definidos antes del parámetro AsyncCallback en la firma para BeginXXX y devolverá lo que devuelva la función EndXXX. Así, si tuviéramos un método Web cuya declaración síncrona fuera similar a:

    [WebMethod]
    public string LengthyProcedure(int milliseconds) {...}

Entonces, una declaración asíncrona sería similar a:

    [WebMethod]
    public IAsyncResult BeginLengthyProcedure(
                            int milliseconds, 
                            AsyncCallback cb, 
                            object s) {...}

    [WebMethod]
    public string EndLengthyProcedure(IAsyncResult call) {...}

El WSDL para cada una sería el mismo.

Una vez que el controlador de ASMX se refleje en un ensamblado y detecte un método Web asíncrono, deberá administrar solicitudes para dicho método de forma diferente que para las solicitudes síncronas. En vez de llamar a un método simple, llama al método BeginXXX. Deserializa la solicitud entrante en los parámetros para que pase a la función (como lo hace con las solicitudes síncronas), pero también pasa el puntero a una función de devolución de llamada interna como parámetro AsyncCallback extra en el método BeginXXX.

Este enfoque es de forma intencionada muy similar al paradigma de programación de .NET Framework para aplicaciones cliente del servicio Web. En el caso de la compatibilidad del lado del cliente para llamadas asíncronas de servicios Web, se liberan subprocesos bloqueados para el equipo cliente, mientras que en el lado del servidor se liberan subprocesos bloqueados en el equipo servidor. Sin embargo, existen dos diferencias fundamentales. En primer lugar, en vez de que el código de servidor llame a las funciones BeginXXX y EndXXX, lo hará el controlador de ASMX. En segundo lugar, escribirá el código para las funciones BeginXXX y EndXXX en vez de utilizar el código generado por WSDL.EXE o el Asistente "Agregar referencia Web" en Visual Studio .NET. Sin embargo, el resultado es el mismo: liberar subprocesos para que puedan realizar otros procesamientos.

Una vez que el controlador de ASMX llama a la función BeginXXX del servidor, devolverá el subproceso al grupo de subprocesos del proceso para que pueda administrar cualquier otra solicitud que se reciba. El HttpContext para la solicitud aún no se liberará. El controlador de ASMX esperará hasta que se llame a la función de devolución de llamada que pasó a la función BeginXXX para finalizar el procesamiento de la solicitud.

Una vez llamada la función de devolución de llamada, el controlador de ASMX llamará a la función EndXXX para que el método Web pueda finalizar cualquier procesamiento que necesite realizar y se puedan proporcionar los datos de retorno que se serializarán en la respuesta de SOAP. Sólo cuando se envíe la respuesta después de que vuelva la función EndXXX se liberará el HttpContext para la solicitud.

Un método Web asíncrono sencillo

Para ilustrar los métodos Web asíncronos, comenzaré con un sencillo método Web síncrono denominado LengthyProcedure, cuyo código aparece a continuación. Posteriormente, veremos cómo hacer lo mismo de forma asíncrona. LengthyProcedure simplemente bloquea el número determinado de milisegundos.

[WebService]
public class SyncWebService : System.Web.Services.WebService
{
    [WebMethod]
    public string LengthyProcedure(int milliseconds) 
    { 
        System.Threading.Thread.Sleep(milliseconds);
        return "Correcto"; 
    }
}

Ahora convertiremos LengthyProcedure en un método Web asíncrono. Debemos crear una función BeginLengthyProcedure y una función EndLengthyProcedure, como se ha descrito anteriormente. Recuerde que nuestra llamada BeginLengthyProcedure deberá devolver una interfaz IAsyncResult. En este caso, voy a hacer que nuestra llamada BeginLengthyProcedure realice una invocación al método asíncrono utilizando un delegado y el método BeginInvoke en dicho delegado. La función de devolución de llamada pasada a BeginLengthyProcedure se transferirá al método BeginInvoke en nuestro delegado y la interfaz IAsyncResult devuelta de BeginInvoke será devuelta por el método BeginLengthyProcedure.

Se llamará al método EndLengthyProcedure cuando haya finalizado nuestro delegado. Llamaremos al método EndInvoke en el delegado que pasa a la interfaz IAsyncResult que recibimos como entrada en la llamada EndLengthyProcedure. La cadena devuelta será la que devuelva nuestro método Web. Este es el código:

[WebService]
public class AsyncWebService : System.Web.Services.WebService
{
    public delegate string LengthyProcedureAsyncStub(
        int milliseconds);

    public string LengthyProcedure(int milliseconds) 
    { 
        System.Threading.Thread.Sleep(milliseconds);
        return "Correcto"; 
    }

    public class MyState 
    { 
        public object previousState; 
        public LengthyProcedureAsyncStub asyncStub; 
    }

    [ System.Web.Services.WebMethod ]
    public IAsyncResult BeginLengthyProcedure(int milliseconds, 
        AsyncCallback cb, object s)
    {
        LengthyProcedureAsyncStub stub 
            = new LengthyProcedureAsyncStub(LengthyProcedure);
        MyState ms = new MyState();
        ms.previousState = s; 
        ms.asyncStub = stub;
        return stub.BeginInvoke(milliseconds, cb, ms);
    }
  
    [ System.Web.Services.WebMethod ]
    public string EndLengthyProcedure(IAsyncResult call)
    {
        MyState ms = (MyState)call.AsyncState;
        return ms.asyncStub.EndInvoke(call);
    }
}

Cuándo resultan más adecuados los métodos Web asíncronos

Deben tenerse en cuenta varias cuestiones a la hora de determinar si los métodos Web asíncronos son adecuados para la aplicación. En primer lugar, la función BeginXXX para la llamada debe devolver una interfaz IAsyncResult. Las interfaces IAsyncResult se devuelven a partir de ciertas operaciones asíncronas de E/S para obtener acceso a secuencias, realizar llamadas de Microsoft® Windows® Sockets, realizar E/S de archivos, interactuar con otros dispositivos de hardware, llamar a métodos asíncronos y, por supuesto, llamar a otros servicios Web. Probablemente deseará obtener la interfaz IAsyncResult a partir de uno de estos tipos de operaciones asíncronas, de modo que pueda devolverla desde la función BeginXXX. La otra opción es crear su propia clase que implemente la interfaz IAsyncResult, pero, de todos modos, probablemente tendrá que empaquetar una de las implementaciones de E/S anteriormente mencionadas.

Para casi todas las operaciones asíncronas que hemos mencionado, resulta muy adecuado utilizar métodos Web asíncronos para empaquetar la llamada asíncrona del servidor al tiempo que da como resultado un código del servicio Web más eficaz. La excepción es cuando se realizan llamadas de método asíncrono con delegados. Éstos harán que las llamadas de método asíncrono se ejecuten en un subproceso del grupo de subprocesos del proceso. Desafortunadamente, estos son los mismos subprocesos que utiliza el controlador de ASMX para dar servicio a las solicitudes entrantes. De modo que, al contrario que las llamadas que realizan operaciones de E/S reales con recursos de hardware o de red, una llamada de método asíncrono que utilice delegados bloqueará uno de los subprocesos del proceso durante la ejecución. También podría bloquear el subproceso original y ejecutar el método Web de forma síncrona.

El siguiente ejemplo muestra un método Web asíncrono que llama al servicio Web del servidor. Ha marcado los métodos BeginGetAge y EndGetAge con el atributo WebMethod para que se ejecute de forma asíncrona. El código de este método Web asíncrono llama a un método Web del servidor denominado UserInfoQuery para obtener la información que necesita devolver. La llamada a UserInfoQuery se realiza de forma asíncrona y se pasa a la función AsyncCallback que se transfirió al método BeginGetAge. Esto provocará que se llame a la función de devolución interna cuando finalice la solicitud del servidor. La función de devolución de llamada llamará a nuestro método EndGetAge para finalizar la solicitud. En este caso, el código es mucho más simple que el del ejemplo anterior y tiene la ventaja adicional de que no inicia el procesamiento del servidor en el mismo grupo de subprocesos que da servicio a nuestras solicitudes de método Web de nivel medio.

[WebService]
public class GetMyInfo : System.Web.Services.WebService
{
    [WebMethod]
    public IAsyncResult BeginGetAge(AsyncCallback cb, Object state)
    {
        // Invocar a una llamada asíncrona de servicios Web.
        localhost.UserInfoQuery proxy 
            = new localhost.UserInfoQuery();
        return proxy.BeginGetUserInfo("Nombre del usuario", 
                                      cb, 
                                      proxy);
    }

    [WebMethod]
    public int EndGetAge(IAsyncResult res)
    {
        localhost.UserInfoQuery proxy 
            = (localhost.UserInfoQuery)res.AsyncState;
        int age = proxy.EndGetUserInfo(res).age;
        //  Realizar aquí cualquier procesamiento adicional en 
        //  los resultados desde la llamada de servicios Web.
        return age;
    }
}

Uno de los tipos de operaciones de E/S más comunes que se producen en un método Web es un llamada a una base de datos SQL. Desafortunadamente, Microsoft® ADO.NET por el momento no tiene definido un buen mecanismo de llamadas asíncronas y el simple empaquetado de una llamada SQL en una llamada de delegado asincrónica no ayuda en absoluto al departamento de eficacia. El almacenamiento de los datos en caché a veces es una solución, pero también se debe considerar el uso de Microsoft SQL Server 2000 Web Services Toolkit (en inglés) para exponer las bases de datos como servicio Web. Entonces, podrá utilizar la compatibilidad de .NET Framework para llamar a servicios Web de forma asíncrona para consultar o actualizar la base de datos.

Los conocimientos adquiridos para tener acceso a SQL mediante una llamada de servicios Web deben tomarse muy en serio por muchos de los recursos del servidor. Si ha estado utilizando sockets TCP para comunicarse con un equipo Unix o tiene acceso a algunas de las otras plataformas SQL disponibles mediante controladores de bases de datos de propietario (o incluso si tiene un recurso al que ha tenido acceso utilizando DCOM), podría utilizar los numerosos kits de herramientas de servicios Web disponibles en la actualidad para exponer los recursos como servicios Web.

Una de las ventajas de este enfoque es que se pueden aprovechar los avances en infraestructura de servicios Web del lado del cliente, como las llamadas asíncronas de servicios Web con .NET Framework. Así podrá obtener las funciones de llamadas asíncronas de forma gratuita y resultará que el mecanismo de acceso a clientes funcionará de forma eficaz con métodos Web asíncronos.

Agregar datos con un método Web asíncrono

En la actualidad, muchos servicios Web tienen acceso a varios recursos del servidor y agregan la información para el servicio Web cliente. Aunque la llamada a varios recursos del servidor agrega complejidad al modelo del método Web asíncrono, se gana mucho en términos de eficacia.

Por ejemplo, el método Web llama a dos servicios Web del servidor, Servicio A y Servicio B. Desde la función BeginXXX, puede llamar tanto al Servicio A como al Servicio B de forma asíncrona. Debería pasar a cada una de estas llamadas asíncrona su propia función de devolución de llamada. Para poder desencadenar la finalización del método Web después de recibir los resultados del Servicio A y B, la función de devolución de llamada proporcionada comprobará que ambas solicitudes han finalizado, realizará el procesamiento en los datos devueltos y, por último, llamará a la función de devolución de llamada pasada a la función BeginXXX. Esto desencadenará la llamada a la función EndXXX, que a su retorno hará que finalice el método Web asíncrono.

Conclusión

Los métodos Web asíncronos proporcionan un mecanismo eficaz en los servicios Web de ASP.NET Web para invocar a llamadas a servicios de servidor sin que se bloqueen los valiosos subprocesos del grupo de subprocesos del proceso mientras no realizan ninguna acción. En combinación con solicitudes asíncronas a recursos del servidor, un servidor puede maximizar el número de solicitudes simultáneas que puede administrar con sus métodos Web. Deberá tener en cuenta este enfoque al desarrollar aplicaciones de servicios Web de alto rendimiento.

 


A su servicio

Matt Powell es miembro del equipo MSDN Architectural Samples, en el que ha colaborado para desarrollar el innovador SOAP Toolkit 1.0. Entre otros logros de Matt, se encuentran el de ser coautor de Running Microsoft Internet Information Server (en inglés) de Microsoft Press, haber escrito numerosos artículos para revistas y contar con una encantadora familia en la que refugiarse cada día después del trabajo.

Ultima actualización: Lunes, 13 de Enero de 2003

©2005 Microsoft Corporation. Todos los derechos reservados. Condiciones de uso |Marcas registradas |Declaración de Privacidad
Microsoft
Hosted by www.Geocities.ws

1