云原生应用之--SpringNative 实战

简介: 云原生应用之--SpringNative 实战

1.1 Graalvm

1.1.1 简介

GraalVM 是一种高性能运行时,可显着提高应用程序性能和效率,非常适合微服务. 对于 Java 程序 GraalVM 负责将 Java 字节码编译成机器码,映像生成过程使用静态分析来查找可从主 Java 方法访问的任何代码,然后执行完全提前 (AOT) 编译。生成的本机二进制文件包含机器代码形式的整个程序,以便立即执行。

1.

1.1.2 环境准备

  • Brew 安装

  brew install --cask graalvm/tap/graalvm-ce-lts-java11

  gu install native-image

1.2.1.2.

复制

  • 下载安装
  1. 下载 GraalVM : https://www.graalvm.org/downloads/
  2. 配置环境变量:JAVA_HOME 和 PATH
  3. 运行 gu install native-image

1.1.3 运行 demo

// 创建 HelloWorld.java 文件

public class HelloWorld {

   public static void main(String[] args) {

   

       System.out.println("Hello, World!");

   }

}

// 执行编译

javac HelloWorld.java

native-image HelloWorld

//运行

./helloworld

Hello, World!

1.2.3.4.5.6.7.8.9.10.11.12.13.1.2.3.4.5.6.7.8.9.10.11.12.13.

复制

1.2 Spring Native

1.2.1 简介

Spring Native 原生镜像可以在许多场景下降低工作负载,包括微服务,函数式服务,非常适合容器和 Kubernetes。优点:快速启动,提高峰值性能以及降低内存消耗缺点:构建过程慢, 预热后的运行时优化少常规 JVM 和此本机映像平台之间的主要区别:

  • 在构建时会从主入口点对应用程序进行静态分析。
  • 在构建时将未使用的零件删除。
  • 反射,资源和动态代理需要配置。
  • 类路径在构建时是固定的。
  • 没有类延迟加载:可执行文件中附带的所有内容都将在启动时加载到内存中。
  • 一些代码将在构建时运行。
  • 一些 Java 切面类的特性未得到完全支持。组成模块Spring Native 由以下模块组成:
  • spring-native:运行Spring Native所需的运行时依赖,还提供了Native hints API。
  • spring-native-configuration:Spring AOT 插件使用的 Spring 类的配置提示,包括各种 Spring Boot 自动配置。
  • spring-native-docs:参考指南,采用 asciidoc 格式。
  • spring-native-tools:用于查看镜像构建配置和输出的工具。
  • spring-aot:Maven 和 Gradle 插件公共的 AOT 转换基础架构。
  • spring-aot-gradle-plugin:AOT 转换的 Gradle 插件。
  • spring-aot-maven-plugin:AOT 转换的 Maven 插件。
  • samples:包含各种演示功能用法的示例,也用于集成测试。

2. 快速上手

主要有两种的方式来构建 Spring Boot 原生应用:使用 Spring Boot Buildpacks Support 生成一个包含本地可执行文件的轻量级容器。使用 GraalVM native image Maven plugin support 来生成本地可执行文件。

2.1 通过 Buildpacks 上手

2.1.1 系统要求

需要安装 Docker,并至少分配 8G 内存, 以及更多的 CPU

2.1.2 初始化 DEMO 项目

通过 https://start.spring.io/ 初始化 demo 工程

2.1.3 构建原生应用

可以按以下命令构建本地应用程序:

  • Maven $ mvn spring-boot:build-image
2.1.3.1 编译加速

资料:https://paketo.io/docs/howto/configuration/直接执行编译命令,因为要从 github 下载相关依赖,会非常慢,慢到你怀疑人生, 而且大多数时候会下载失败, 如图image.png则可以通过以下方法进行加速

  1. 下载构建需要的文件到本地,或上传到 OSS

https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-21.3.0

graalvm-ce-java11-linux-amd64-21.3.0.tar.gz

graalvm-ce-java11-linux-amd64-21.3.0.tar.gz.sha256 (sha256校验码)

native-image-installable-svm-java11-linux-amd64-21.3.0.jar

native-image-installable-svm-java11-linux-amd64-21.3.0.jar.sha256 (sha256校验码)

1.2.3.4.5.1.2.3.4.5.

复制

  1. 在工程根目录 bindings/dependency-mapping 创建 binding 文件
  2. 创建 type 文件:echo ‘dependency-mapping’ >type
  3. 查看文件校验码

也可以通过 https://github.com/paketo-buildpacks/graalvm/blob/main/buildpack.toml 网站进行查看

  1. 在工程根目录 bindings/dependency-mapping 创建 mapping 文件
  • 本地文件方式

echo 'file://{docker 内文件目录}/graalvm-ce-java11-linux-amd64-21.3.0.tar.gz'>3a1bc8eaf0518c128aaacb987ceb0b0e288776f48af630c11c01fd31122d93fa

echo 'file://{docker 内文件目录}/native-image-installable-svm-java11-linux-amd64-21.3.0.jar'>8958d4e0cad07340db0cf9e871776809e2f08fe0c93960f728fec75c4a96764f

1.2.1.2.

复制

  • Oss 方式

echo 'https://max-volador.oss-cn-hangzhou.aliyuncs.com/graalvm/dependency/graalvm-ce-java11-linux-amd64-21.3.0.tar.gz'>3a1bc8eaf0518c128aaacb987ceb0b0e288776f48af630c11c01fd31122d93fa

echo 'https://max-volador.oss-cn-hangzhou.aliyuncs.com/graalvm/dependency/native-image-installable-svm-java11-linux-amd64-21.3.0.jar'>8958d4e0cad07340db0cf9e871776809e2f08fe0c93960f728fec75c4a96764f

1.2.1.2.

复制

  1. 最后一步, 修改 pom.xml 配置,配置完成后就可以快乐的执行编译命令

<plugin>

  <groupId>org.springframework.boot</groupId>

  <artifactId>spring-boot-maven-plugin</artifactId>

  <configuration>

     <classifier>${repackage.classifier}</classifier>

     <image>

        <builder>paketobuildpacks/builder:tiny</builder>

        <env>

           <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>

           <SERVICE_BINDING_ROOT>/bindings</SERVICE_BINDING_ROOT>

        </env>

        <!-- 文件挂载 -->

        <bindings>

           <binding>${basedir}/bindings/dependency-mapping:/bindings/dependency-mapping</binding>

           <!--suppress UnresolvedMavenProperty -->

           <binding><absolute-binding-path>: {docker 内文件目录} </binding>

        </bindings>

     </image>

  </configuration>

</plugin>

1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.

2.1.4 运行原生应用

$ docker run --rm -p 8080:8080 demo:0.0.1-SNAPSHOT

1.1.

复制

2.2 通过原生镜像的 Maven 插件上手

2.2.1 系统要求

  1. Docker 8G 以上内存
  2. Graalvm 环境

2.2.2 初始化 DEMO 项目

通过 https://start.spring.io/ 初始化 demo 工程

2.2.3 构建原生应用

$ mvn -Pnative-image package上面的命令会创建一个本地可执行文件,该可执行文件在 target 目录中。

2.2.4 运行原生应用程序

$ ./target/demo

3. 开发进阶

3.1 Spring AOT

Spring AOT构建插件旨在通过利用应用程序的上下文(类路径,配置)来生成和编译源代码,从而改善本机图像的兼容性和占用空间。

3.1.1 Maven

<build>

   <plugins>

       <!-- ... -->

       <plugin>

           <groupId>org.springframework.experimental</groupId>

           <artifactId>spring-aot-maven-plugin</artifactId>

           <version>0.10.4</version>      

           <configuration>

               <removeSpelSupport>true</removeSpelSupport>

               <removeUnusedConfig>true</removeUnusedConfig>

               <removeYamlSupport>true</removeYamlSupport>

               <removeXmlSupport>false</removeXmlSupport>

           </configuration>

           <executions>

               <execution>

                   <id>test-generate</id>

                   <goals>

                       <goal>test-generate</goal>

                   </goals>

               </execution>

               <execution>

                   <id>generate</id>

                   <goals>

                       <goal>generate</goal>

                   </goals>

               </execution>

           </executions>

       </plugin>

   </plugins>

</build>

1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.

复制

3.1.2 配置 Spring AOT

  • mode 切换插件真实为本地镜像编译器提供多少配置:
  • native (默认)提供本地镜像以及代理的资源,初始化,代理和反射(使用自动配置提示)配置。
  • native-init 如果仅希望提供初始化配置和替换,则应使用。
  • native-agent 正在使用跟踪代理程序生成的配置作为基础,并且还为控制器等组件提供了其他提示。
  • removeXmlSupporttrue 默认情况下设置为 true,优化空间占用,将其设置为 false 恢复 Spring XML 支持(XML converters, codecs and XML application context support)。
  • removeSpelSupport默认情况下设置为 false,设置为 true 删除 Spring SpEL 支持以优化空间占用(应仅在不需要 SpEL 的应用中使用)。
  • removeYamlSupport 默认情况下设置为 false,设置为则true 删除Spring Boot Yaml支持以优化空间占用。
  • removeJmxSupport 默认情况下设置为 true,以优化空间占用,将其设置为false 恢复 Spring Boot JMX支持。
  • verify 默认情况下设置为 true,执行一些自动验证以确保应用可以本地编译, 设置为 false 关闭验证。
  • debugVerify 默认设置为false,设置为 true 时启用验证调试。
  • removeUnusedConfig默认情况下设置为 true,设置为 false 禁用删除未使用的配置。
  • failOnMissingSelectorHint 默认情况下设置为 true,如果没有为激活的选择器提供提示数据,则抛出错误,设置为 false 将插件从抛出错误切换为警告。
  • [Experimental] buildTimePropertiesMatchIfMissing 默认设置为 true。将其设置为 false 意味着指定 matchIfMissing=true 的任何属性都将被覆盖且不报错。
  • [Experimental] buildTimePropertiesChecks(实验)打开一些与属性相关的配置条件构建时间的评估。它必须至少包含 default-include-all或 default-exclude-all 的初始参数, 然后可以使用逗号分隔的前缀列表,以明确包含或排除(例如 default-include-all,!spring.dont.include.these.,!or.these 或 default-exclude-all,spring.include.this.one.though.,and.this.one)。前缀匹配最长的属性将会被应用(如果属性与多个前缀匹配)。

3.1.3. native-image 配置

Spring Native 通过 Spring AOT build plugin 在 META-INF/native-image 下自动生成配置文件 native-image.properties,reflect-config.json,proxy-config.json 或 resource-config.json:

3.2 Spring-native 扩展

3.2.1 通过 @NativeHint 实现

@NativeHint(options = "native-image 命令行参数",

types="反射类配置",

aotProxies="复杂代理类配置",

jdkProxies="JDK 动态代理类配置",

serializables="序列化类配置,

resources="资源文件配置",

initialization="应该在构建时或运行时显式初始化的类/包",

imports="共享类导入")

@NativeHint(options = {"-H:+ReportExceptionStackTraces"})

1.2.3.4.5.6.7.8.9.10.11.1.2.3.4.5.6.7.8.9.10.

复制

3.2.2 通过 配置文件实现

在 META-INF/native-image 下 ${groupId}.${artifactId} 新增配置文件

reflect-config.json: 反射配置

serialization-config.json: 序列化配置

proxy-config.json: 动态代理配置

resource-config.json: 外部文件配置

1.2.3.4.5.1.2.3.4.5.

复制

4. 常见问题

4.1 构建问题

4.1.1 在构建时意外初始化了 DataSize

Error: Classes that should be initialized at run time got initialized during image building:

org.springframework.util.unit.DataSize was unintentionally initialized at build time. To see why org.springframework.util.unit.DataSize got initialized use --trace-class-initialization

1.2.1.2.

复制

缺乏 spring-native 依赖项和Spring AOT plugin

4.1.2 构建本机映像时出现内存不足错误

Error: Image build request failed with exit status 137。native-image 会消耗大量 RAM,因此建议您使用至少 16G RAM 的计算机

4.1.3 Builder 生命周期 ‘creator’ 失败,状态码为 145

Error: Image build request failed with exit status 145。内存不足, 网络问题等

4.1.4 缺少资源包

Caused by: java.util.MissingResourceException:

 Resource bundle not found javax.servlet.http.LocalStrings.

 Register the resource bundle using the option

   -H:IncludeResourceBundles=javax.servlet.http.LocalStrings.

1.2.3.4.1.2.3.4.

复制

4.2 运行问题

4.2.1 序列化&反序列化失败问题

反序列化失败

DemoResponse(data=null, code=null, message= null)

序列化失败

在 META-INF/native-image/${groupId}/${artifactId}/serialization-config.json 添加需要进行序列化的类信息

[

{

  "name": "com.springnative.demo.response.DemoResponse"

}

]

1.2.3.4.5.6.7.8.9.1.2.3.4.5.6.7.8.9.

复制

4.2.2 反射问题

在 META-INF/native-image/${groupId}/${artifactId}/reflect-config.json 中添加需要用到反射的类信息

{

 "name": "com.springnative.demo.response.DemoResponse",

 "allDeclaredFields": true,

 "allDeclaredConstructors": true,

 "allDeclaredMethods": true,

 "allPublicMethods": true,

 "allDeclaredClasses": true

}

1.2.3.4.5.6.7.8.9.1.2.3.4.5.6.7.8.9.

复制

4.2.3 apache httpclient 调用失败, 采用 java.net.http.HttpClient 替换

4.2.4 mybatis-plus 初始化问题 & mapper 失效问题 (待补充)

5. 参考资料

Spring Native documentationGraalvmgraalvm-ce-buildsSpring-native Githubpaketo

相关文章
|
17天前
|
Cloud Native 安全 物联网
云原生技术在现代软件开发中的应用与挑战####
云原生,这一词汇如同一股强劲的科技风暴,席卷了整个信息技术领域,它不仅重塑了软件的开发模式,还引领了一场关于效率、可扩展性和弹性的深刻变革。本文旨在深入探讨云原生技术的核心概念,分析其在现代软件开发中的广泛应用,并直面伴随其发展而来的挑战,为读者勾勒出一幅既充满机遇又不乏考验的云原生技术图景。 ####
|
11天前
|
敏捷开发 Cloud Native 持续交付
云原生技术在现代企业中的应用与实践
【10月更文挑战第23天】本文将深入探讨云原生技术在现代企业中的广泛应用,并结合具体案例分析其对企业数字化转型的推动作用。我们将从云原生技术的基本原理出发,逐步揭示其在提高业务敏捷性、降低成本和增强系统可靠性方面的优势。同时,文章还将分享一系列成功实施云原生技术的企业案例,为读者提供实践中的参考和启示。最后,我们将讨论云原生技术面临的挑战及未来的发展趋势,为企业在这一领域的进一步探索提供指导。
|
12天前
|
Cloud Native 持续交付 云计算
云原生技术深度探索:构建现代化应用的基石####
【10月更文挑战第21天】 本文将深入探讨云原生技术的核心概念、关键技术及其在现代软件开发中的应用。我们将从容器化、微服务架构、持续集成/持续部署(CI/CD)、无服务器架构等关键方面展开,揭示这些技术如何共同作用,帮助企业实现高效、弹性且易于维护的应用部署与管理。通过实例分析,展现云原生技术在实际项目中的显著优势,为读者提供一套全面理解并应用云原生技术的指南。 ####
31 2
|
18天前
|
运维 Cloud Native 持续交付
云原生技术在现代IT架构中的深度应用与挑战####
【10月更文挑战第17天】 本文深入剖析了云原生技术的精髓,探讨其在现代IT架构转型中的核心作用与面临的挑战。云原生不仅是一种技术实现,更是企业数字化转型的重要推手,通过容器化、微服务、持续集成/持续部署(CI/CD)等关键要素,重塑软件开发、部署与运维模式。文章首先概述了云原生的基本原则与核心组件,随后分析了其如何促进企业敏捷性、可扩展性和资源利用率的提升,同时也指出了在安全性、复杂性管理及人才技能匹配等方面存在的挑战,并提出了相应的对策建议。 ####
52 6
|
19天前
|
运维 监控 Cloud Native
云原生技术在现代企业中的应用与挑战####
【10月更文挑战第15天】 本文深入探讨了云原生技术如何重塑企业的IT架构,并分析了其带来的机遇与面临的挑战。通过案例分析,揭示了云原生技术在提升业务敏捷性、降低运维成本方面的显著优势,同时也指出了在安全性、多云管理等方面的潜在难题,为企业决策者提供了有价值的参考。 ####
22 3
|
25天前
|
运维 Cloud Native 持续交付
云原生技术:构建现代应用的基石
【10月更文挑战第9天】在数字化转型的浪潮中,云原生技术如同一股清流,引领着企业走向更加灵活、高效的未来。本文将深入探讨云原生的核心概念,揭示其在现代应用开发与部署中的重要作用,并通过实际案例分析,展现云原生技术如何助力企业实现敏捷开发和自动化运维,最终提升业务竞争力。
73 3
|
26天前
|
运维 Kubernetes Cloud Native
云原生技术:构建现代应用的新范式
【10月更文挑战第9天】 云原生是一种通过云计算环境优化的软件开发和运行方法论,旨在最大化利用云平台的灵活性、可扩展性和弹性。本文将深入探讨云原生技术的基本原理、核心组件以及其在实际项目中的应用。我们将从Kubernetes的容器编排机制入手,逐步探讨如何通过自动化工具实现持续集成与持续部署(CI/CD),最终展示如何构建一个高效、可靠的云原生应用。
39 2
|
7天前
|
Cloud Native 安全 持续交付
云原生技术在现代软件开发中的应用与挑战####
本文深入探讨了云原生技术在现代软件开发中的广泛应用及其面临的主要挑战,旨在为开发者和企业提供实用的指导和策略。云原生技术通过其独特的架构和方法论,极大地提升了软件的可扩展性、弹性和敏捷性。然而,随着技术的不断演进,如何有效应对其在安全性、复杂性和成本控制等方面的挑战,成为了业界关注的焦点。本文将详细阐述云原生技术的核心概念、实际应用案例,并针对当前面临的主要挑战提出相应的解决策略。 ####
|
23天前
|
Cloud Native Devops 云计算
云原生技术:构建现代应用的新基石
【10月更文挑战第12天】 本文深入探讨了云原生技术的核心理念、关键技术和实践方法,揭示了其在现代应用开发和运维中的重要地位。通过分析云原生技术的发展趋势和面临的挑战,本文为读者提供了全面而深入的理解,旨在帮助读者更好地利用云原生技术构建高效、灵活和可扩展的现代应用。
34 0
|
23天前
|
Cloud Native 安全 云计算
云原生技术在现代企业中的应用与挑战
本文探讨了云原生技术在现代企业中的重要性及其应用,并分析了企业在实施过程中面临的主要挑战。通过案例分析,本文展示了如何利用云原生技术提高企业的敏捷性和弹性,同时提出了相应的解决方案和建议。