Cree aplicaciones de microservicio basadas en compilación estática

Autor: Rao Zihao (Cheng Pu)

Limitaciones de Java

Una aplicación Java tradicional se puede dividir aproximadamente en los siguientes pasos, desde la escritura del código hasta el inicio y la operación:

  1. Primero, escriba el programa de código fuente .java.
  2. Luego, use la herramienta javac para traducir el archivo .java a código de bytes .class. El código de bytes es uno de los contenidos más importantes en Java. Es precisamente por su apariencia que Java puede proteger el entorno subyacente y lograr el efecto de escritura una vez. ¡corre a cualquier parte!
  3. El archivo .class basado en el paso 2 se empaquetará en un paquete jar o paquete war para su implementación y ejecución. Durante el proceso de implementación, la aplicación se carga a través de la máquina virtual Java y luego se interpreta el código de bytes para ejecutar la lógica empresarial.

Todo el proceso se muestra en la siguiente figura:

imagen

Figura 1: proceso de ejecución del programa Java

El proceso anterior no solo aporta ventajas a los programas Java que otros lenguajes de programación no tienen, como multiplataforma, facilidad de uso, etc. Pero también trae algunos problemas de rendimiento a los programas Java, como una velocidad de inicio lenta y un uso elevado de memoria durante el tiempo de ejecución.

problema de arranque en frio

El proceso detallado de inicio y ejecución del programa Java en la Figura 1 se muestra en la Figura 2 a continuación:

imagen

*Figura 2: Análisis del proceso de inicio del programa Java [ 1] *

El proceso de inicio de una aplicación Java primero debe cargar el programa de software de la máquina virtual JVM correspondiente a la aplicación en la memoria, como se muestra en la parte roja de la figura anterior. Luego, la máquina virtual JVM carga la aplicación correspondiente en la memoria. Este proceso corresponde a la parte azul claro Class Load (CL) en la figura anterior. Durante el proceso de carga de clases, la aplicación comenzará a interpretarse y ejecutarse, correspondiente a la parte verde claro en la figura anterior. Explique el proceso de ejecución: la JVM recicla objetos basura, correspondientes a la parte amarilla en la figura anterior. A medida que avanza el programa, la JVM utilizará la tecnología Just In Time (JIT) para compilar y optimizar los códigos que se ejecutan con más frecuencia para mejorar la velocidad de ejecución de la aplicación. El proceso JIT corresponde a la parte blanca de la figura anterior. El código después de la compilación y optimización JIT corresponde a la parte verde oscuro de la figura.

Después del análisis anterior, no es difícil ver que un programa Java pasará por varias etapas de inicio de VM, inicio de aplicación y aplicación activa desde el inicio hasta ser compilado y optimizado dinámicamente por JIT. En comparación con otros lenguajes compilados, su inicio en frío el problema es más serio.

Problema de uso elevado de memoria durante el tiempo de ejecución

Además del problema del arranque en frío, del análisis anterior no es difícil ver que cuando se ejecuta un programa Java, primero necesita cargar una máquina virtual JVM sin hacer nada, esta operación generalmente ocupa una cierta cantidad de memoria. Además, porque el programa Java primero interpreta y ejecuta el código de bytes y luego realiza la compilación y optimización JIT.

Debido a que, en comparación con algunos lenguajes compilados, las acciones de compilación y optimización se posponen al tiempo de ejecución, es muy fácil cargar mucho más código del que realmente se necesita ejecutar, lo que resulta en un uso de memoria no válido. En resumen, estas son las principales razones por las que mucha gente suele criticar el elevado uso de memoria de los programas Java.

Programas Java más ligeros

tecnología de compilación estática

Dado que el método tradicional de ejecución de programas Java que primero interpreta, ejecuta y luego compila dinámicamente tiene muchos de los problemas anteriores, ¿hay alguna forma de hacer que los programas Java, al igual que otros lenguajes de programación, como C/C++, se compilen primero y luego se ejecuten para resolverlos? los problemas anteriores?

La respuesta es sí. La compilación anticipada (compilación AOT) o compilación estática se propuso desde muy temprano en el campo de Java. La idea central es avanzar la fase de compilación de los programas Java hasta antes del inicio del programa y luego realizar la compilación y optimización del código durante la fase de compilación para maximizar el inicio del programa, eliminar los inicios en frío y reducir la sobrecarga de la memoria en tiempo de ejecución.

Existen muchas tecnologías de implementación para la compilación estática en el campo de Java, la más representativa de las cuales es la plataforma de ejecución multilingüe de alto rendimiento y código abierto GraalVM [ 2] lanzada por Oracle . Algunos lectores que vean esto pueden preguntar: "¿Qué es una plataforma de ejecución multilingüe de alto rendimiento? ¿Qué tiene que ver con la compilación estática en sí?".

imagen

Figura 3: Plataforma de ejecución multilingüe GraalVM

Como se muestra en la Figura 3 anterior, GraalVM proporciona un marco de implementación del intérprete Truffle, lo que permite a los desarrolladores usar la API proporcionada por Truffle para implementar rápidamente un intérprete para un lenguaje específico, de modo que los programas escritos en varios lenguajes de programación en la figura anterior se puede compilar El efecto de ejecución, convirtiéndose así en una plataforma de tiempo de ejecución multilingüe. El compilador de GraalVM que implementa capacidades de compilación estática es GraalVM JIT Compiler. El marco de compilación estática y el tiempo de ejecución son implementados por el subproyecto Substrate VM y son compatibles con la implementación del tiempo de ejecución OpenJDK. Proporcionan manejo de excepciones, programación sincrónica, administración de subprocesos, administración de memoria y otras funciones cuando se ejecuta el programa espejo nativo.

Por lo tanto, GraalVM no solo puede servir como una plataforma de ejecución multilingüe, sino que también puede usarse para compilar estáticamente programas Java gracias al compilador estático GraalVM JIT Compiler que se proporciona.

Después de hablar sobre la relación entre la compilación estática y GraalVM, algunos lectores pueden sentir curiosidad: ¿cuáles son las diferencias entre la compilación estática basada en GraalVM y los métodos convencionales de interpretación y ejecución de JVM? En comparación con el programa Java compilado en tiempo de ejecución JVM actualmente ampliamente utilizado, la diferencia entre la escritura de código y la compilación y ejecución de programas Java basados ​​en compilación estática se muestra en la Figura 4 a continuación:

imagen

Figura 4: Comparación entre la compilación estática y el proceso de ejecución de JVM tradicional

En comparación con el método de tiempo de ejecución JVM, la compilación estática primero analizará y compilará el programa antes de ejecutarlo, luego generará un archivo ejecutable de imagen nativa que está estrechamente relacionado con el entorno de ejecución y finalmente ejecutará el archivo directamente para iniciar el programa para su ejecución.

En este punto, algunos lectores pueden sentir curiosidad: ¿qué efecto tendrá exactamente el proceso de compilación estática de la Figura 4 anterior en el programa Java? ¿Cómo resolver el problema de la recolección de basura de programas ejecutables compilados estáticamente? Como se muestra en la Figura 5 a continuación, describe los contenidos de entrada y salida del proceso de compilación en la implementación de la tecnología de compilación estática GraalVM.

imagen

Figura 5: Entrada y salida de compilación estática

Los primeros tres contenidos de entrada a la izquierda en la Figura 5: Aplicación, Bibliotecas y JDK son las tres partes necesarias para compilar y ejecutar un programa Java. Substrate VM es la parte central de GraalVM que implementa la compilación estática y desempeña un papel importante en todo el proceso de compilación estática.

Durante el proceso de análisis estático, como se muestra en la parte central de la Figura 5 anterior, Substrate VM realiza un análisis estático en la aplicación a través de un análisis de puntos insensible al contexto, que puede realizar un análisis estático en la aplicación sin ejecutar el programa. Análisis del programa fuente, se proporciona una lista de todas las funciones posibles y luego se utiliza como entrada para la etapa de compilación posterior para compilar estáticamente el programa. Debido a las limitaciones del análisis estático, este proceso no puede cubrir características dinámicas como la reflexión, el proxy dinámico y las llamadas JNI en Java. Esto también ha provocado que muchos marcos Java utilicen una gran cantidad de las características anteriores en el proceso de implementación, por lo que es difícil completar el análisis estático de todos sus propios códigos directamente en base a Substrate VM y requiere una configuración externa adicional [3] para resolver el análisis estático ... sus propias deficiencias.

Por ejemplo, la comunidad Spring ha desarrollado AOT Engine [ 4] como se muestra en la Figura 6 a continuación para ayudar a resolver el análisis estático de reflexiones, proxies dinámicos, etc. del proyecto Spring, y convertirlos en contenido que Substrate VM pueda reconocer durante la compilación. fase., asegurando que las aplicaciones Spring se puedan compilar estáticamente con éxito en función de Substrate VM.

imagen

Figura 6: Motor AOT de resorte

Una vez completado el análisis estático, según la lista de funciones accesibles de los resultados del análisis estático, se llama al compilador GraalVM JIT en GraalVM presentado anteriormente para compilar la aplicación en un código local que esté fuertemente relacionado con la plataforma de destino para completar el proceso de compilación.

Una vez completada la compilación, ingresará a la etapa de generación de archivos ejecutables nativos en el lado derecho de la Figura 5 anterior. Durante este proceso, Substrate VM guardará el contenido determinado e inicializado en la fase de compilación estática, así como los datos en el tiempo de ejecución de Substrate VM y la biblioteca JDK, en el montón de imágenes del archivo ejecutable final. El tiempo de ejecución de Substrate VM proporciona el archivo ejecutable final con la recolección de basura, el manejo de excepciones y otras capacidades necesarias durante la operación. Para la recolección de basura, solo se proporcionó Serial GC en la edición inicial de GraalVM Community Edition. El G1 GC, más capaz, se proporciona en Enterprise Edition. Sin embargo, en la última versión de la comunidad, el equipo de GraalVM también introdujo G1 GC [ 5] para proporcionar a los desarrolladores capacidades de compilación estática más potentes.

Adaptarse a la compilación estática de GraalVM

Después de presentar brevemente la tecnología de compilación estática y sus propias limitaciones en la sección anterior, muchos desarrolladores de comunidades externas pueden preguntarse en este momento: ¿cómo puede un proyecto de código abierto Java realizar rápidamente una compilación y adaptación estáticas? Para este problema, de hecho, el problema central esencial a resolver es convertir el contenido dinámico que GraalVM no puede reconocer ni procesar en el marco de código abierto en contenido reconocible. Por lo tanto, dado que este problema es diferente en diferentes marcos, la solución también tendrá algunas diferencias. Por ejemplo, en Spring, el motor AOT desarrollado para su propio marco puede resolver el problema de que el proceso de inicialización de las clases registradas proporcionadas por su marco no se puede reconocer en la fase de compilación estática a través de la anotación @Configuration, y el proxy dinámico que solo puede La clase que se genera en la fase de tiempo de ejecución se puede generar por adelantado durante la fase de compilación estática. Esta clase resuelve el problema de que las clases de proxy de compilación estática directa no se pueden generar de manera efectiva [6 ] para lograr la adaptación de compilación estática de las aplicaciones Spring.

Para muchos marcos de código abierto implementados en base a Spring, si las características dinámicas que GraalVM no puede reconocer son causadas por el uso estándar de Spring, ya que pertenecen al sistema Spring, el proceso de compilación estática definitivamente requerirá la participación del motor Spring AOT. Por lo tanto, el marco en sí no necesita proporcionar ninguna adaptación para tener capacidades de compilación estática.

Para proyectos que no son del sistema Spring o si usa alguna reflexión nativa u otras características dinámicas de Java en el JDK, debe proporcionar el archivo de configuración estática correspondiente en el proyecto para el uso dinámico de Java en su propio código para que el compilador pueda identificar durante el proceso de compilación estática. Las características dinámicas del proyecto deben compilarse y construirse para lograr una compilación y ejecución sin problemas del proyecto. En respuesta a esta situación, GraalVM proporciona un agente de seguimiento llamado agente de imagen nativa para ayudarlo a recopilar metadatos y preparar archivos de configuración de manera más conveniente. El Agente recopila automáticamente el uso de funciones dinámicas de las aplicaciones que se ejecutan en máquinas virtuales Java normales y las convierte en archivos de configuración que GraalVM puede reconocer. Finalmente, almacene el archivo de configuración dinámica del marco generado por el Agente en el directorio META-INF/native-image/<group.id>/<artifact.id> del proyecto, y podrá usar estas configuraciones durante el proceso de compilación estática. Contenido, identificación de características dinámicas en paquetes de proyectos.

Todos los clientes de middleware incluidos en la versión Spring Cloud Alibaba 2022.0.0.0 ahora han completado la adaptación para crear aplicaciones nativas de GraalVM. Debido a la naturaleza específica del proyecto en sí, existe una gran cantidad de usos de funciones dinámicas que GraalVM no puede reconocer debido a la sintaxis de Spring en la implementación general del proyecto. Este contenido lo resuelve directamente Spring AOT Engine y la comunidad. no realiza ningún trabajo de adaptación adicional.

Además de la sintaxis del sistema Spring, el proyecto en sí también tiene otros usos dinámicos de Java. Esta comunidad utiliza el agente de imagen nativo para realizar el análisis y la generación de configuración dinámica.

Cree microservicios basados ​​en compilación estática

Todos los clientes de middleware incluidos en la versión Spring Cloud Alibaba 2022.0.0.0 han completado la adaptación para crear aplicaciones nativas de GraalVM. Proporciona a los usuarios capacidades de compilación estática listas para usar. El proceso de experiencia de funciones relacionadas es el siguiente:

Preparación ambiental

Primero necesita instalar la distribución GraalVM en su máquina. Puede descargarlo manualmente en la página de Liberica Native Image Kit o utilizar un administrador de descargas como SDKMAN!. El entorno de demostración de este artículo es MacOS. Si es Windows, consulte el documento correspondiente [ 7] para su funcionamiento. Ejecute el siguiente comando para instalar el entorno GraalVM:

$ sdk install java 22.3.r17-nik
$ sdk use java 22.3.r17-nik

Verifique que esté configurada la versión correcta verificando el resultado de java -version:

$ java -version
openjdk version "17.0.5" 2022-10-18 LTS
OpenJDK Runtime Environment GraalVM 22.3.0 (build 17.0.5+8-LTS)
OpenJDK 64-Bit Server VM GraalVM 22.3.0 (build 17.0.5+8-LTS, mixed mode)

Creación de aplicaciones

Para utilizar la capacidad de compilación estática de GraalVM para crear microservicios, primero asegúrese de que la versión Spring Boot de su proyecto sea 3.0.0 o superior y que la versión Spring Cloud sea 2022.0.0 o superior. Luego, introduzca las dependencias del módulo requeridas de la versión Spring Cloud Alibaba 2022.0.0.0 en el proyecto.

Utilice los siguientes comandos para generar los archivos de configuración de sugerencias necesarios para la reflexión, la serialización y el proxy dinámico en la aplicación, siempre que el módulo principal spring-boot-starter-parent se introduzca en la aplicación:

$ mvn -Pnative spring-boot:run

Después de eso, la aplicación se iniciará y ejecutará previamente. Todas las funciones de la aplicación deben probarse lo más completamente posible para garantizar que la mayor parte del código de la aplicación esté cubierto por los casos de prueba. Este proceso se basará en la imagen nativa de GraalVM. -agente para recopilar características dinámicas en el programa, lo que garantiza que todos los atributos dinámicos necesarios durante la ejecución de la aplicación se generen por completo. Después de ejecutar todos los casos de prueba, descubrimos que se generarán los siguientes archivos de sugerencias en el directorio de recursos/META-INF/native-image:

  • Resource-config.json: archivo de sugerencias de recursos en la aplicación
  • reflect-config.json: archivo de sugerencias de definición de reflexión en la aplicación
  • serialization-config.json: archivo de sugerencias de contenido de serialización en la aplicación
  • proxy-config.json: archivo de sugerencias de contenido relacionado con el proxy Java en la aplicación
  • jni-config.json: archivo de sugerencias de contenido de Java Native Interface (JNI) en la aplicación

Nota: Todos los módulos principales de la versión oficial de Spring Cloud Alibaba 2022.0.0.0 incluyen de forma predeterminada el contenido de configuración requerido para las características dinámicas de sus propios componentes en sus dependencias, por lo que el proceso de preejecución anterior es principalmente para escanear la aplicación. propio código comercial y otro de terceros Las características dinámicas en el paquete de terceros garantizan que el proceso de compilación estática posterior pueda realizarse sin problemas y que la aplicación pueda iniciarse normalmente.

compilación estática

Una vez que los pasos anteriores estén listos, ejecute el siguiente comando para crear la imagen nativa:

$ mvn -Pnative native:compile

Después de una ejecución exitosa, podemos ver el archivo ejecutable generado en el directorio /target.

Programa en ejecución

No es diferente de un archivo ejecutable normal. Cuando inicia la aplicación a través de target/xxx, puede observar un resultado similar al siguiente:

2023-08-01T17:21:21.006+08:00  INFO 65431 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-08-01T17:21:21.008+08:00  INFO 65431 --- [           main] c.a.cloud.imports.examples.Application   : Started Application in 0.553 seconds (process running for 0.562)

Con la nueva versión de la aplicación Spring Cloud Alibaba que utiliza la tecnología de compilación estática GraalVM, todas las capacidades principales se han mejorado significativamente en términos de velocidad de inicio y uso de memoria, como se muestra en la siguiente tabla.

imagen

Nota: El ejemplo de código de prueba anterior proviene del módulo de ejemplos en el proyecto Spring Cloud Alibaba, entorno Mac 4c16g, cada conjunto de datos se prueba 3 veces y se promedia. Los datos específicos pueden variar según la máquina.

Otras actualizaciones de la comunidad

Nuevo sitio web oficial en línea

Desde el código abierto en 2018 hasta el lanzamiento de la primera versión GA en 2019, la comunidad ha pasado por 5 años. El proyecto ha lanzado 35 versiones y el número acumulado de estrellas supera las 26.000. Las soluciones de microservicio Spring Cloud Alibaba se utilizan ampliamente en diversas industrias. En el proceso de transformación digital en diversas industrias.

Dado que el proyecto Spring Cloud Alibaba es un estándar de solución de microservicio basado en Spring Cloud establecido conjuntamente con Spring, se implementa como un conjunto de soluciones de tecnología de microservicio que incorporan las décadas de experiencia en tecnología de microservicios de Alibaba. La documentación inicial y otro contenido relacionado del proyecto siempre han sido microservicios en el sitio web oficial spring.io. Sin embargo, la comunidad también descubrió gradualmente que debido a la imposibilidad de agregar contenido chino en spring.io, hay demasiados proyectos, lo que genera problemas como menos proyectos o contenido comunitario que un solo proyecto puede contener.

Por lo tanto, la comunidad se comunicó con los funcionarios de Spring y, con su apoyo, según los hábitos de los desarrolladores nacionales, se lanzó oficialmente el nuevo sitio web oficial de la comunidad. El nombre de dominio relevante es: sca.aliyun.com, donde sca es el acrónimo de Spring Cloud Alibaba del proyecto.

imagen

Introducción al nuevo confirmador

La comunidad Spring Cloud Alibaba ha visto varios contribuyentes externos participando activamente en iteraciones de mantenimiento de la comunidad en los últimos meses. ¡Me gustaría expresarles mi gratitud! Además, a Liu Ziming, quien ha estado participando en actividades comunitarias y haciendo importantes contribuciones al artículo, la comunidad lo nominó formalmente como Comisionado comunitario de acuerdo con el nuevo sistema de nominación y votación de Comisionados y aprobó la votación. Fue elegido exitosamente. ¡Felicitaciones a él! Más estudiantes externos pueden prestar atención a la comunidad de código abierto Spring Cloud Alibaba y contribuir a la comunidad de código abierto.

imagen

Enlaces relacionados:

[1] Análisis del proceso de inicio de programas Java
https://shipilev.net/talks/j1-Oct2011-21682-benchmarking.pdf

[2] Plataforma de ejecución multilingüe de alto rendimiento y código abierto GraalVM https://www.oracle.com/java/graalvm/

[3] Implementación externa https://www.graalvm.org/latest/reference-manual/native-image/metadata/

[4] Motor AOT
https://spring.io/blog/2021/12/09/new-aot-engine-brings-spring-native-to-the-next-level

[5] G1 GC
https://medium.com/graalvm/a-new-graalvm-release-and-new-free-license-4aab483692f5

[6] Problemas como la clase de proxy dinámico
https://docs.spring.io/spring-boot/docs/current/reference/html/native-image.html#native-image.introtaining-graalvm-native-images.understanding - mucho procesamiento

[7] Documento correspondiente
https://medium.com/graalvm/using-graalvm-and-native-image-on-windows-10-9954dc071311

Supongo que te gusta

Origin blog.csdn.net/alisystemsoftware/article/details/132476577
Recomendado
Clasificación