Spring Native 实现 0.059s 启动一个SpringBoot项目!

这篇具有很好参考价值的文章主要介绍了Spring Native 实现 0.059s 启动一个SpringBoot项目!。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

最近自己用Spring Cloud Alibaba做了一个微服务架构的项目,部署的时候遇到了难题:内存不够。目前该项目有7个微服务,因为我只有一台阿里云的服务器(2C 4G),所以我只能把所有的微服务部署在一台服务器上,部署方式是使用docker制作springboot的fat jar镜像,每个微服务在不加任何JVM调优参数的情况下所占内存约500M。

由于是微服务所以肯定还要部署:nacos,除此之外还用到了redis、sentinel、rocketmq、elk等(mysql买的阿里云的),光是运行这些应用就占用内存2个多G,剩下的1个多G内存在部署4个微服务后就满了,于是开始对springboot应用的内存进行初步优化:

添加JVM参数优化内存大小

# JVM初始分配的内存由-Xms指定,默认是物理内存的1/64
-Xms128m
# JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4
-Xmx128m
# 规定了每个线程虚拟机栈及堆栈的大小,一般情况下,256k是足够的,此配置将会影响此进程中并发线程数的大小。
-Xss256k
# 指定并行GC线程的数量,一般最好和CPU核心数量相当
-XX:ParallelGCThreads=2

默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制;空余堆内存大于70%时,JVM会减少堆直到 -Xms的最小限制。

因此服务器一般设置-Xms、-Xmx相等以避免在每次GC 后调整堆的大小。对象的堆内存由称为垃圾回收器的自动内存管理系统回收。

默认情况下,当 CPU 数量小于8, ParallelGCThreads 的值等于 CPU 数量,我的服务器是2C的所以这个参数可省略。配置完成后,启动服务发现内存确实变小了,由原来的500M降至100~200M,但不是我想要的效果,我期望的效果是达到几十M的级别。

经网上查阅大量资料得知可以使用Spring Native这门新技术来实现我的需求。(该技术正处于快速迭代阶段,变动较大,建议用于个人学习,不要用于生产)

SpringBoot项目使用Spring Native后:

  1. 应用启动速度特别快,毫秒级别
  2. 运行时更低的内存消耗,官方展示的含有Spring Boot, Spring MVC, Jackson, Tomcat的镜像大小是50M
  3. 为了达到前面的效果,代价是构建时间更长(即使是一个Hello Word构建也需要2分钟,不过主要取决于电脑配置,我的是2min左右)

Spring Native是什么

简而言之就是为了提高Java在云原生的竞争力(个人理解)。

以下内容摘抄自GitHub上Spring Native的自述文件:

Spring Native 为使用GraalVM 原生映像编译器将 Spring 应用程序编译为原生可执行文件提供 beta
支持,以提供通常设计为打包在轻量级容器中的原生部署选项。实际上,目标是在这个新平台上支持几乎未修改的 Spring Boot 应用程序。

以下内容摘抄自其他博客:

近几年“原生”一词一直泛滥在云计算、边缘计算等领域中,而原生宠幸的语言也一直都是Golang,Rust等脱离Sandbox运行的开发语言。Java得益于上世纪流行的一次编译,到处执行的理念,流行至今,但也因为这个原因,导致Java程序脱离不了JVM运行环境,使得不那么受原生程序的青睐。在云原生泛滥的今天,臃肿的JVM使Java应用程序对比其他语言显得无比的庞大,各路大神也想了很多方式让Java变的更“原生”。

Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java

实战

本次实战相关的环境信息如下:

  • OS:Windows10 21H1
  • IDE:IntelliJ IDEA 2021.2.3
  • JDK:graalvm-ce-java11-21.3.0
  • Maven:3.6.3
  • Docker Desktop for Windows: 20.10.12
  • Spring Boot:2.6.2
  • Spring Native:0.11.1
    Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java从官方文档得知(上图)

使用 Spring Native 的应用程序应该使用 Java 11 或 Java 17 编译。

构建 Spring Boot 原生应用程序有两种主要方法:

  1. 使用Spring Boot Buildpacks 支持生成包含本机可执行文件的轻量级容器。
  2. 使用GraalVM 原生镜像 Maven 插件支持生成原生可执行文件。

经过各种踩坑后在本机上成功的使用了方法1和方法2。简单来说:

方法1就是在SpringBoot2.3后,可以使用spring-boot-maven-plugin插件来构建docker镜像,使用mvn spring-boot:build-image命令结合Docker的API来实现Spring Boot 原生应用程序的构建,成功执行后会直接生成一个docker镜像,然后run这个镜像就可以了,不用我们再写Dockerfile了,相关的参数配置都在pom.xml中配置(该插件的configuration标签下,和fabric8或spotify的docker-maven-plugin很相似)。

方法2不需要安装docker,但要安装Visual Studio,然后执行mvn -Pnative package命令后会生成一个可执行文件(.exe),运行即可。

主要区别如下

1 环境依赖不同

  • 方法1需要安装Docker
  • 方法2需要安装Visual Studio(需要用到部分单个组件:2个MSVC,1个Windows 10 SDK)

2 执行的maven命令不同

  • 方法1是mvn spring-boot:build-image
  • 方法2是mvn -Pnative package

因为每个微服务使用Docker部署而不是exe文件,所以方法1正好符合我的需求,所以后文使用Spring Boot Buildpacks的方式构建Spring Boot原生应用程序。

安装Graal VM(graalvm-ce-java11-windows-amd64)

官方下载地址:

https://www.graalvm.org/downloads/
Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,javaSpring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java

配置环境变量

Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,javaSpring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java针对方法1的话,上面三张图好像只用配置JAVA_HOME就行,想一次成功的话建议3个都配,后续可以自行测试。

检验是否安装成功
Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java

安装native-image

打开新的cmd,输入以下命令,等待安装

gu install native-image

这一步我执行失败了,解决方法就是从github上手动下载native-image,然后解压、安装

https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-21.3.0/native-image-installable-svm-java11-windows-amd64-21.3.0.jar

jar用WinRAR也是可以解压的,解压后如下

Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java
在bin目录下打开cmd,输入以下命令,等待安装

$ gu install -L native-image*

安装 Desktop for Windows

具体步骤略,按照官方文档操作即可:

https://docs.docker.com/desktop/windows/install/

配置pom.xml

前面都是准备工作,这一步开始才是重点

首先快速创建一个Spring Boot项目,我命名为spring-native

完整的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>ltd.pcdd</groupId>
    <artifactId>spring-native</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-native</name>
    <description>spring-native</description>
    <properties>
        <java.version>11</java.version>
        <repackage.classifier/>
        <spring-native.version>0.11.1</spring-native.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.experimental</groupId>
            <artifactId>spring-native</artifactId>
            <version>${spring-native.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.experimental</groupId>
                <artifactId>spring-aot-maven-plugin</artifactId>
                <version>0.11.1</version>
                <executions>
                    <execution>
                        <id>generate</id>
                        <goals>
                            <goal>generate</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <!--Spring Boot 2.3发布后带来了新特性之一就是对构建镜像的便捷支持-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <image>
                        <builder>paketobuildpacks/builder:tiny</builder>
                        <env>
                            <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
                        </env>
                    </image>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>spring-release</id>
            <name>Spring release</name>
            <url>https://repo.spring.io/release</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-release</id>
            <name>Spring release</name>
            <url>https://repo.spring.io/release</url>
        </pluginRepository>
    </pluginRepositories>

</project>

本文介绍的是Spring Native0.11.1版本,其对应的Spring Boot版本必须是2.6.2,以上只是一个最基本的配置案例,实际开发中还需要在spring-boot-maven-plugin插件的configuration标签下配置其他许许多多的参数。

例如docker远程的地址和证书的路径、jvm调优参数、配置文件指定、docker镜像名端口仓库地址等等,最好的方法就是看spring-boot-maven-plugin的官方文档,这里以配置jvm参数为例

Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java通过官方文档得知只需要在configuration标签下配置即可,例如

<image>
 <builder>paketobuildpacks/builder:tiny</builder>
 <env>
  <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
  <BPE_DELIM_JAVA_TOOL_OPTIONS xml:space="preserve"> </BPE_DELIM_JAVA_TOOL_OPTIONS>
  <BPE_APPEND_JAVA_TOOL_OPTIONS>-Xms128m</BPE_APPEND_JAVA_TOOL_OPTIONS>
  <BPE_APPEND_JAVA_TOOL_OPTIONS>-Xmx128m</BPE_APPEND_JAVA_TOOL_OPTIONS>
  <BPE_APPEND_JAVA_TOOL_OPTIONS>-Xss256k</BPE_APPEND_JAVA_TOOL_OPTIONS>
  <BPE_APPEND_JAVA_TOOL_OPTIONS>-XX:ParallelGCThreads=2</BPE_APPEND_JAVA_TOOL_OPTIONS>
  <BPE_APPEND_JAVA_TOOL_OPTIONS>-XX:+PrintGCDetails</BPE_APPEND_JAVA_TOOL_OPTIONS>
 </env>
</image>

其他的配置参数还有很多。

官方文档:

https://docs.spring.io/spring-boot/docs/2.6.2/maven-plugin/reference/htmlsingle/#build-image

执行maven命令

mvn clean
mvn '-Dmaven.test.skip=true' spring-boot:build-image

下载完相关依赖后,电脑风扇就开始呼呼的转,查看任务管理器发现CPU利用率100%,内存使用量飙升,最后稳定在90%+。

构建成功
Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java

创建并运行容器

查看所有镜像
Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,javaspring-native就是构建的镜像

创建并运行容器
Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java在Docker Desktop查看日志,发现应用成功启动,启动仅耗时。,也就是59ms,果然印证了Spring Native启动是毫秒级别这句话。
Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java成功调用接口

Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java
在Docker Desktop查看占用内存,仅28M左右。

Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java不使用Spring Native启动应用
Spring Native 实现 0.059s 启动一个SpringBoot项目!,java,spring,spring boot,java启动耗时3s,占用内存高达511M,高下立判。

文章仅供参考,建议结合Spring Native官方最新文档学习。

https://docs.spring.io/spring-native/docs/current/reference/htmlsingle/index.html文章来源地址https://www.toymoban.com/news/detail-524333.html

到了这里,关于Spring Native 实现 0.059s 启动一个SpringBoot项目!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • IntelliJ IDEA下SpringBoot指定某一个配置文件启动项目

    Springboot项目有如下配置文件 主配置文件application.yml, 测试环境:application-test.yml 生产环境:application-pro.yml 开发环境:application-dev.yml 在开发过程中,通常在主配置文件里指定实际使用的配置文件: 如下图: 需要确保项目已经打成jar包: springboot-demo.jar 1).使用java -jar启动(

    2024年02月13日
    浏览(58)
  • 【Spring框架全系列】如何创建一个SpringBoot项目

    🌇哈喽,大家好,我是小浪。前几篇博客我们已经介绍了什么是Spring,以及如何创建一个Spring项目,OK,那么单单掌握Spring是完全不够的,Spring的家族体系十分强大,我们还需要深入学习,以便于我们后续达到能独立做项目的水平。今天我们来学习SpringBoot。🏜 📲目录 一、

    2024年02月03日
    浏览(50)
  • Springboot 3.0之Spring Native初体验

    Spring 3.0 中引入了一个新特性,即Spring 对Graalvm Image的支持。 Graalvm 官网 https://www.graalvm.org/native-image/ GraalVM编译器 Graalvm 是一个高效能,支持云原生的编译器。支持Java、JavaScript、Python、Ruby、R、WASM等多种语言。编译器的作用就是生成需要更少计算资源的更快、更精简的代码

    2024年02月04日
    浏览(51)
  • window服务器环境将springboot项目 jar包安装成一个window服务自启动

    目录 1.下载WinSW工具 2.新建一个Window Service信息的xml文件 3.将xml和exe重命名 4.安装卸载服务 5.修改配置文件 6.常用命令(注意winsw是exe名字 将下载的WinSW-x64.exe和新建的xml文件,名字需要保持一致 卸载需要 关闭服务后 再执行卸载命令,不然刷新后还会在服务列表,只是服务已经

    2024年02月08日
    浏览(38)
  • Spring Boot项目实现无数据库启动

    今天需要创建一个不连接数据库的Spring Boot工程, 结果一切配置好后项目却启动失败, 提示如下: 查询了一下资料, 发现原来Spring Boot启动时是默认是要连接数据库的, 这样一来只需要把数据库的一些配置排除掉就可以了: 重新启动, 项目成功运行了。另外, pom.xml文件中也不要引入

    2024年02月15日
    浏览(51)
  • SpringBoot项目启动后执行指定方法的四种实现

    今日的好天气 距离上一次更新帖子已经过了很久很久,久到我也不知道我在搞什么飞机。 国庆节第一天终于搬到了新家,最近量子纠缠比较火,冬天也在路上,匆匆又一年。 @PostConstruct是Java自带的注解,在方法上加该注解会在项目启动的时候执行该方法,也可以理解为在

    2023年04月15日
    浏览(44)
  • 从 0 开始实现一个 SpringBoot + Vue 项目

    参考:梦想屋A 后端开发软件:IntelliJ IDEA 前端开发软件:Visual Studio Code 后端框架:SpringBoot 后端语言:Java 前端框架:Vue 这是后面要用的妙妙小工具: 服务器连接工具:Termius 数据库:MySQL 数据库管理工具:Navicat Premium 数据库连接工具:MyBatis API 文档生成工具:Swagger API 文

    2024年02月21日
    浏览(39)
  • SimSearch:一个轻量级的springboot项目索引构建工具,实现快速模糊搜索

    大部分项目都会涉及模糊搜索功能,而实现模糊搜索一般分为两个派系: like简约派系 搜索引擎派系 对于较为大型的项目来说,使用Solr、ES或者Milvus之类的引擎是比较流行的选择了(效果只能说优秀),而对于中小型项目,如果考虑这些较为重型的引擎,就意味着开发成本和

    2024年02月02日
    浏览(92)
  • 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日
    浏览(47)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包