Cómo Quarkus combina la programación imperativa y reactiva

Este año planeamos desarrollar seriamente temas de contenedores, Java nativo de la nube и Kubernetes. Una continuación lógica de estos temas será una historia sobre el marco Quarkus, ya consideró sobre Habré. El artículo de hoy trata menos sobre el diseño de "Java subatómico superrápido" y más sobre la promesa que Quarkus aporta a Enterprise.

Cómo Quarkus combina la programación imperativa y reactiva

Java y JVM siguen siendo extremadamente populares, pero cuando se trabaja con tecnologías sin servidor y microservicios nativos de la nube, Java y otros lenguajes JVM se usan cada vez menos porque ocupan demasiado espacio de memoria y son demasiado lentos para cargar, lo que los hace No es adecuado para su uso con contenedores de corta duración. Por suerte, esta situación está empezando a cambiar gracias a Quarkus.

¡Java subatómico ultrarrápido ha alcanzado un nuevo nivel!

42 lanzamientos, 8 meses de trabajo comunitario y 177 desarrolladores increíbles: el resultado de todo fue el lanzamiento en noviembre de 2019. Cuarcos 1.0, un lanzamiento que marca un hito importante en el desarrollo del proyecto y ofrece muchas características y capacidades interesantes (puedes leer más sobre ellas en anuncio).

Hoy le mostraremos cómo Quarkus combina modelos de programación imperativo y reactivo en un único núcleo reactivo. Comenzaremos con una breve historia y luego entraremos en detalles sobre qué es el dualismo central reactivo de Quarkus y cómo Java-Los desarrolladores pueden aprovechar estos beneficios.

Microservicios, arquitecturas impulsadas por eventos и sin servidor-funciones: todo esto, como dicen, va en aumento hoy en día. Recientemente, la creación de arquitecturas centradas en la nube se ha vuelto mucho más fácil y accesible, pero los problemas persisten, especialmente para los desarrolladores de Java. Por ejemplo, en el caso de las funciones y microservicios sin servidor, existe una necesidad urgente de reducir el tiempo de inicio, reducir el consumo de memoria y aún así hacer que su desarrollo sea más conveniente y agradable. Java ha realizado varias mejoras en los últimos años, como una funcionalidad ergonómica mejorada para contenedores, etc. Sin embargo, lograr que Java funcione correctamente en un contenedor sigue siendo un desafío. Así que comenzaremos analizando algunas de las complejidades inherentes de Java, que son particularmente agudas cuando se desarrollan aplicaciones Java orientadas a contenedores.

Primero, echemos un vistazo a la historia.

Cómo Quarkus combina la programación imperativa y reactiva

Corrientes y contenedores

A partir de la versión 8u131, Java comenzó a admitir más o menos contenedores debido a mejoras en la funcionalidad ergonómica. En particular, la JVM ahora sabe en cuántos núcleos de procesador se está ejecutando y puede configurar grupos de subprocesos (normalmente grupos de bifurcación/unión) en consecuencia. Por supuesto, esto es genial, pero digamos que tenemos una aplicación web tradicional que usa servlets HTTP y se ejecuta en Tomcat, Jetty, etc. Como resultado, esta aplicación le dará a cada solicitud un hilo separado y le permitirá bloquear este hilo mientras espera operaciones de E/S, por ejemplo, al acceder a la base de datos, archivos u otros servicios. Es decir, el tamaño de dicha aplicación no depende de la cantidad de núcleos disponibles, sino de la cantidad de solicitudes simultáneas. Además, esto significa que las cuotas o los límites en Kubernetes en el número de núcleos no serán de mucha ayuda aquí y el asunto terminará en una estrangulación.

Agotamiento de la memoria

Los hilos son memoria. Y las limitaciones de memoria dentro del contenedor no son de ninguna manera una panacea. Simplemente comience a aumentar la cantidad de aplicaciones y subprocesos y, tarde o temprano, encontrará un aumento crítico en la frecuencia de conmutación y, como resultado, una degradación del rendimiento. Además, si su aplicación usa marcos de microservicios tradicionales, se conecta a una base de datos, usa almacenamiento en caché o usa memoria de otra manera, obviamente necesita una herramienta que le permita mirar dentro de la JVM y ver cómo administra la memoria sin matarla. JVM en sí (por ejemplo, XX:+UseCGroupMemoryLimitForHeap). Y aunque, desde Java 9, la JVM ha aprendido a aceptar cgroups y adaptarse en consecuencia, reservar y gestionar memoria sigue siendo un asunto bastante complejo.

Cuotas y límites

Java 11 introdujo soporte para cuotas de CPU (como PreferContainerQuotaForCPUCount). Kubernetes también ofrece soporte para límites y cuotas. Sí, todo esto tiene sentido, pero si la aplicación vuelve a exceder la cuota asignada, nuevamente terminamos con el tamaño, como es el caso de las aplicaciones Java tradicionales, determinado por el número de núcleos y con la asignación de un hilo separado para cada uno. solicitud, entonces todo esto tiene poco sentido.
Además, si utiliza cuotas y límites o las funciones de escalamiento horizontal de la plataforma subyacente a Kubernetes, el problema tampoco se resuelve por sí solo. Simplemente gastamos más recursos en resolver el problema original o terminamos gastando de más. Y si se trata de un sistema de alta carga en una nube pública, es casi seguro que terminaremos usando más recursos de los que realmente necesitamos.

¿Y qué hacer con todo esto?

En pocas palabras, utilice bibliotecas y marcos de E/S asíncronos y sin bloqueo como Netty, Vert.x o Acká. Son mucho más adecuados para trabajar en contenedores debido a su naturaleza reactiva. Gracias a las E/S sin bloqueo, el mismo hilo puede procesar múltiples solicitudes simultáneas. Mientras una solicitud espera resultados de E/S, el subproceso que la procesa se libera y es asumido por otra solicitud. Y cuando finalmente llegan los resultados de E/S, continúa el procesamiento de la primera solicitud. Al intercalar el procesamiento de solicitudes dentro del mismo subproceso, puede reducir la cantidad total de subprocesos y reducir el consumo de recursos para procesar solicitudes.

Con E/S sin bloqueo, la cantidad de núcleos se convierte en un parámetro clave porque determina la cantidad de subprocesos de E/S que se pueden ejecutar en paralelo. Cuando se usa correctamente, esto le permite distribuir eficazmente la carga entre núcleos y manejar cargas de trabajo más altas con menos recursos.

¿Cómo? ¿Eso es todo?

No, hay algo más. La programación reactiva ayuda a hacer un mejor uso de los recursos, pero también tiene un precio. En particular, el código deberá reescribirse de acuerdo con los principios de no bloqueo y evitar el bloqueo de subprocesos de E/S. Y este es un modelo de desarrollo y ejecución completamente diferente. Y aunque aquí hay muchas bibliotecas útiles, no deja de ser un cambio radical en la forma habitual de pensar.

Primero, necesita aprender a escribir código que se ejecute de forma asincrónica. Una vez que comience a utilizar E/S sin bloqueo, deberá especificar explícitamente qué debe suceder cuando se reciba una respuesta a una solicitud. Simplemente bloquear y esperar ya no funcionará. En su lugar, puede pasar devoluciones de llamada, utilizar programación reactiva o continuación. Pero eso no es todo: para utilizar E/S sin bloqueo, necesita servidores y clientes sin bloqueo, preferiblemente en todas partes. En el caso de HTTP todo es sencillo, pero también existen bases de datos, sistemas de archivos y mucho más.

Y aunque la reactividad total de extremo a extremo maximiza la eficiencia, ese cambio puede ser difícil de digerir en la práctica. Por lo tanto, la capacidad de combinar código reactivo e imperativo se convierte en un requisito previo para:

  1. Utilice eficazmente los recursos en las áreas más cargadas del sistema de software;
  2. Utilice un código de estilo más simple en las partes restantes.

Presentando Quarkus

En realidad, esta es la esencia de Quarkus: combinar modelos reactivos e imperativos dentro de un único entorno de ejecución.

Quarkus se basa en Vert.x y Netty, con una variedad de marcos reactivos y extensiones además para ayudar al desarrollador. Quarkus está diseñado para crear no solo microservicios HTTP, sino también arquitecturas basadas en eventos. Por su carácter reactivo funciona de forma muy eficaz con sistemas de mensajería (Apache Kafka, AMQP, etc.).

El truco consiste en cómo utilizar el mismo motor reactivo tanto para código imperativo como reactivo.

Cómo Quarkus combina la programación imperativa y reactiva

Quarkus hace esto de manera brillante. La elección entre imperativo y reactivo es obvia: utilice un núcleo reactivo para ambos. Lo que realmente ayuda es un código rápido y sin bloqueo que maneja casi todo lo que pasa a través del subproceso del bucle de eventos, también conocido como subproceso IO. Pero si tiene aplicaciones REST o del lado del cliente clásicas, Quarkus tiene listo un modelo de programación imperativo. Por ejemplo, el soporte HTTP en Quarkus se basa en el uso de un motor reactivo y sin bloqueo (Eclipse Vert.x y Netty). Todas las solicitudes HTTP recibidas por su aplicación primero pasan a través de un bucle de eventos (IO Thread) y luego se envían a la parte del código que administra las solicitudes. Dependiendo del destino, el código de gestión de solicitudes se puede llamar dentro de un hilo separado (el llamado hilo de trabajo, usado en el caso de servlets y Jax-RS) o usar el hilo de E/S de origen (ruta reactiva).

Cómo Quarkus combina la programación imperativa y reactiva

Los conectores del sistema de mensajería utilizan clientes sin bloqueo que se ejecutan sobre el motor Vert.x. Por lo tanto, puede enviar, recibir y procesar mensajes de forma eficaz desde sistemas de middleware de mensajería.

El sitio Quarkus.io Aquí hay algunos buenos tutoriales que lo ayudarán a comenzar con Quarkus:

También hemos creado tutoriales prácticos en línea para enseñarle varios aspectos de la programación reactiva en solo un navegador, sin necesidad de IDE ni computadora. Puedes encontrar estas lecciones. aquí.

Recursos útiles

10 lecciones en vídeo sobre Quarkus para familiarizarse con el tema

Como dicen en la web. Quarkus.io, cuarcus - Es KubernetesPila Java orientada a, diseñada para GraalVM y OpenJDK HotSpot y ensamblada a partir de las mejores bibliotecas y estándares de Java.

Para ayudarte a comprender el tema, hemos seleccionado 10 videotutoriales que cubren varios aspectos de Quarkus y ejemplos de su uso:

1. Presentamos Quarkus: el marco Java de próxima generación para Kubernetes

Por Thomas Qvarnstrom y Jason Greene
El objetivo del proyecto Quarkus es crear una plataforma Java para Kubernetes y entornos sin servidor, y combinar modelos de programación reactiva e imperativa en un único entorno de ejecución para que los desarrolladores puedan variar de manera flexible su enfoque cuando trabajan con una amplia gama de arquitecturas de aplicaciones distribuidas. Obtenga más información en la conferencia introductoria a continuación.

2. Quarkus: Java subatómico superrápido

Por: Burr Sutter
Este video tutorial de DevNation Live demuestra cómo usar Quarkus para optimizar aplicaciones Java empresariales, API, microservicios y funciones sin servidor en un entorno Kubernetes/OpenShift, haciéndolos mucho más pequeños, más rápidos y más escalables.

3. Quarkus y GraalVM: acelerando Hibernate a súper velocidades y reduciéndolo a tamaños subatómicos

Autor: Sanne Grinovero
En la presentación aprenderá cómo surgió Quarkus, cómo funciona y cómo le permite crear bibliotecas complejas, como Hibernate ORM, compatibles con imágenes nativas de GraalVM.

4. Aprenda a desarrollar aplicaciones sin servidor

Autor: Martín Lutero
El siguiente vídeo muestra cómo crear una aplicación Java sencilla utilizando Quarkus e implementarla como una aplicación sin servidor en Knative.

5. Quarkus: diviértete codificando

Autor: Edson Yanaga
Una guía en vídeo para crear su primer proyecto de Quarkus, que le permitirá comprender por qué Quarkus se está ganando el corazón de los desarrolladores.

6. Java y contenedores: cuál será su futuro juntos

Publicado por Mark Little
Esta presentación presenta la historia de Java y explica por qué Quarkus es el futuro de Java.

7. Quarkus: Java subatómico superrápido

Autor: Dimitris Andreadis
Una descripción general de las ventajas de Quarkus que han recibido el reconocimiento de los desarrolladores: simplicidad, velocidades ultraaltas, las mejores bibliotecas y estándares.

8. Quarkus y sistemas de cohetes subatómicos

Autor: Clément Escoffier
A través de la integración con GraalVM, Quarkus proporciona una experiencia de desarrollo ultrarrápida y un entorno de ejecución subatómico. El autor habla sobre el lado reactivo de Quarkus y cómo usarlo para crear aplicaciones reactivas y de transmisión.

9. Quarkus y el desarrollo rápido de aplicaciones en Eclipse MicroProfile

Autor: John Clingan
Al combinar Eclipse MicroProfile y Quarkus, los desarrolladores pueden crear aplicaciones MicroProfile en contenedores con todas las funciones que se inician en decenas de milisegundos. El vídeo detalla cómo codificar una aplicación MicroProfile en contenedores para su implementación en la plataforma Kubernetes.

10. Java, versión "Turbo"

Autor: Marco Biel
El autor muestra cómo utilizar Quarkus para crear contenedores Java súper pequeños y súper rápidos que permiten avances reales, especialmente en entornos sin servidor.



Fuente: habr.com

Añadir un comentario