El lenguaje de pro­gra­ma­ción Java es conocido desde hace mucho tiempo como un “lenguaje del sector”. Se creó en los primeros años de Internet, pero la web se ha de­sa­rro­lla­do muy rá­pi­da­me­n­te desde entonces. Además de la clásica ar­qui­te­c­tu­ra cliente-servidor, hay una serie de in­te­re­sa­n­tes modelos al­te­r­na­ti­vos: las apli­ca­cio­nes basadas en co­n­te­ne­do­res, los mi­cro­se­r­vi­cios, la co­mpu­tación sin servidor y las apli­ca­cio­nes web reactivas se han es­ta­ble­ci­do de forma ge­ne­ra­li­za­da. Estos tipos de apli­ca­cio­nes han sido hasta ahora difíciles de im­ple­me­n­tar con Java. Gracias al entorno Quarkus, esto ha cambiado. El director de RedHat, Ken Johnson, lo explica así:

Cita

“… it's a very small Java stack, perfect for co­n­tai­ne­rs, se­r­ve­r­le­ss and other scenarios where you're running Java ap­pli­ca­tio­ns in the cloud.”

- Ken Johnson, Fuente: https://cloud.redhat.com/blog/quarkus-is-here-for-your-java

“[Quarkus] es una es­tru­c­tu­ra Java muy pequeña, perfecta para co­n­te­ne­do­res, sin servidor y óptima para otros es­ce­na­rios en los que se ejecutan apli­ca­cio­nes Java en la nube.” (Tra­du­c­ción: IONOS)

Te pre­se­n­ta­re­mos Quarkus y te mo­s­tra­re­mos cómo este entorno está re­vo­lu­cio­na­n­do la creación de apli­ca­cio­nes Java.

¿Qué hace que Quarkus sea especial?

Quarkus es un entorno de­sa­rro­lla­do por RedHat para crear apli­ca­cio­nes Java. Quarkus se de­sa­rro­lló con el objetivo de ejecutar programas Java en co­n­te­ne­do­res. En pa­r­ti­cu­lar, se centra en el apoyo al software de co­n­fi­gu­ra­ción Ku­be­r­ne­tes. Otro enfoque del de­sa­rro­llo de Quarkus es el uso de bi­blio­te­cas y es­tá­n­da­res Java es­ta­ble­ci­dos.

“HotSpot”, del proyecto OpenJDK, se utiliza como máquina virtual Java (JVM) para que sea la capa de ejecución del código Java. Además, también se puede utilizar el de­sa­rro­llo “GraalVM”, que se basa en HotSpot. Este último permite compilar el código Java en código máquina di­re­c­ta­me­n­te eje­cu­ta­ble. Para entender el beneficio inmediato de utilizar Quarkus, veamos primero cómo se ejecutan las apli­ca­cio­nes Java con y sin Quarkus.

¿Cómo se han ejecutado tra­di­cio­na­l­me­n­te las apli­ca­cio­nes Java?

La idea básica que hizo que Java fuera algo re­vo­lu­cio­na­rio cuando apareció era tan simple como cau­ti­va­do­ra: Java pe­r­mi­ti­ría de­sa­rro­llar un programa sin estar atado a un hardware o sistema operativo es­pe­cí­fi­co. Esta in­de­pe­n­de­n­cia de la pla­ta­fo­r­ma se resume a menudo con la frase “escribe una vez, ejecuta en cualquier parte”. La po­r­ta­bi­li­dad asociada permite trasladar el programa entre pla­ta­fo­r­mas. ¡Qué gran truco! ¿Pero cómo funciona?

Como ocurre con otros lenguajes de pro­gra­ma­ción, un programa Java comienza con un código fuente que puede ser leído por un humano. Para ejecutar las in­s­tru­c­cio­nes del texto fuente en un ordenador, se generan las in­s­tru­c­cio­nes co­rre­s­po­n­die­n­tes en el formato del pro­ce­sa­dor es­pe­cí­fi­co. Con Java, hay otro paso in­te­r­me­dio: el texto fuente se traduce primero a un formato in­te­r­me­dio, el llamado código de bytes, como ocurre con el lenguaje Python. A co­n­ti­nua­ción, el código de bytes se ejecuta en la “Java virtual machine” (JVM). Para ejecutar un programa Java en un di­s­po­si­ti­vo, debe tener instalada una JVM.

El código de bytes se in­te­r­pre­ta tra­di­cio­na­l­me­n­te para su ejecución en la JVM. Las in­s­tru­c­cio­nes del código de bytes se traducen pieza a pieza en in­s­tru­c­cio­nes de código máquina y se ejecutan. El proceso de co­m­pi­la­ción a tiempo real o “just-in-time co­m­pi­la­tion” (JIT) es más eficaz. Con ese proceso, el código de bytes también se convierte en código máquina, pero también entran en juego otras op­ti­mi­za­cio­nes. En resumen, la ejecución de un programa Java implica los si­guie­n­tes pasos:

  1. Compilar el código fuente de Java a código de bytes con el comando del co­m­pi­la­dor de Java ‘javac’:
javac java_program.java
  1. Ejecutar el código de bytes de Java con el comando de ejecución de Java ‘java’ - A co­n­ti­nua­ción, se genera el código máquina:
java java_program
Nota

Aquí estamos hablando de una “máquina virtual”. Aunque el término es el mismo, en este caso no se refiere a ningún tipo de te­c­no­lo­gía para vi­r­tua­li­zar un sistema operativo. En cambio, el código in­te­r­me­dio se traduce a código máquina.

Por muy práctico que sea el modelo de Java “escribe una vez, ejecuta en cualquier parte”, el enfoque tiene algunos puntos débiles: El uso de la JVM conlleva una so­bre­ca­r­ga bastante im­po­r­ta­n­te. Por un lado, se requiere un cierto tiempo para iniciar la JVM, que se añade al tiempo de ejecución de la apli­ca­ción real. Por otro lado, además de un mayor consumo de memoria, hay una pérdida de re­n­di­mie­n­to. Todo esto juega un papel menor en las apli­ca­cio­nes que se ejecutan durante mucho tiempo. Sin embargo, el enfoque no es muy adecuado para las apli­ca­cio­nes de corta duración, basadas en co­n­te­ne­do­res. Lo ideal es que estas se inicien lo antes posible. Un tiempo de inicio de varios segundos es in­ace­p­ta­ble.

¿Cómo se ejecutan las apli­ca­cio­nes Java con Quarkus?

A di­fe­re­n­cia de la ejecución nativa de las apli­ca­cio­nes Java, Quarkus ofrece varias ventajas. Vamos a di­fe­re­n­ciar los dos modos que soporta Quarkus:

  1. Op­ti­mi­za­ción del código de bytes y ejecución en la JVM
  2. Ejecución como código nativo tras la co­m­pi­la­ción

El código Java escrito con Quarkus puede eje­cu­tar­se no­r­ma­l­me­n­te en la JVM. Sin embargo, existen co­n­si­de­ra­bles ventajas en cuanto al consumo de memoria y al tiempo de inicio de una apli­ca­ción en ejecución. Para co­n­se­gui­r­lo, Quarkus utiliza algunos trucos. En pa­r­ti­cu­lar, una serie de pasos que consumen mucho tiempo se trasladan de la ejecución al proceso de co­n­s­tru­c­ción. Esto incluye los pasos que, de otro modo, se producen cada vez que se ejecuta una apli­ca­ción Java:

  • Carga y análisis de las co­n­fi­gu­ra­cio­nes
  • Ex­plo­ra­ción de la ruta de acceso a las clases Java y re­so­lu­ción de las ano­ta­cio­nes
  • Creación de modelos de unidades para bases de datos o similares, si procede

Con Quarkus, estos pasos se realizan una vez y los re­su­l­ta­dos se almacenan en la caché para una rápida re­cu­pe­ra­ción. Otra op­ti­mi­za­ción del re­n­di­mie­n­to consiste en que Quarkus reduce la cantidad de in­fo­r­ma­ción dinámica di­s­po­ni­ble en tiempo de ejecución. Esta se sustituye por las co­rre­s­po­n­die­n­tes co­n­s­tru­c­cio­nes estáticas. Esto es es­pe­cia­l­me­n­te útil en lo que respecta al uso en co­n­te­ne­do­res. Una apli­ca­ción en co­n­te­ne­dor no suele cambiar nunca y siempre se ejecuta en el mismo entorno.

El segundo modo soportado por Quarkus para ejecutar apli­ca­cio­nes Java es aún más in­te­re­sa­n­te. Con la co­m­pi­la­ción por an­ti­ci­pa­do o “ahead-of-time co­m­pi­la­tion” (AOT), se genera un código máquina di­re­c­ta­me­n­te eje­cu­ta­ble a partir del texto fuente de Java, en lugar del código de bytes, lo que significa que ya no es necesaria una JVM en el hardware de destino. El programa solo se ejecuta en una ar­qui­te­c­tu­ra de pro­ce­sa­dor es­pe­cí­fi­ca y tiene que ser re­co­m­pi­la­do para otras pla­ta­fo­r­mas. Sin embargo, esta re­s­tri­c­ción suele ser irre­le­va­n­te para su uso en co­n­te­ne­do­res. El ahorro en el consumo de memoria y en el tiempo de inicio de la apli­ca­ción que se consigue con la co­m­pi­la­ción AOT es realmente im­pre­sio­na­n­te. Compara las pruebas de re­n­di­mie­n­to que hemos recogido de la página oficial de Quarkus:

Apli­ca­ción Escenario Uso de memoria Tiempo de la primera respuesta
Quarkus + AOT REST 12 MB 0.02 s
Quarkus + AOT REST + CRUD 28 MB 0.04 s
Quarkus + JIT REST 73 MB 0.94 s
Quarkus + JIT REST + CRUD 145 MB 2.03 s
Cloud Native Stack REST 136 MB 4.3 s
Cloud Native Stack REST + CRUD 209 MB 9.5 s
Nota

En cuanto a la te­r­mi­no­lo­gía: REST significa que solo se ejecuta un servidor web en el co­n­te­ne­dor. En el escenario REST + CRUD, se ejecuta una base de datos junto al servidor web. Para la pila nativa en la nube, el co­n­te­ne­dor contiene una JVM, además de la apli­ca­ción Java.

¿Para qué se utiliza Quarkus?

Quarkus no es un entorno de apli­ca­ción más. Por el contrario, el software pretende redefinir lo que significa de­sa­rro­llar apli­ca­cio­nes con Java. Solo a modo de re­co­r­da­to­rio: tra­di­cio­na­l­me­n­te, era más im­po­r­ta­n­te que una apli­ca­ción Java se ejecutara de forma estable durante mucho tiempo. El tiempo que tardaba la apli­ca­ción en iniciarse no era algo crítico.

Detente a co­n­si­de­rar las apli­ca­cio­nes basadas en co­n­te­ne­do­res: los nuevos co­n­te­ne­do­res pueden ser arra­n­ca­dos au­to­má­ti­ca­me­n­te por el software de co­n­fi­gu­ra­ción. La apli­ca­ción en el co­n­te­ne­dor debe estar entonces lista para su uso inmediato. Además, a menudo se inician varios co­n­te­ne­do­res re­du­n­da­n­tes para un servicio. En co­n­se­cue­n­cia, la reducción del consumo de recursos co­n­se­gui­da con Quarkus se mu­l­ti­pli­ca.

El director de RedHat, Alex Handy, lo resume así:

Cita

“When you think of se­r­ve­r­le­ss computing, mi­cro­se­r­vi­ces and the […] cloud, there's one language you're probably not [thinking of]: Java. And that's a real shame. […] Java was and is the workhorse language of business. It remains the third most popular language in the world […] It's been the language of choice for co­r­po­ra­tio­ns that need to keep a single ap­pli­ca­tion up and running for years at a time. ”

- Alex Handy, fuente: https://the­ne­w­s­ta­ck.io/quarkus-gives-spring-boot-users-a-path-to-se­r­ve­r­le­ss-and-live-coding/

“Cuando piensas en la pro­gra­ma­ción sin se­r­vi­do­res, los mi­cro­se­r­vi­cios y la nube [...], hay un lenguaje en el que pro­ba­ble­me­n­te no estás pensando: Java. Y eso es una verdadera lástima. [...] Java ha sido y es el lenguaje de trabajo de las empresas. Sigue siendo el tercer lenguaje in­fo­r­má­ti­co más popular del mundo [...] Ha sido el lenguaje elegido por las empresas que necesitan mantener una única apli­ca­ción en fu­n­cio­na­mie­n­to durante años.” (Tra­du­c­ción: IONOS)

Las ventajas de Quarkus son evidentes. Sin embargo, el entorno también tiene algunas li­mi­ta­cio­nes. Por ello, Quarkus no está pensado pri­n­ci­pa­l­me­n­te para migrar apli­ca­cio­nes Java exi­s­te­n­tes. En cambio, merece la pena utilizar Quarkus como punto de partida para un nuevo de­sa­rro­llo. A co­n­ti­nua­ción, veremos algunas áreas de apli­ca­ción es­pe­cí­fi­cas. En todos los ejemplos me­n­cio­na­dos, se utiliza Maven o Gradle como he­rra­mie­n­ta de co­m­pi­la­ción. El área de apli­ca­ción se determina co­n­fi­gu­ra­n­do el comando ‘mvn’ o ‘gradle’. A co­n­ti­nua­ción, la he­rra­mie­n­ta de co­m­pi­la­ción genera au­to­má­ti­ca­me­n­te las co­n­fi­gu­ra­cio­nes y co­m­po­ne­n­tes ne­ce­sa­rios.

Ejecución de apli­ca­cio­nes de mi­cro­se­r­vi­cios en Ku­be­r­ne­tes con Java y Quarkus

Ku­be­r­ne­tes es un software de co­n­fi­gu­ra­ción para apli­ca­cio­nes de co­n­te­ne­do­res. El uso de Ku­be­r­ne­tes con co­n­te­ne­do­res Docker es bastante común. Los servicios in­di­vi­dua­les de una apli­ca­ción se guardan como imágenes Docker y son ge­s­tio­na­dos por Ku­be­r­ne­tes. El operador se encarga de la gestión de los co­n­te­ne­do­res generados a partir de las imágenes: Ku­be­r­ne­tes inicia, controla y supervisa los servicios. A menudo, se inician varias copias de un servicio para compartir la carga y aumentar la to­le­ra­n­cia a fallos. Si uno de los servicios falla, el co­n­te­ne­dor se destruye y se crea un nuevo co­n­te­ne­dor a partir de la misma imagen. Java Quarkus incluye las co­n­fi­gu­ra­cio­nes ne­ce­sa­rias para su uso en Ku­be­r­ne­tes.

Im­ple­me­n­ta­ción de API REST y apli­ca­cio­nes sin servidor con Java y Quarkus

REST es el tipo de ar­qui­te­c­tu­ra es­ta­ble­ci­do desde hace tiempo para las apli­ca­cio­nes web. Las API, en pa­r­ti­cu­lar, se im­ple­me­n­tan en su mayoría siguiendo este enfoque. Una API REST se basa en una ar­qui­te­c­tu­ra cliente-servidor. La co­mu­ni­ca­ción se realiza a través del protocolo HTTP uti­li­za­n­do los “verbos” GET, POST, PUT, DELETE. Estos co­rre­s­po­n­den a los conocidos “verbos” CRUD (“create, read, update, delete”) del entorno de las bases de datos. El in­te­r­ca­m­bio de datos entre una API y un usuario suele rea­li­zar­se mediante JSON.

La pro­gra­ma­ción sin servidor es una ar­qui­te­c­tu­ra al­te­r­na­ti­va para las apli­ca­cio­nes basadas en la nube. En este modelo, también conocido como “Function as a Service” (FaaS), una única función se ejecuta bre­ve­me­n­te en un co­n­te­ne­dor. La función es llamada, realiza un cálculo y después se desactiva de nuevo. A pesar del nombre, las funciones sin servidor siguen eje­cu­tá­n­do­se en los se­r­vi­do­res. Los pro­gra­ma­do­res ya no tienen que preo­cu­par­se por ellas. Con AWS Lambda, Google Cloud Functions y Microsoft Azure Functions, los entornos sin servidor están di­s­po­ni­bles en las pri­n­ci­pa­les pla­ta­fo­r­mas en la nube. El código Java puede uti­li­zar­se en estas pla­ta­fo­r­mas con Quarkus.

Consejo

Crea tu propia REST API en un servidor dedicado de IONOS.

Construir apli­ca­cio­nes web reactivas con Java y Quarkus

En contraste con la pro­gra­ma­ción im­pe­ra­ti­va, la pro­gra­ma­ción reactiva re­pre­se­n­ta el paradigma de la pro­gra­ma­ción moderna. El pro­gra­ma­dor describe las acciones que deben tener lugar cuando se producen de­te­r­mi­na­dos eventos. Los re­pre­se­n­ta­n­tes más conocidos de este estilo de pro­gra­ma­ción son los entornos “React” y “Vue”, escritos en Ja­va­S­cri­pt. Ambos se centran en la creación de in­te­r­fa­ces de usuario basadas en la web. Con Quarkus, se pueden im­ple­me­n­tar apli­ca­cio­nes con un estilo im­pe­ra­ti­vo y reactivo. Incluso es posible combinar ambos pa­ra­di­g­mas.

¿Dónde se utiliza Quarkus?

Quarkus se diseñó con el objetivo de optimizar las apli­ca­cio­nes Java para su uso en co­n­te­ne­do­res y entornos en la nube. Sin embargo, la po­si­bi­li­dad de compilar un programa Java di­re­c­ta­me­n­te en código máquina abre po­si­bi­li­da­des de apli­ca­ción aún más in­te­re­sa­n­tes. Echemos un vistazo a las áreas de apli­ca­ción actuales más in­te­re­sa­n­tes de Quarkus.

En primer lugar, re­co­r­de­mos cómo se ejecuta un programa Java de­sa­rro­lla­do con Quarkus. Durante el proceso de co­n­s­tru­c­ción, el código fuente de Java se compila en código de bytes, que luego se traduce en código máquina cuando se ejecuta. Con Quarkus se puede generar código de bytes, que luego se ejecuta en un entorno de ejecución de Java, como la VM HotSpot, mediante in­te­r­pre­ta­ción o co­m­pi­la­ción just-in-time (JIT). De­pe­n­die­n­do de la co­n­fi­gu­ra­ción, entran en juego varias op­ti­mi­za­cio­nes re­le­va­n­tes para el re­n­di­mie­n­to.

Por otro lado, GraalVM, basado en HotSpot, puede uti­li­zar­se para generar una imagen nativa uti­li­za­n­do la co­m­pi­la­ción por an­ti­ci­pa­do (AOT). La imagen nativa es un archivo binario que contiene todas las bi­blio­te­cas y de­pe­n­de­n­cias ne­ce­sa­rias para ejecutar la apli­ca­ción. Como no se necesita una JVM para la ejecución, los mayores aumentos de re­n­di­mie­n­to se obtienen con la co­m­pi­la­ción AOT.

Apli­ca­cio­nes Java en entornos de co­n­te­ne­do­res

Ku­be­r­ne­tes suele in­te­r­ve­nir cuando se utiliza una apli­ca­ción Java en co­n­te­ne­do­res. Una apli­ca­ción Java em­pa­que­ta­da como imagen Docker también puede uti­li­zar­se en un clúster OpenShift. El uso de Quarkus con Ku­be­r­ne­tes también puedes probarlo, por ejemplo, uti­li­za­n­do una in­s­ta­la­ción minikube en tu sistema local.

Funciones Java en entornos sin servidor

Utiliza Quarkus para im­ple­me­n­tar fá­ci­l­me­n­te una función escrita en Java en entornos sin servidor de Amazon, Google y Microsoft.

Programas Java en sistemas in­te­gra­dos

Con la po­si­bi­li­dad de crear una imagen nativa a partir de una apli­ca­ción Java, el código Java también puede uti­li­zar­se en sistemas in­te­gra­dos. Aquí entra en juego la co­m­pi­la­ción AOT, que garantiza un bajo consumo de memoria y tiempos de arranque rápidos para una apli­ca­ción concreta.

Quarkus comparado con otros entornos

Quarkus es adecuado para una amplia gama de es­ce­na­rios de apli­ca­ción. Otros entornos son más es­pe­cí­fi­cos hasta cierto punto. Veamos un par de al­te­r­na­ti­vas similares:

  • React: este entorno de Ja­va­S­cri­pt se ha es­ta­ble­ci­do como el estándar de la pro­gra­ma­ción reactiva del mismo nombre.
  • Open Liberty: este entorno de IBM también permite el de­sa­rro­llo de apli­ca­cio­nes de mi­cro­se­r­vi­cios con Java. Al igual que Quarkus, Open Liberty viene con una fu­n­cio­na­li­dad de recarga en tiempo real.
  • Micronaut: con el entorno Micronaut, se pueden programar mi­cro­se­r­vi­cios y apli­ca­cio­nes sin servidor en Java. Al igual que con Quarkus, aquí se utiliza GraalVM.
  • Spring/Spring Boot: Spring es pro­ba­ble­me­n­te el entorno Java más popular para apli­ca­cio­nes web. Spring se basa en GraalVM y, además de la creación de mi­cro­se­r­vi­cios, soporta la pro­gra­ma­ción reactiva y la recarga en tiempo real. En una co­m­pa­ra­ción de re­n­di­mie­n­to, Quarkus supera a Spring. Un proyecto existente de Spring puede migrar a Quarkus con relativa facilidad.

¿Cuáles son los pros y los contras de Quarkus?

La principal ventaja de de­sa­rro­llar apli­ca­cio­nes Java con Quarkus es la mejora del re­n­di­mie­n­to. Esto es es­pe­cia­l­me­n­te im­po­r­ta­n­te cuando se utilizan apli­ca­cio­nes Java en entornos de co­n­te­ne­do­res. Las mejoras de re­n­di­mie­n­to incluyen:

  • Tiempo de arranque rápido de la apli­ca­ción
  • Bajo consumo de memoria por parte de la apli­ca­ción en ejecución
  • Escalado casi inmediato de los servicios
  • Menor necesidad de espacio para las imágenes nativas

Además de las ventajas de re­n­di­mie­n­to, Quarkus brilla es­pe­cia­l­me­n­te por su facilidad de uso. Los de­sa­rro­lla­do­res ex­pe­ri­me­n­ta­dos de Java EE y Spring pueden aprender fá­ci­l­me­n­te a utilizar el entorno. También se be­ne­fi­cian del hecho de que Quarkus se basa en un entorno sólido. Se utilizan las si­guie­n­tes te­c­no­lo­gías estándar, entre otras:

  • Eclipse Mi­cro­Pro­fi­le
  • Spring De­pe­n­de­n­cy Injection
  • Hibernate ORM

Quarkus también ofrece un entorno de pro­gra­ma­ción en vivo, en el que los de­sa­rro­lla­do­res pueden crear rá­pi­da­me­n­te un prototipo. La función de recarga en vivo co­n­tri­bu­ye a un de­sa­rro­llo fluido: tras activar el modo dev, los cambios en el código fuente y la co­n­fi­gu­ra­ción se compilan en segundo plano. El de­sa­rro­lla­dor solo tiene que recargar la ventana del navegador para apreciar los cambios.

Por último, co­n­clui­re­mos con las de­s­ve­n­ta­jas de utilizar Quarkus. Estas se derivan pri­n­ci­pa­l­me­n­te de las op­ti­mi­za­cio­nes que entran en juego durante la co­m­pi­la­ción.

  • En concreto, la reducción de la in­fo­r­ma­ción dinámica generada durante el tiempo de ejecución puede provocar problemas en algunos es­ce­na­rios.
  • Las po­si­bi­li­da­des muy limitadas de in­s­pe­c­ción pueden di­fi­cu­l­tar la de­pu­ra­ción de una apli­ca­ción.
  • El proceso de co­n­s­tru­c­ción altamente op­ti­mi­za­do para las imágenes nativas lleva mucho tiempo.

Quarkus no está pensado para cualquier proyecto Java. Hasta cierto punto, el uso de este entorno requiere que los procesos se adapten.

Ir al menú principal