Para nadie es un secreto que soy un fanático del modelo serverless en general y de Azure Functions en particular, habiendo dedicado unos cuantos artículos a cubrir este servicio de Azure, es que es simplemente un modelo de trabajo muy conveniente para varios casos de uso, y que hoy con motivo del Microsoft Build 2024 tiene uno de sus cambios mas trascendentes desde su lanzamiento y es el nuevo plan Azure Functions Flex.
No nos entretendremos explicando cómo funciona el servicio, solo debemos recordar Azure Functions se basa en proporcionar una abstracción al desarrollador, donde no tenemos que interactuar con una máquina virtual, por mas que por detrás haya una, y que su modelo de trabajo se orienta esencialmente a los eventos, donde un evento puede ser una invocación HTTP, un timer, la inserción de un elemento en una cola, etc. Y con esos pilares se pueden construir aplicaciones cloud native muy interesantes.
El caso es que a pesar de todo su poder Azure Functions tiene algunas limitaciones que siempre deben tenerse en cuenta al momento de diseñar una aplicación:
- El cold start: un modelo serverless “puro” (llamado modo Consumo en Azure) en teoría se basa en que el recurso de computo no esta asignado de manera dedicada al cliente, sino que solo se asigna cuando haya necesidad (o sea cuando el Functions es invocado), pero esto implica que haya un tiempo de espera mientras el recurso se inicializa y se asigna para su uso, dicho tiempo de espera se conoce como “cold start” y puede ser inconveniente en los casos de uso en que se requiera inmediatez, esta situación ha llevado a que se tenga que recurrir a planes como:
- App Service o Premium: esto consiste básicamente en tener el recurso de computo permanentemente asociado al cliente, evitando el cold start, aunque teniendo el inconveniente de tener que pagar por el recurso de forma permanente, aun cuando no se haga uso de el, en todo caso esto puede ser aceptado ya que nos permite hacer uso de una funcionalidad muy interesante y necesaria:
- VNET Integration: ha sido inevitable y totalmente lógico, que las organizaciones hayan ido ordenando sus diversos recursos en la nube mediante redes privadas (VNETs y subnets), lo cual permite el desarrollo de infraestructuras hibridas que comuniquen el mundo on premise con el mundo cloud, y obviamente no exponer a Internet recursos sensibles. El problema es que los Azure Functions de modo Consumo no pueden vincularse a una VNET, por lo que si se quiere trabajar en un modelo orientado a eventos, se hace necesario usar los planes App Service o Premium.
- Pocas opciones de dimensionamiento: cuando se usa el modo Consumo NO se puede dimensionar el recurso de cómputo que nos atendera cuando sea invocado, si queremos precisar que tan potente será este necesariamente debemos recurrir a los modo App Service o Premium.
Y bueno, dirán, ¿por qué tanto repaso? Es que el día de hoy en el Microsoft Build se ha anunciado el Public Preview del nuevo plan Azure Functions Flex Consumption, que básicamente nos ofrece un modelo basado en el modo Consumo, pero con las siguientes ventajas:
Enrolamiento a VNET: Como lo mencione anteriormente, esto va a permitir que nuestras aplicaciones serverless puedan acceder a recursos (BD, APIs, etc) alojados en nuestras redes privadas (VNETs) e inclusive a servicios publicados en nuestras redes on premise, esto definitivamente va a ser un espaldarazo para la adopción de Azure Functions en mas casos de uso.
Nótese la diferencia entre un Function en plan Consumption “tradicional” y una con el plan Flex Consumption
¡¡No puedo sino insistir que esto va a desbloquear la elección de Azure Functions para varios casos de uso, a probarlas!!
Escalamiento Flexible: Uno de los pilares del modelo serverless ha sido la capacidad de ir generando mas instancias de computo conforme la demanda iba aumentando, pero a menos que usaras un plan App Service o Premium, uno no podía elegir el “tamaño” base del recurso de computo que te iba a atender, esto cambia con Consumption Flex ya que uno puede elegir entre estos tamaños de nuestra instancia: 2048MiB y 4096 MiB de RAM, con lo cual si sabemos que cada operación es pequeña iremos por una instancia pequeña, pero si cada proceso es mas intensivo en memoria pues elegiremos un tamaño mas grande, esto nos da un modelo de flexibilidad diferente al que ya existía en App Service o Premiun.
Pero ojo, la flexibilidad ahora no solo viene por elegir el tamaño en el modo Consumo, sino también por la forma en que se puede gestionar el reparto de procesos en nuestras instancias, para lo cual veamos el siguiente gráfico:
Como se puede ver, aquí tenemos dos ejemplos diferentes de reparto de carga para 10 peticiones HTTP, un el primer caso la instancia solo tolera una ejecución por vez, por lo cual obviamente se han tenido que levantar un total de 10 instancias a la vez, por otro lado en el ejemplo de la derecha se opto porque cada instancia pueda ejecutar hasta dos procesos en paralelo, y consecuentemente solo se han tenido que provisionar 5 instancias para atender la carga. Como es natural esto nos permitirá personalizar nuestros modelos de reparto de carga, balanceando lo intensivo de recursos que sean nuestros métodos y/o que tan demandados sean, pero no nos preocupemos tanto aun, Azure nos proveerá con opciones por defecto razonables para empezar a trabajar.
UPDATE: Considerando que puede ser complicado definir la configuración óptima de nuestros Flex Consumption también se ha lanzado el Performance Optimizer basado en Azure Load Testing, que nos permitirá hacer las pruebas a fin de obtener la configuración mas adecuada para nuestros casos de uso.
“Always Ready”: siempre puede haber escenarios en que se quiera reducir el “cold start” a 0, y eso inevitablemente nos va a llevar a tener el recurso de computo ya provisionado, en este caso Consumption Flex nos permite asignar instancias que siempre estarán disponibles para una función o grupo de funciones, como se ve aquí:
Pero uno dirá, tenemos una base fija y luego escalamos bajo demanda ¿y eso de que nos vale? ¿acaso no es lo mismo que teníamos en Premium o App Service? Pues no, para empezar, comparemos con los tamaños de App Service:
Y la cosa no acaba aquí, releeamos lo que puse arriba “instancias que siempre estarán disponibles para una función o grupo de funciones” lo cual quiere decir que, si nuestra aplicación tiene métodos que no requieren respuesta inmediata, como el atender a un timer o a la llegada de un archivo a un storage, no asignaremos Always Ready, pero si por el contrario hay métodos HTTP que requieren respuesta inmediata, podremos hacer uso de la funcionalidad y garantizar la performance. Todo esto nos permite optimizar nuestra factura garantizando la performance global de la aplicación.
Como pueden notar, estoy muy entusiasmado por este lanzamiento, pero no puedo dejar de comentar unos detalles a tener en cuenta antes de que vayamos a correr a migrar nuestras Functions actuales:
- Consumption Flex trabaja con las siguientes versiones de lenguajes Java 11/17, Node 20, Python 3.1x y ….Net 8 Isolated, siendo este ultimo caso un escenario algo complicado, porque el modo Isolated fue introducido recién en .Net 8, y la estructura de los proyectos es diferente con respecto al tradicional In Process, modo en el que han sido implementados los diversos Functions desplegados por el mundo, es que … era el único modo disponible. En el caso de Node, básicamente tendremos que aplicar los mismos criterios que implican una migración a Runtime 4 y a la nueva estructura de proyectos de Node.
- Toca repasar bien la estrategia de redes privadas en nuestras organizaciones, porque si bien vamos a poder enrolar nuestros Functions a una VNET, el escalamiento horizontal al que podamos llegar va a estar limitado por el tamaño de la subnet en que alojemos a nuestros proyectos, así que toca planificar con buen criterio.
En todo caso, la tecnología ya está disponible desde hoy, en modo preview, así que toca probarla y sacarle el jugo para optimizar nuestros desarrollos cloud native.
¡Como siempre puedes compartirme tus comentarios respecto a esta tecnología y a las otras novedades del Build! Te leo.