Hola Habr!
En el próximo año nuevo, planeamos desarrollar seriamente temas de contenedores,
Cloud-Native Java y
Kubernetes . Una continuación lógica de estos temas en ruso será la historia sobre el marco
Quarkus , ya considerado en un buen artículo sobre Habré. El artículo de hoy no se centra tanto en el "dispositivo
subatómico ultrarrápido de Java " como en las perspectivas que Quarkus aporta a Enterprise.
Java y JVM siguen siendo extremadamente populares, pero cuando se trabaja con tecnologías sin servidor y microservicios orientados a la nube, Java y otros lenguajes para JVM se usan cada vez menos, ya que ocupan demasiado espacio en la memoria y se cargan muy lentamente, por lo que no son adecuados para utilizar con contenedores de corta duración. Afortunadamente, esta situación está empezando a cambiar gracias a Quarkus.
Introduccion
Cuanto más hago DevOps, contenedores y tecnologías sin servidor, más encuentro que estoy escribiendo
mi código en contenedores en contenedores livianos o
FaaS en Python o JavaScript. Java es simplemente demasiado pesado para arrancar para usar en un marco sin servidor. Con respecto a los microservicios, JavaScript o Python proporcionan una carga más rápida y contenedores más compactos, lo que hace que Java sea más eficiente.
Python y JavaScript son los mejores lenguajes para crear microservicios basados en la nubeJava tiene
más de 20 años , y en el momento de su creación, el mundo era completamente diferente de lo que es ahora. Con el advenimiento de la JVM, se resolvieron grandes problemas: pudimos escribir código una vez y ejecutarlo en muchas plataformas y sistemas operativos. Los contenedores le permiten empaquetar aplicaciones, bibliotecas y recursos del sistema operativo en contenedores separados, y cada contenedor puede funcionar en cualquier lugar.
La portabilidad que proporciona la JVM ahora es menos relevante . En un momento, estábamos listos para incurrir en costos adicionales para garantizar la portabilidad, pero ahora estos tiempos han pasado.
Ahora necesita un trabajo rápido con retrasos mínimos y aplicaciones reactivas que siempre estarán disponibles . Los contenedores y las herramientas de orquestación de contenedores, como
Kubernetes, proporcionan estas capacidades independientemente del lenguaje de programación.
Las empresas que cambian a arquitecturas de microservicios toman sus servicios basados en
Spring escritos en Java, los vinculan a archivos jar pesados, agregan
JDK y los ejecutan en un contenedor basado en Linux. Esta solución funciona, pero debe lidiar con contenedores pesados de 500 MB de tamaño, que se ponen en un estado de accesibilidad durante 10-30 segundos cada uno; Este es un problema grave. Después de la migración, muchas compañías están cambiando lentamente a usar Python, dejando los servicios del lado del servidor en Java y, al final, se detienen en FaaS.
Las tecnologías sin servidor y FaaS son muy populares hoy en día porque le permiten concentrarse en las funciones de escritura sin preocuparse por la infraestructura. Sea como fuere, todos trabajan en contenedores, pero el proveedor de la nube gestiona su ciclo de vida. La mejor parte es que, después de un cierto tiempo, el proveedor detiene completamente el contenedor y reanuda su trabajo solo después de la próxima llamada, es decir, solo paga el tiempo de trabajo real. La primera llamada de función puede durar un poco más de lo habitual, este es el famoso
arranque en frío . El hecho es que el contenedor necesita una carga primaria. El uso de Python o JavaScript no es un gran problema, pero en el caso de Java, la carga inicial puede demorar entre 10 y 15 segundos, y esta es una oración y una de las razones de la disminución de la popularidad de Java. Ahora necesitamos un
código que pueda comenzar, completar la tarea y luego detenerse . No queremos lidiar con muchos subprocesos o procesos de larga duración, necesitamos
procesos de corta duración que puedan cargarse muy rápidamente .
Introduciendo Quarkus
Si lees blogs técnicos o sigues las noticias, probablemente pienses que el
paradigma sin servidor se está apoderando del mundo, y todos lo toman con extremo entusiasmo. Ahora, una startup puede escribir funciones y proporcionarlas en la nube como un servicio, gracias al uso de JavaScript, y también escalarlas para admitir a millones de usuarios, sin tener que administrar la infraestructura. Es cierto que también hay un mundo real fuera de Silicon Valley: instituciones financieras, gobierno, minoristas y muchas otras industrias atendidas por millones de líneas Java, que son demasiado caras para reescribir. Por lo tanto, tenemos que dar por sentado el hecho de que en estas industrias sigue siendo el uso de contenedores pesados.
GraalVM y, en particular, Substrate VM, abren hoy la puerta al futuro glorioso ya largo plazo del lenguaje Java. GraalVM es una
máquina virtual universal para ejecutar aplicaciones escritas en JavaScript, Python, Ruby, R e idiomas para JVM, en particular Java, Scala o Kotlin. Lo
mejor es que
GraalVM le permite precompilar programas (en modo AOT) en un archivo ejecutable nativo . Esto significa que puede compilar su código Java directamente en código específico de la máquina. El programa resultante no funciona en Java HotSpot VM, pero usa todos los componentes necesarios, en particular, gestión de memoria, programación de subprocesos desde otra implementación de una máquina virtual llamada Substrate VM. Substrate VM está escrito en Java, y su código se compila en un ejecutable nativo. El programa resultante se inicia más rápido y, en consecuencia, proporciona una menor sobrecarga en el uso de memoria en comparación con Java VM. Esto es genial, pero probablemente pienses: ¿compilación temprana? ¡Contradice la idea básica para la que se creó la JVM, es decir, el uso de código una vez escrito en todas partes! Esto es una locura! Sin embargo, piense por sí mismo: ahora tenemos contenedores y no necesitan una JVM. Las
aplicaciones de contenedor convencionales
creadas con Spring boot tienen un nivel adicional de abstracción, que es absolutamente innecesario en el mundo donde está Kubernetes . Tiene una aplicación Java ejecutándose en la JVM dentro del contenedor, este contenedor permanece sin cambios, porque hoy el producto terminado es un contenedor, no una aplicación. Ahora estamos empacando contenedores, no archivos WAR. Por lo tanto,
todos los costos asociados con el uso de la aplicación JVM dentro del contenedor se vuelven inútiles , y AOT se convierte en una decisión muy lógica si va a empacar sus aplicaciones en contenedores.
Es cierto que la compilación AOT limita seriamente las capacidades dinámicas de Java (carga de clases en tiempo de ejecución, reflexión, proxies, etc.). En la práctica, esto significa que el 90% del ecosistema de Java no funcionará sin cambios. En consecuencia,
el ecosistema de Java debe adaptarse . Hay buenas noticias: ¡la mayor parte de esto se puede hacer durante el montaje!
Este es el poder de Quarkus. Utiliza GraalVM y proporciona un ecosistema que admite la compilación AOT en el momento de la compilación; así, usando Java, puede crear binarios nativos. Gracias a Quarkus, GraalVM
está disponible para los desarrolladores de Java .
Comenzando con Quarkus
Como se explicó anteriormente, Quarkus proporciona una compilación temprana para aplicaciones Java, y esto produce un ecosistema de Java subatómico supersónico; Quarkus se caracteriza por una carga ultrarrápida, y Java vuelve al juego en el campo del desarrollo basado en la nube. Durante años, ninguna nueva tecnología me ha inspirado, y
no estoy solo en esto .
Lea
la guía para principiantes y compruébelo usted mismo. Todavía hay muchas compañías que usan Java + JPA dentro del contenedor, pero en esta configuración, la carga puede tomar 15 segundos, y
en el caso de Quarkus, ¡0.005!
Quarkus StatsEstá utilizando el mismo IDE y las mismas herramientas a las que está acostumbrado en el mundo de Spring Boot. Para construir su proyecto, use Maven o Gradle. El proyecto se puede ejecutar directamente en el IDE y, además, hay un reinicio en vivo disponible para usted con cualquier cambio, y no necesita reiniciar la aplicación. Quarkus no es Spring, por lo que si usa Spring Boot, tendrá que migrar el código específico de Spring. Afortunadamente, Quarkus proporciona un
nivel de compatibilidad para implementar las dependencias de Spring , lo que simplifica enormemente el trabajo. El marco Quarkus cumple con los estándares, lo que significa facilidad de portabilidad y soporte para su código.
Proceso de desarrollo de Quarkus
Quarkus se puede usar en modo de desarrollo, que recuerda a Spring Boot. Con él también puedes empacar tu proyecto en un tarro grueso. Esto es muy conveniente para probar y depurar su código, ya que se admite el reinicio en vivo; pero necesita compilar por adelantado para entrar en producción. Todo el proceso se muestra en el siguiente diagrama:

- Primero, cree la aplicación en su IDE favorito, y luego puede ejecutarla en modo desarrollador con: "
mvnw compile quarkus:dev
", como lo haría con la aplicación Spring Boot. También puedes empacarlo en un frasco grueso. - Tan pronto como termine el paso anterior y el resultado le convenga,
mvnw package -Pnative
listo para crear el archivo binario de Java, simplemente ejecute: " mvnw package -Pnative
". Esto llevará algún tiempo, ya que el código nativo se generará durante la compilación por adelantado. Cuando se complete este paso, tendrá a su disposición un archivo ejecutable ultrapequeño y ultrarrápido, pero solo puede funcionar en su plataforma / SO, es decir, ¡no será portado! Pero esto es normal, ya que podemos ponerlo en un contenedor, y así garantizar la portabilidad. Aquí se explica cómo hacerlo: ./mvnw package -Pnative -Dnative-image.docker-build=true
4 - y eliminamos el ejecutable del contenedor Docker, es decir, realizamos el ensamblaje nativo dentro del contenedor y creamos un archivo binario. Es posible que esta técnica no funcione en su computadora portátil si su sistema operativo difiere de la plataforma de destino especificada en el DockerFile
generado por Quarkus durante la creación del proyecto. - Luego, después de tener el binario, simplemente cree una imagen basada en el archivo acoplable.
docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/quickstart
. - Finalmente, la aplicación se puede iniciar en Docker o Kubernetes:
docker run -i --rm -p 8080:8080 quarkus-quickstart/quickstart
Características de Quarkus
Quarkus tiene muchas más funciones que el código nativo de Java.
- Unificación de capacidades imperativas y reactivas: le permite combinar código imperativo familiar con código sin bloqueo escrito en un estilo reactivo.
- El desarrollador está satisfecho : configuración unificada, configuración cero, reinicio en vivo en poco tiempo, código optimizado optimizado para el 80% de los casos comunes y código flexible para el 20% restante de los casos, generación de archivos ejecutables nativos sin complicaciones, codificación en vivo.
- Carga increíblemente rápida, un área de memoria residente increíblemente pequeña (sí, ¡no se trata solo del tamaño de almacenamiento dinámico!), Que proporciona un escalado vertical casi instantáneo y un uso de memoria muy denso al orquestar contenedores en plataformas como Kubernetes. Ver más detalles .
- Quarkus ofrece un marco de trabajo completo, fácil de usar y completo, con bibliotecas de primera clase que usted conoce y ama integradas en las estructuras de soporte. Más detalles
- Se admiten las bibliotecas Hibernate, JPA, REST, JWT, etc.
- Configuraciones compatibles implementadas en Kubernetes y OpenShift
- Trazado abierto usando Jaeger
- Soporte Kotlin
- Mensajería con Kafka, Camel ...
- Y mucho más, ¡mira la lista de extensiones !
Ecosistema Quarkus
En resumen, ahora puede ejecutar servicios transaccionales tradicionales JPA / JTA en contenedores livianos súper rápidos, tanto en la nube como en las instalaciones .
Ejemplo de Quarkus
En esta sección, echemos un vistazo simplificado a
la guía para principiantes para darle una impresión del poder de Quarkus.

La forma más fácil de crear un nuevo proyecto Quarkus es abrir una ventana de símbolo del sistema y ejecutar el siguiente comando en él:
mvn io.quarkus:quarkus-maven-plugin:0.12.0:create \ -DprojectGroupId=org.acme \ -DprojectArtifactId=getting-started \ -DclassName="org.acme.quickstart.GreetingResource" \ -Dpath="/hello"
Esto genera un proyecto Maven con GreetingResuce que proporciona el punto final / hola. También se generan imágenes de Dockerfile Docker para archivos nativos y jvm (imágenes tradicionales en forma de jarra gruesa). El código es muy limpio y simple:
@Path("/hello") public class GreetingResource { @GET @Produces(MediaType.TEXT_PLAIN) public String hello() { return "hello"; } }
Para ejecutar la aplicación, use:
./mvnw compile quarkus:dev
La aplicación se empaqueta utilizando el paquete ./mvnw. El resultado son 2 archivos jar:
- getting-begin-1.0-SNAPSHOT.jar: contiene solo clases y recursos de proyecto. Este es un artefacto común resultante del ensamblaje de Maven;
- getting-begin-1.0-SNAPSHOT-runner.jar es un jar ejecutable. Tenga en cuenta que esto no es "uber-jar", hay dependencias aquí, se copian en el directorio de destino / lib.
Puede iniciar la aplicación usando: java -jar target / getting-begin-1.0-SNAPSHOT-runner.jar
Luego, debe descargar e instalar GraalVM y establecer la variable de entorno
GRAALVM_HOME
.
Ahora puede crear un ejecutable nativo con:
./mvnw package -Pnative -Dnative-image.docker-build=true
.
Aquí se explica cómo crear una imagen de Docker:
docker build -f src/main/docker/Dockerfile.native -t quarkus-quickstart/quickstart
.
Ahora puede iniciarse utilizando cualquier motor de orquestación de contenedores, si utiliza
minishift :
kubectl run quarkus-quickstart --image=quarkus-quickstart/quickstart:latest --port=8080 --image-pull-policy=IfNotPresent
kubectl expose deployment quarkus-quickstart --type=NodePort
Eso es todo! ¡Ahora tiene un contenedor con un servicio REST de Java que comienza en 0.004 segundos!
Conclusión
Ahora entiendo por qué estoy tan impresionado con el marco Quarkus compatible con Red Hat. Realmente creo que cambiará el panorama tecnológico de Java y brindará a las grandes empresas tradicionales una oportunidad real de migrar a la nube.
Kubernetes + Knative + Quarkus cambian las reglas del juego en un desarrollo orientado a la nube y complacerán a cualquier desarrollador de Java.
¡Este
repositorio tiene muchos ejemplos interesantes!