SpringBoot3.x原生镜像-Native Image实践

这篇具有很好参考价值的文章主要介绍了SpringBoot3.x原生镜像-Native Image实践。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前提

之前曾经写过一篇《SpringBoot3.x 原生镜像-Native Image 尝鲜》,当时SpringBoot处于3.0.0-M5版本,功能尚未稳定。这次会基于SpringBoot当前最新的稳定版本3.1.2详细分析Native Image的实践过程。系统或者软件版本清单如下:

组件 版本 备注
macOS Ventura 13.4.1(c) ARM架构
sdkman 5.18.2 JDK和各类SDK包管理工具
Liberica Native Image Kit 23.0.1.r17-nik 可以构建Native ImageJDK
SpringBoot 3.1.2 使用当前(2023-08-20)最新发布版
Maven 3.9.0 -

安装 sdkman

sdkman是一个轻量级、支持多平台的开源开发工具管理器,可以通过它安装任意主流发行版本(例如OpenJDKKonaGraalVM等等)的任意版本的JDK。通过下面的命令可以轻易安装sdkman:

curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
sdk version

可以通过sdk list java查看支持的JDK发行版本:

通过shell命令sdk install java $Identifier就可以安装对应的JDK发行版。例如可以这样安装GraalVM-ce-17:

sdk install java 17.0.8-graalce

通过shell命令sdk uninstall java $Identifier可以卸载对应的JDK发行版。如果安装了多个版本或者多个发行版的JDK,可以通过shell命令sdk default java $Identifier去指定默认使用的JDK版本,例如:

sdk default java 17.0.8-graalce

可以通过shell命令sdk current或者sdk current java查看当前正在使用的SDK或者JDK版本。

安装 Liberica NIK

Liberica Native Image Kitbellsoft出品的旨在创建高性能原生二进制(Native Binaries)基于JVM编写的应用的工具包,简称为Liberica NIKLiberica NIK本质就是把OpenJDK和多种其他工具包一起封装起来的JDK发行版,在Native Image功能应用过程,可以简单把它视为OpenJDK + GraalVM的结合体。可以通过sdk list java查看相应的JDK版本:

这里选择JDK-17的版本进行安装:

sdk install java 23.0.1.r17-nik
# 这里最好把此JDK设置为当前系统的默认JDK,否则后面编译镜像时候会提示找不到GraalVM
sdk default java 23.0.1.r17-nik

安装完成后,通过java -version验证一下:

编写 SpringBoot 应用

基于Maven新建一个SpringBoot应用,这里已经整理好了一份POM文件,实践过程可以直接用,如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>cn.vlts</groupId>
    <artifactId>spring-boot-native-image-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.2</version>
        <relativePath/>
    </parent>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.version>3.11.0</maven.compiler.version>
        <maven.install.version>3.1.1</maven.install.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.tomcat.embed</groupId>
                    <artifactId>tomcat-embed-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>org.apache.tomcat.embed</groupId>
                    <artifactId>tomcat-embed-websocket</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.experimental</groupId>
            <artifactId>tomcat-embed-programmatic</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <groupId>org.apache.maven.plugins</groupId>
                <version>${maven.compiler.version}</version>
                <configuration>
                    <source>${maven.compiler.source}</source>
                    <target>${maven.compiler.target}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-install-plugin</artifactId>
                <version>${maven.install.version}</version>
            </plugin>
            <plugin>
                <groupId>org.graalvm.buildtools</groupId>
                <artifactId>native-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <mainClass>cn.vlts.NativeImageApplication</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

这里把Maven的所有插件都提升到当前(2023-08-20前后)最新版本,原生镜像打包的关键插件是native-maven-plugin,此插件是跟随spring-boot-starter-parent进行版本管理,这里无须指定插件的版本。另外,tomcat-embed-programmatic是一个实验性依赖,可以降低嵌入式Tomcat的内存使用,在生产中应用时候可以暂不启用此特性。接着编写启动类cn.vlts.NativeImageApplication

@SpringBootApplication
@RestController
public class NativeImageApplication {

    public static void main(String[] args) {
        SpringApplication.run(NativeImageApplication.class, args);
    }

    @RequestMapping(path = "/")
    public ResponseEntity<String> index() {
        return ResponseEntity.ok("index");
    }
}

构建、测试与发布

三个操作的Maven命令分别是:

  • 构建:mvn -Pnative native:compile
  • 测试:mvn -PnativeTest test
  • 发布:mvn -Pnative spring-boot:build-image,注意此命令会打包镜像并且发布到Docker的官方仓库中

虽然 native:compile 命令表面意义是编译,但是实际上它就是构建原生镜像的命令

执行构建流程:

mvn -Pnative native:compile -Dmaven.test.skip=true

构建结果如下:

其中这个不带.jar后缀的就是最终的原生镜像,并且Native Image是不支持跨平台的,它只能在ARM架构的macOS中运行(受限于笔者的编译环境)。可以发现它(见上图中的target/spring-boot-native-image-demo,它是一个二进制执行文件)的体积比executable jar大好几倍。参照SpringBoot的官方文档,经过AOT编译的SpringBoot应用会生成下面的文件:

  • Java源代码
  • 字节码(例如动态代理编译后的产物等)
  • GraalVM识别的提示文件:
    • 资源提示文件(resource-config.json
    • 反射提示文件(reflect-config.json
    • 序列化提示文件(serialization-config.json
    • Java(动态)代理提示文件(proxy-config.json
    • JNI提示文件(jni-config.json

这里的输出非执行包产物基本都在target/spring-aot目录下,其他非Spring或者项目源代码相关的产物输出到graalvm-reachability-metadata目录中。最后可以验证一下产出的Native Image

可以看到启动速度达到惊人的毫秒级别,如果应用在生产中应该可以全天候近乎无损发布。当然,理论上Native Image性能也会大幅度提升,但是限于篇幅这里暂时不进行性能测试。

小结

鉴于SpringBoot3.x的正式版已经推出一段时间,从文档上看,Native Image使用的技术已经相对成熟,可以放心用于生产环境。当然,Native Image目前还存在一些局限性会让一些组件完全无法使用或者部分功能受限(参考Spring Boot with GraalVM),希望这些问题或者局限性有一天能够突破让所有JVM应用迎来一次性能飞跃。

(本文完 c-2-d e-a-20230820)文章来源地址https://www.toymoban.com/news/detail-660579.html

到了这里,关于SpringBoot3.x原生镜像-Native Image实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • SpringBoot3.0新特性:1、spring.factories文件废弃,自动配置包位置变化 2、Spring Native 快速体验 3、jakata api迁移 3、三方库的支持

    有自己写过starter包的友友们一定知道,一定用/META-INF/spring.factories文件定义发现自动配置,但是在springboot 2.7,这个文件就被弃用了,在springboot 3.0 就被彻底移除了。 比如之前定义的/META-INF/spring.factories文件: 而现在 这个/META-INF/spring.factories并不是不存在了,只是在3.0之后 外

    2024年02月10日
    浏览(35)
  • Redis之缓存穿透问题解决方案实践SpringBoot3+Docker

    当一种请求,总是能越过缓存,调用数据库,就是缓存穿透。 比如当请求一个数据库没有的数据,那么缓存也不会有,然后就一直请求,甚至高并发去请求,对数据库压力会增大。 如果 key 具有某种规则,那么可以对key增加校验机制,不符合直接返回。 Redisson 布隆过滤器 逻

    2024年02月21日
    浏览(38)
  • 【云原生|Docker系列第3篇】Docker镜像的入门实践

    欢迎来到Docker入门系列的第三篇博客!在前两篇博客中,我们已经了解了什么是Docker以及如何安装和配置它。本篇博客将重点介绍Docker镜像的概念,以及它们之间的关系。我们还将学习如何拉取、创建、管理和分享Docker镜像,这是使用Docker的重要步骤之一。 Docker镜像是Docke

    2024年02月16日
    浏览(27)
  • 云原生之容器编排实践-在K8S集群中使用Registry2搭建私有镜像仓库

    基于前面搭建的3节点 Kubernetes 集群,今天我们使用 Registry2 搭建私有镜像仓库,这在镜像安全性以及离线环境下运维等方面具有重要意义。 Note: 由于是测试环境,以下创建了一个 local-storage 的 StorageClass ,并使用本地磁盘的方式创建使用 PV ,实际建议使用 NFS 。 共用到了三台

    2024年02月19日
    浏览(36)
  • SpringBoot与SpringCloudAzure:微软云原生应用实践

    微软的Azure是一款云计算平台,它为开发者提供了一系列的云服务,包括计算、存储、数据库、AI等。Spring Boot是一款Java应用程序开发框架,它简化了开发人员的工作,使得他们可以快速地构建出高质量的应用程序。Spring Cloud是一款基于Spring Boot的云原生应用开发框架,它提供

    2024年02月21日
    浏览(28)
  • graalvm安装并使用native-image

    下载graalvm,可以直接去官网下载 https://www.graalvm.org/downloads/ github地址 https://github.com/graalvm/graalvm-ce-builds/releases/tag/vm-22.1.0 这里以jdk11为例 https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.1.0/graalvm-ce-java11-windows-amd64-22.1.0.zip native-image的jar https://github.com/graalvm/graalvm-ce-builds/r

    2024年02月06日
    浏览(40)
  • 我把Solon打包成了native image,速度快的惊人

    Solon 一个高效的应用开发框架:更快、更小、更简单。https://solon.noear.org/ 我刚开始对 Solon 感兴趣的原因,就是启动快、包体积小,用了一段时间之后,发现 Solon 使用 GraalVM native iamge 打包有一些问题,我把问题发到 Solon 用户群里,作者告诉我 Solon 的原生编译还 beat 阶段,只

    2023年04月27日
    浏览(31)
  • React Native expo项目使用expo-image-picker上传图片

     app.json: https://docs.expo.dev/versions/latest/sdk/imagepicker/      expo-image-picker 图片上传 要使用Expo的ImagePicker库进行图片上传,您可以按照以下步骤操作。 首先,确保您已在项目中安装了Expo的ImagePicker库。 然后,您可以使用以下代码来选择图片并上传: 此示例使用Button和Image组件创

    2024年02月15日
    浏览(31)
  • Spring Boot 3.0 GA来啦,GraalVM Native Image Support初体验

    2022-11-25, SpringBoot 3.0.0 GA 版本发布,带了Web Javaer万众期待的 Cloud Native 特性,这也意味着占据Java Web圈半壁江山的Spring框架正式进入真正的云原生时代。笔者作为一名多年的Java Web开发者,异常激动和兴奋,因为尽管java生态圈在全球开发领域占据非常大的份额,国内各类IT企

    2023年04月09日
    浏览(32)
  • Day920.结构化日志&业务审计日志 -SpringBoot与K8s云原生微服务实践

    Hi,我是 阿昌 ,今天学习记录的是关于 结构化日志业务审计日志 的内容。 结构化日志 (Structured Logging)是一种将日志信息组织为结构化数据的技术。 传统的日志通常是一些文本信息,比如一行记录一个错误或者事件,这些信息往往是自由格式的。 相比之下,结构化日志则

    2023年04月09日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包