Haga que el paquete jar para su proyecto SpringBoot sea delgado

Spring boot está empaquetado de la forma predeterminada porque es un paquete completamente dependiente (también llamado paquete fat), que no solo es lento de empaquetar, grande en tamaño y lento en transmisión. Hoy, te enseñaré cómo adelgazar Spring Boot.

antecedentes

Ahora que la arquitectura de microservicios se está volviendo cada vez más popular, son muy comunes más de 10 módulos de servicio basados ​​en Spring Boot para un proyecto. Suponiendo que un módulo de servicio está marcado como un paquete jar de 100M, entonces una versión completa puede necesitar cargar archivos 1G. Cuando la condición de la red es buena, es posible que no sienta mucho, pero si el código necesita copiarse en la intranet para su publicación o cargarse en algunos servidores externos, afectará seriamente la eficiencia del trabajo.

Entonces, ¿hay alguna manera de hacernos adelgazar el paquete del jar de la bota de primavera?
La respuesta es sí, cuando Spring Boot se empaqueta a través de la configuración relevante, solo se cargan algunos paquetes de dependencia que a menudo cambian, como el módulo común del proyecto, algunos módulos API que llaman a la interfaz fingida y esos paquetes de dependencia fija se cargan directamente en el servidor. En el directorio especificado, puede especificar el directorio donde se carga el paquete lib mediante el comando cuando se inicia el proyecto. De esta manera, el paquete jar que escribimos tiene menos de unos pocos megabytes como máximo, lo que reduce en gran medida el tamaño del paquete jar del proyecto Spring Boot y mejora la eficiencia de publicación y ejecución.

Suplemento:
frasco de grasa : frasco de grasa, el paquete del frasco que se escribe contiene todos los paquetes dependientes.
La ventaja es que se puede ejecutar directamente sin agregar otros comandos, pero la desventaja es que es demasiado grande y difícil de transmitir.

** thin jar: ** significa paquete delgado. El paquete jar que se escribe solo contiene algunos paquetes de dependencia que se cambian con frecuencia, generalmente módulos públicos en el proyecto o algunos módulos dependientes de la interfaz API.
La ventaja es que es de tamaño pequeño, lo que contribuye a mejorar la eficiencia del lanzamiento del proyecto; la
desventaja es que puede haber riesgos de seguridad al depender de paquetes externos. Si la dependencia maven del proyecto cambia con frecuencia, es más problemático mantener el directorio lib en el servidor y no conduce a la ubicación del problema.

Ejercicio adelgazante

1. Modificar los parámetros de empaquetado de maven

<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <layout>ZIP</layout>
                     <includes>
                         <include>
                             <groupId>nothing</groupId>
                             <artifactId>nothing</artifactId>
                         </include>
                         <include>
                             <groupId>com.huacloud.tax.rpc</groupId>
                             <artifactId>common</artifactId>
                         </include>
                     </includes>
                </configuration>
            </plugin>
        </plugins>
    </build>

Descripción:

El diseño
utilizado para configurar el tipo de paquete jar ejecutable Main-Class, debe establecerse en el ZIP, de modo que un jar golpee la Main-Class sea PropertiesLauncher.

incluye
tendrá que mantener el paquete frasco, de acuerdo con groupId y artifactId (Tenga en cuenta que ambos son necesarios) incluir en.
Nada significa paquetes dependientes inexistentes, lo que significa que
los módulos de servicios comunes se importan sin paquetes dependientes .

2. Ejecute el paquete maven:
primero ejecute mvn clean y luego mvn package
Inserte la descripción de la imagen aquí
para copiar el paquete que se ha impreso en el directorio de destino al directorio D: \ web, y renómbrelo a tax-ws-thin-zip.jar.

Verifique el archivo MANIFEST.MF en el directorio META-INF en tax-ws-thin-zip.jar a través de la herramienta de compresión: se
Inserte la descripción de la imagen aquí
encuentra que el valor de Main-Class efectivamente ha cambiado a PropertiesLauncher, lo que indica que nuestra configuración es exitosa.
(En cuanto a por qué Main-Class debe configurarse como PropertiesLauncher, lo presentaré más adelante)

3. Compare el volumen de FatJar y ThinJar: Se
Inserte la descripción de la imagen aquí
puede encontrar que el volumen del paquete delgado tax-ws-thin.jar es mucho menor que el volumen del paquete de grasa.

4. Copie el paquete lib del paquete fatJar al directorio D: \ web
Inserte la descripción de la imagen aquí
5. Inicie el paquete jar con el comando

D:\web>java -Dloader.path="D:\web\lib"  -jar tax-ws-thin.jar

Configure la ruta de carga del paquete dependiente externo a través del parámetro de inicio loader.path.

El inicio exitoso del proyecto indica que el paquete de dependencia subcontratado que configuramos se ha cargado en vigencia.

Exploración de principios

¿Por qué configurar Main-Class del paquete jar ejecutable en PropertiesLauncher para especificar la ruta de carga del paquete dependiente configurando el parámetro de inicio loader.path?
En primer lugar, tenemos cierta comprensión del Lanzador en el principio de implementación del paquete jar ejecutable de Spring Boot.

Lo siguiente se tomó del sitio web oficial de arranque de Spring: La
clase org.springframework.boot.loader.Launcher es una clase de programa de arranque especial que sirve como punto de entrada principal para el jar ejecutable. Es la Main-Class real en el archivo jar, que se usa para configurar el URLClassLoader apropiado y finalmente llamar al método main ().

Hay tres subclases de lanzadores ( JarLauncher, WarLauncher y PropertiesLauncher ). Su propósito es cargar recursos (archivos .class, etc.) desde archivos jar anidados o archivos war en el directorio (en lugar de archivos explícitamente en la ruta de clases). Para JarLauncher y WarLauncher, la ruta de anidación es fija. JarLauncher se encuentra en BOOT-INF / lib /, mientras que WarLauncher se encuentra en WEB-INF / lib / y WEB-INF / lib-provided /. Si es necesario, se pueden agregar frascos adicionales en estas ubicaciones. De forma predeterminada, PropertiesLauncher busca en BOOT-INF / lib / en el archivo de su aplicación. Puede agregar otras ubicaciones configurando una variable de entorno llamada LOADER_PATH o loader.path en loader.properties (esta es una lista separada por comas de directorios, archivos de almacenamiento o directorios en archivos de almacenamiento).
————————————————

En otras palabras, el Launcher Launcher carga recursos dependientes para el inicio del proyecto. Hay 3 lanzadores ( JarLauncher, WarLauncher y PropertiesLauncher ). Las rutas para JarLauncher y WarLauncher para cargar recursos son fijas, y se puede acceder a PropertiesLauncher a través de la variable de entorno loader.path Especifique dónde cargar los recursos.
Inserte la descripción de la imagen aquí

Descripción del valor del atributo de diseño:

JAR, el jar ejecutable habitual
Main-Class: org.springframework.boot.loader.JarLauncher

WAR, es decir, la guerra ejecutable habitual, la dependencia del contenedor de servlets requerida se encuentra en
Main-Class: org.springframework.boot.loader.warLauncher

ZIP , o DIR, similar a JAR
Main-Class: org.springframework.boot.loader.PropertiesLauncher
(solo recuerde esto, hay algunos otros escenarios de aplicación)

Configuración de la propiedad PropertiesLauncher

PropertiesLauncher tiene algunas características especiales que se pueden habilitar a través de propiedades externas (propiedades del sistema, variables de entorno, entradas de manifiesto o loader.properties). La siguiente tabla describe estos atributos:

Llave propósito
loader.path ruta de carga del paquete lib
loader.home Se utiliza para resolver rutas relativas en loader.path. Por ejemplo, dado loader.path = lib, $ {loader.home} / lib es la ubicación de la ruta de clases (y todos los archivos jar en ese directorio). Esta propiedad también se utiliza para buscar el archivo loader.properties, como se muestra en el siguiente ejemplo / opt / app. Su valor predeterminado es $ {user.dir}.
loader.args Los parámetros predeterminados del método principal (separados por espacios).
loader.main El nombre de la clase principal para comenzar (por ejemplo, com.app.Application)
loader.config.name La ruta del archivo de propiedades (por ejemplo, classpath: loader.properties). El valor predeterminado es loader.properties.
loader.system Bandera booleana que indica que todos los atributos deben agregarse a las propiedades del sistema. El valor predeterminado es falso.

Para obtener más información, puede ver la documentación sobre el paquete jar ejecutable de Spring Boot en el sitio web oficial: El formato Jar ejecutable

Corrección de trampas

He visto una forma en Internet que no configura layout = ZIP, pero después de marcarlo directamente como un paquete delgado, use -Djava.ext.dirs en el comando de inicio para especificar la ruta de carga del paquete de dependencia externa.

D:\web>java -Djava.ext.dirs="D:\web\lib"  -jar tax-ws-thin.jar

Análisis de principio:
-Djava.ext.dirs anulará la configuración ext de Java. El directorio especificado por java.ext.dirs lo carga el cargador ExtClassLoader. Si su programa no especifica la propiedad del sistema, el cargador cargará $ JAVA_HOME / por defecto Todos los archivos jar en el directorio jre / lib / ext. Pero si especifica manualmente las propiedades del sistema y olvida agregar la ruta $ JAVA_HOME / jre / lib / ext, ExtClassLoader no cargará los archivos jar en $ JAVA_HOME / lib / ext, lo que significa que perderá algunas funciones. Por ejemplo, se implementa el propio algoritmo de cifrado y descifrado de Java.

Por lo tanto, mediante esta forma de escritura, modificar directamente a la fuerza la ruta de carga del cargador de clases extendido predeterminado de Java puede causar fácilmente algunos problemas. Es mejor no usarlo a la ligera.

No se puede encontrar el paquete de controladores de Oracle

Al usar -Djava.ext.dirs para configurar la ruta de carga del paquete de dependencia externa, existe un problema de que el paquete de controladores de Oracle no se puede cargar. En este momento, debe agregar
-Doracle.jdbc.thinLogonCapability = o3 para configurar la compatibilidad de inicio de sesión de Oracle

Extensión: mecanismo de delegación parental

La expansión aquí implica el mecanismo de carga de la delegación principal de Java.
Inserte la descripción de la imagen aquí

1. BootStrapClassLoader: inicia el cargador de clases. El cargador de clases se crea al inicio y se escribe en el kernel de la JVM. No es un archivo de código de bytes, sino un código binario escrito en c ++, por lo que el desarrollador no puede iniciar La referencia de la clase no se puede operar por referencia. Este cargador es para cargar la biblioteca de clases bajo $ JAVA_HOME / jre / lib (o especificado por el parámetro -Xbootclasspath).

2. EXTClassLoader: cargador de clases extendido, ExtClassLoader cargará la biblioteca de clases bajo $ JAVA_HOME / jre / lib / ext (o especificado por el parámetro -Djava.ext.dirs).

3. AppClassLoader: el cargador de aplicaciones cargará la biblioteca de clases en la ruta especificada por la variable de entorno java CLASSPATH, y la ruta especificada por CLASSPATH se puede obtener a través de Systemn.getProperty ("java.class.path"), que se puede sobrescribir .

4. CustomClassLoader: El cargador personalizado es el CLassLoader definido por el usuario Por ejemplo, el standardClassLoader de tomcat pertenece a esta categoría.

Mecanismo de delegación principal de ClassLoader:
1. Cuando APPClassLoader carga una clase, no cargará primero la clase por sí mismo, sino que delegará la solicitud de carga de clases al cargador de clases principal EXTClassloader para completar.

2. Cuando EXTClassLoader carga una clase, no intentará cargar la clase primero, sino que delega la solicitud de carga de la clase a BootStrapClassLoader para completar.

3. Si BottStrapClassLoader no se carga, se utilizará EXTClassLoader para intentar cargar.

4. Si EXTClassLoader no se carga, utilizará APPClassLoader para cargar. Si APPClassLoader tampoco se carga, informará una excepción ClassNotFundException.

para resumir

1. ¿Por qué desea hacer que el paquete jar ejecutable del proyecto de arranque de primavera sea delgado
? 2. Los tres arrancadores de arranque de primavera explican
3. Cómo configurar el arrancador de PropertiesLauncher para realizar la carga de paquetes de dependencias externas
4. Indíquelo especificando -Djava.ext.dirs Implementación de parámetros del problema de carga del paquete de dependencia externa
5. La extensión explica el mecanismo de carga de la delegación principal de Java
6. La solución al problema de que el paquete de dependencia externa no se puede cargar con el paquete de controladores de Oracle

Al final

Gracias por su apoyo reciente. Aunque dice que el aprendizaje es asunto suyo, es realmente alentador ver sus me gusta, comentarios y atención. Gracias a todos.
Continuaré trabajando duro para compartir más artículos técnicos de alta calidad y espero comunicarme y crecer con ustedes.

Más emocionante, sígueme.
Leyenda: sigue al anciano para aprender java

Supongo que te gusta

Origin blog.csdn.net/w1014074794/article/details/106445145
Recomendado
Clasificación