Cómo primer post del blog hablaré de programación asíncrona en netcore y porque debemos darle una mayor importancia, para ello voy a dividir este post en 3 partes o si no se hará muy largo 😀. En esta primera parte me centraré en explicar cuál son los beneficios de la programación asíncrona y explicar el funcionamiento de async y await.

¿Qué es la programación asíncrona?

Cuando se habla de programación asíncrona se tiende asociar a mejor rendimiento de una aplicación del lado del cliente y comúnmente a la responsividad que tenga esta con el usuario. Por ejemplo en Typescript al utilizar async y await liberamos el hilo de ejecución de Javascript lo que permite que la aplicación siga respondiendo a otras acciones.

En el caso de una aplicación de servidor, como sería una escrita en netcore, la definición va un poco más allá a la responsividad de la aplicación.

Para ilustrar en qué nos beneficia la programación asíncrona primero veamos cómo funciona un proceso síncrono en netcore:

data/admin/2020/8/1-Sincrono.jpg Cuando se realiza una solicitud HTTP hacia el servidor se solicita un hilo de ejecución al threadpool, todo el tiempo que demore en completarse dicha solicitud mantendrá el hilo de ejecución en modo de espera, por ende, no podrá ser utilizado en otra solicitud HTTP. Por ejemplo si llamamos a un recurso externo, descargamos un archivo o simplemente realizamos una consulta a la base de datos que demore demasiado. Todo ese tiempo el hilo de ejecución quedará bloqueado. Si llega otra solicitud se solicitará un nuevo hilo de ejecución ocurriendo el mismo escenario.

El problema surge cuando son demasiadas las solicitudes que llegan a nuestro servidor, puede llegar un momento en donde todos los hilos de ejecución se encuentren ocupados con otras solicitudes HTTP, como lo muestra la imagen en el la solitud 3.

Es aquí en donde se nos presenta un problema de escalabilidad a nuestra aplicación, podríamos solucionarlo escalando la infraestructura de nuestra aplicación.

Hay dos formas de escalar aplicaciones:

data/admin/2020/8/Escalabilidad-Horizontal.jpg

  • Escalabilidad horizontal: En la escalabilidad horizontal se agregan más servidores o máquinas virtuales de manera horizontal. Este es uno de los mecanismos más usado para escalar aplicaciones, pero por otro lado también tiene un costo. Si tenemos un servicio cloud, tendremos que pagar más recursos.

data/admin/2020/8/Escalabilidad-Vertical.jpg

  • Escalabilidad vertical: Para escalar de manera vertical se agregan más recursos al servidor: Aumentar la memoria ram, Mejorar el disco duro etc.

Es el la escalabilidad vertical es en donde como programadores podemos colocar nuestro granito de arena al utilizar mejor los recursos y programar de manera asíncrona.

data/admin/2020/8/Asincrono.jpg

Ilustrando el mismo ejemplo anterior, cuando se realiza una solicitud al servidor se solicitará un hilo de ejecución al threadpool, pero a diferencia de la llamada síncrona, el hilo de ejecución inmediatamente queda liberado, independiente si se demora la solicitud. Esto da la posibilidad a que otras solicitudes tengan hilos de ejecución disponibles y la aplicación siga funcionando sin problemas.

Cuando la solicitud asíncrona finaliza, se retornar al contexto en donde quedo previamente la llamada y continua con la ejecución de la operación.

¿Cómo funciona en netcore?

En .net (> framework 4.5) y netcore podemos transformar una operación síncrona en una operación asíncrona utilizando los keyword async y await.

El keyword async es un modificador que se agrega a la firma del método para convertirlo en asíncrono, pero debe ir acompañado, se debe agregar el keyword await, el cual le indica al compilador que no puede continuar hasta que el proceso termine. Esto permite que el flujo de ejecución retorne al consumidor ocasionando que se libere el hilo utilizado por el proceso.

  • Veamos un ejemplo:

data/admin/2020/8/Steps-Async.jpg

Imaginemos que tenemos un api rest que nos devuelven películas. Tenemos un método principal marcado con async y llamando a un método GetMovies.

El flujo de ejecución del programa será el siguiente:

  1. MyProccessAsync
  2. GetMoviesAsync
  3. GetMoviesIds
  4. GetAllMoviesAsync
  5. Se devuelve al método principal y como tiene un await se devuelve al consumidor.