Azure Functions – Serverless Backends

Últimamente se oye bastante hablar de serverless backend. Esta expresión puede sugerir implementaciones de servidor sin… servidor. Pero no, la realidad es que dicha expresión define una arquitectura en la cual no nos preocupamos para nada del servidor. Existir, existe, pero es totalmente transparente (o casi) para nosotros.

Es una astracción superior a la que ofrece un sistema PaaS. Tomemos un ejemplo de PaaS en Azure, como las web apps. Efectivamente, con una web app tenemos un nivel de abstracción relativamente alto: nos olvidamos de instalar un servidor en una máquina virtual y nos olvidamos de muchas tareas de administración. Con muy poco esfuerzo por nuestra parte podemos tener nuestra aplicación o API HTTP desplegada en una aplicación web con capacidad de escalar según sea necesario. Pero, a pesar de esas facilidades, seguimos viendo claramente un servidor: desplegamos en la webapp, configuramos la webapp, escalamos la webapp. El servidor sigue estando presente, solo que es mucho más sencillo de configurar que el sistema equivalente en IaaS u on-premise.

En un sistema tipo serverless backend, la única tarea realmente indispensable que hay que hacer es subir código y este se ejecuta de forma casi inmediata. No hay apenas configuración. No vemos cual es el servidor subyacente que ejecuta el código. El concepto de servidor “desaparece”: es nuestro código y se ejecuta. No hay que preocuparse de nada más. PaaS vino para simplificarnos la vida respecto IaaS y el serverless backend viene para simplificarla todavía más.

En Azure este paradigma se encarna mediante las Azure Functions que son exactamente lo que su nombre indica: funciones de código que se suben a Azure y se empiezan a ejecutar.

Creando una función de Azure

La creación no podría ser más sencilla, podemos codificar nuestra función directamente desde el portal de Azure.

Lo primero que debemos hacer es agregar una Function App. No es más que un contenedor donde vamos a tener todas nuestras funciones. Para ello desde el portal de Azure pulsamos agregar un nuevo elemento, tecleamos “functions” en el buscador y nos aparecerá la opción:

clip_image002

Pulsamos el botón de Create, rellenamos los datos (básicamente el nombre de nuestra function app) y ya podemos empezar.

Con esto no hemos creado ninguna azure function, solo hemos creado su contenedor. Una vez esté creado ya lo veremos dentro del resource group que hayamos elegido:

clip_image003

Si abrimos la function app (el icono con el rayo) se nos abre la interfaz para añadir funciones directamente desde el portal de Azure:

clip_image005

Lo primero que se nos pide es que tipo de función queremos añadir. Básicamente tenemos tres tipos posibles:

1. Timer: Funciones que se ejecutan basadas en un temporizador. Se pueden ejecutar cada 5 minutos, cada día a las 15 en punto o los domingos las 8 de la mañana por poner unos ejemplos.

2. Data Processing: Funciones que se ejecutan en base a triggers lanzados por otros elementos de Azure. Hay una gran variedad de triggers disponibles tales como que se cree un fichero en un storage, que llegue un evento via service bus o un elemento nuevo en una cola de Azure, entre otros.

3. Webhook + API: Funciones que se integran con APIs externas que soporten webhooks. P. ej. Github los soporta, así que sería posible hacer una función que se ejecutara cada vez que alguien comentara una issue en GitHub.

En función del escenario elegido (y del lenguaje C# o JavaScript), veremos el código inicial de nuestra función. P. ej. la siguiente captura muestra el código para una función de tipo “Data Processing”:

clip_image007

Podemos usar el propio portal para configurar los triggers que dispararán dicha función. Para ello, pulsamos sobre la opción Integrate de la barra de la izquierda, y de forma totalmente gráfica podremos configurar los triggers de nuestra función:

clip_image009

Además del trigger podemos especificar entradas opcionales para nuestra función (p. ej. un documento en una cola de Azure, un documento de DocumentDb, …) y también salidas opcionales (fichero a escribir, mensaje a mandar,). Estas entradas y salidas se reciben como parámetros en nuestra función.

Como se ha comentado el código se escribe en el portal:

clip_image011

Desde el propio portal podemos guardar la función, lo que automáticamente la compilará. La función se guarda siempre en un fichero run.csx (para el caso de C#) o index.js (para el caso de JavaScript (NodeJS)).

Por supuesto es posible usar cualquier editor para crear no solo el fichero run.csx (o index.js) y subir luego el contenido a Azure. Al subirlo, automáticamente la función se compilará y estará lista para ejecutarse. Para subir el contenido se puede usar Git o incluso FTP.

La configuración (los triggers que disparan la función, o cada cuando se ejecuta, sus entradas y sus salidas) se guarda en un fichero json. Podemos ver su contenido si pulsamos el botón “Advanced Editor” dentro de la sección “Integrate”. La siguiente captura muestra el editor gráfico:

clip_image013

Si pulsamos sobre el botón “Advanced editor” vemos el contenido del fichero json:

clip_image015

Desplegar una Azure function es desplegar el fichero run.csx (o index.js) y su fichero json de configuración. No es necesario hacer nada más. No hay que compilar nada, en caso de ser necesario la compilación ocurre en Azure.

Webjobs y Azure functions

Azure functions es una evolución de los actuales Webjobs. Muchas de las tareas que se automatizaban en Webjobs pueden automatizarse en Azure functions. La diferencia fundamental es, básicamente, de concepto. Los Webjobs son un escenario PaaS, donde el servidor (una Webapp) es claramente explícito. El webjob se despliegua de forma tradiciona y la webapp que lo contiene se configura como cualquier otra.

Una Azure function se ejecuta a través de una webapp. Se parece mucho a los webjobs, pero esto para nosotros es totalmente transparente. A pesar de que es posible hacerlo, no necesitamos por norma general acceder a la webapp subyacente. En general, las Azure functions evolucionan los webjobs y los llevan a un nuevo nivel de simplicidad.

Resumiendo

Azure functions es la implementación del paradigma serverless backend, en el cual el servidor queda difuminado hasta casi poder ser ignorado. Una Azure function es una porción de código (realmente una función) que se ejecuta como causa de un disparador (puede ser un temporizador, una acción sobre un elemento de Azure (tal como un mensaje en un service bus) o la llegada de un webhook para integrarnos con cualquier API que los soporte). La función puede realizar cualquier operación que sea necesaria (p. ej. comprimir imágenes subidas a Azure, periódicamente limpiar una tabla en una base de datos SQL Azure o cualquier otra tarea). La ejecución de una Azure function puede realizar una tarea que actúe como disparador de otra Azure function, dando lugar a escenarios complejos.

ASP.NET MVC 5–Binding de parámetros dinámicos

Estando trabajando en un proyecto con ASP.NET MVC 5 surgió la “necesidad” (impulsada por la pereza) de tener un controlador MVC (ojo, no WebApi) que recibiese datos en JSON via POST y que devolviese una vista parcial. Hasta ahí nada raro (eso se soporta de serie desde MVC3), donde la pereza intervino es que queríamos que el parámetro del controlador fuese dynamic en lugar de un tipo en concreto. Y eso, en MVC5 no está soportado. Veamos por qué y como podemos solucionarlo 😉

Nota: Todo lo dicho en este post afecta solo a MVC5. En WebApi y en MVC6 (ASP.NET Core) las cosas funcionan distinto.

Continúa leyendo ASP.NET MVC 5–Binding de parámetros dinámicos

Algunas consideraciones sobre las structs

El otro día un tweet de Juan Quijano, animó una pequeña discusión sobre la diferencia entre clases y estructuras en .NET. Este no es el primer post que escribo al respecto, pero bueno, aprovechando la coyuntura vamos a comentar algunas de las cosas que se mencionaron en el pequeño debate que generó el tweet de Juan.

Continúa leyendo Algunas consideraciones sobre las structs

C#–Buenas prácticas en constructores

Escribir el constructor de una clase es algo que parece trivial… A fin de cuentas, el constructor se encarga de construir un objeto, ¿no? Pero la realidad es que escribir constructores no es tan sencillo como parece. ¿Qué significa “construir” un objeto? Por supuesto cada clase tendrá sus propias necesidades, pero hay una serie de guías y buenas prácticas que nos pueden ayudar a tomar ciertas decisiones. A esto va dedicado este post.

Continúa leyendo C#–Buenas prácticas en constructores

WebApi 2–Leer datos desde los headers

En un curso que he impartido sobre WebApi 2 me han comentado un escenario en el que mandaban un conjunto de datos en varias cabeceras HTTP propias y querían leer esos datos desde los controladores.

La verdad es que hay varias maneras de hacer eso en WebApi 2 y vamos a analizar algunas de ellas en este post. Eso nos servirá como excusa para recorrer algunos de los mecanismos de extensibilidad del framework.

Continúa leyendo WebApi 2–Leer datos desde los headers

Atributos con comportamiento: un mal diseño

Tarde o temprano, todo desarrollador ya se de ASP.NET MVC o WebApi necesita hacer sus propios filtros para validaciones propias de peticiones, logging, comprobación de precondiciones… En fin, lo habitual para lo que se usan los filtros, vamos.

Y tarde o temprano este desarrollador se da cuenta de que su filtro debería acceder a un determinado servicio de su aplicación: quizá necesita hacer una consulta a la bbdd, o a un determinado elemento de negocio, o acceder al sistema de logging o cualquier cosa más. Y este desarrollador, que conoce (y usa) la inyección de dependencias se encuentra con que no es posible inyectar dependencias en un filtro. Algunos desarrolladores buscaran cualquier otra alternativa, algunas mejores que otras, pero ninguna satisfactoria: crear un singleton, una clase estática o instanciar directamente el objeto en lugar de obtenerlo como una dependencia (y rompiendo cualquier abstracción realizada). Otros desarrolladores continuarán en su búsqueda. En esta fase de terquedad que nos caracteriza, pensaran “no, no es posible. Tiene que ver alguna manera”.

netstandard–El “estándar” que viene

Cuando .NET salió, las cosas eran muy sencillas: había una sola versión de .NET, el .NET Framework, así que como mucho debíamos saber para que versión de .NET era una determinada librería. “Oh, la librería es solo para .NET 2.0 y yo uso .NET 1.1, que mala suerte”. Al margen de eso no había mucho más, todos teníamos claro que significaba .NET.

Continúa leyendo netstandard–El “estándar” que viene

Creando formateadores de salida en asp.net core

Cuando salió WebApi lo hizo con la negociación de contenido incorporada de serie en el framework. Eso venía a significar, básicamente, que el framework intentaba suministrar los datos en el formato en que el cliente los había pedido. La negociación de contenido se basa (generalmente) en el uso de la cabecera accept de HTTP: el cliente manda en esa cabecera cual, o cuales, son sus formatos de respuesta preferidos. WebApi soporta de serie devolver datos en JSON y XML y el sistema es extensible para crear nuestros propios formatos.

“MVC clásico” (es decir hasta MVC5) no incluye soporte de negociación de contenido: en MVC si queremos devolver datos en formato JSON, debemos devolver explícitamente un JsonResult y si los queremos devolver en XML debemos hacerlo también explícitamente.

En ASP.NET Core tenemos a MVC6 que unifica a WebApi y MVC clásico en un solo framework. ¿Como queda el soporte para negociación de contenido en MVC6? Pues bien, existe soporte para ella, pero dependiendo de que IActionResult devolvamos en nuestros controladores. Así, si en WebApi la negociación de contenido se usaba siempre y en MVC clásico nunca, en MVC6 la negociación de contenido aplica solo si la acción del controlador devuelve un ObjectResult (o derivado). Esto nos permite como desarrolladores decidir sobre qué acciones de qué controladores queremos aplicar la negociación de contenido. Es evidente que aplicarla siempre no tiene sentido: si devolvemos una vista Razor su resultado debe ser sí o sí un HTML que se envía al cliente. No tendría sentido aplicar negociación de contenido sobre una acción que devolviese una vista. De hecho la negociación de contenido tiene sentido en APIs que devuelvan datos (no vistas) y en MVC6 para devolver datos tenemos a ObjectResult, así que es lógico que sea sobre este resultado donde se aplique la negociación de contenido.

En WebApi la negociación de contenido estaba gestionada por los formateadores (formatters). Básicamente a cada content-type se le asociaba un formateador. Si el cliente pedía datos en un determinado content-type se miraba que formateador podía devolver datos en dicho formato. Si no existía se usaba por defecto el formateador de JSON. En MVC6 se ha mantenido básicamente dicho esquema.

Continúa leyendo Creando formateadores de salida en asp.net core

Middlewares de autenticación en asp.net core

La autenticación y autorización de peticiones es una de las funcionalidades que más quebraderos da en el desarrollo de aplicaciones en ASP.NET. Además es que ha ido cambiando con el tiempo… En un escenario de internet, en ASP.NET clásico, ya fuese Webforms o MVC usábamos FormsAuthentication. Por otra parte cuando apareció WebApi, incorporó sus propios mecanismos de autenticación y autorización, generalmente basados en la implementación de MessageHandlers.

Continúa leyendo Middlewares de autenticación en asp.net core

Autenticación por AAD en ASP.NET Core

Este es un post introductorio, de una serie de posts, donde veremos como podemos integrar ASP.NET Core y Azure Active Directory (AAD). En este primer escenario el objetivo es tener una aplicación web, donde se requiera hacer login contra AAD para autenticarse.

Nota: El post está basado en la RC1 de ASP.NET Core… Lo digo porque bueno, a saber que romperán mejorarán en futuras versiones, pues igual algo cambia :)

Continúa leyendo Autenticación por AAD en ASP.NET Core