闷棍暴打面试官 SpringNative 源码系列: (一) 打造更适合Spring的原生镜像

 

Spring-Native 前世今生

当时前东家为了部署微服务测试服, ☁️上买了一台 8核16G 的高性能服务器, 一共的微服务组件有十来个, 只启动了半天才发现, 内存满了 (微服务服务真是启动的又慢又占内存也是没谁了), 当时只知道有两种解决办法, 1. 使用 swap 手动添加交换分区 2. 在☁️上点按钮在线添加内存. 当时图方便选了后者 升到了 32GB, 后来到要部署线上服务器时, 发现至少需要5 台同规格的服务器才能搞定, 因为机器增多, 维护也麻烦些, 但没办法只能无奈加内存啊, 不然它跑的不顺畅啊! 难道除了加内存就没有其他办法吗?

当然有, 那就是 Spring-Native, 它是下一代的Spring运行环境 ! 更轻更快更好 !

闷棍暴打面试官 SpringNative 源码系列: (一) 打造更适合Spring的原生镜像_第1张图片

我的是谁 ?

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

  • 具有Spring Cloud功能的无服务器

  • 以更便宜和更可持续的方式托管Spring微服务

  • 非常适合VMware Tanzu等Kubernetes平台

  • 想要创建最佳的容器映像来打包您的Spring应用程序和服务

闷棍暴打面试官 SpringNative 源码系列: (一) 打造更适合Spring的原生镜像_第2张图片

 

 

 

我有多强 ?

那么原生镜像到底是什么? 为什么会对优化启动速度与内存占有有这么大帮助? 让我们看看官方文档怎么说 !

这些原生的 Spring 应用可以作为一个(原生镜像)独立的可执行文件进行部署(不需要安装 JVM),并且还能提供有趣的特征,包括几乎瞬时的启动(一般会小于 100 毫秒)、瞬时的峰值性能以及更低的资源消耗,其代价是比 JVM 更长的构建时间和更少的运行时优化。

闷棍暴打面试官 SpringNative 源码系列: (一) 打造更适合Spring的原生镜像_第3张图片

 

原生镜像是一种将Java代码提前编译为独立可执行文件(称为本机映像)的技术。该可执行文件包括应用程序类,以及其依赖项的类,运行时库类以及JDK中的静态链接本机代码。它不是在Java VM上运行,而是包括必要的组件,例如内存管理,线程调度等,这些组件来自另一个运行时环境,称为“底层VM”。底层VM是运行时组件(例如反优化器,垃圾收集器,线程调度等)的名称。与JVM相比,生成的程序具有更快的启动时间和更低的运行时内存开销。

原生镜像构建器 是native-image 的一种实用程序,用于处理应用程序的所有类及其依赖项,包括来自JDK的那些类。它静态分析这些数据,以确定在应用程序执行期间可以访问哪些类和方法。然后,它会提前将可访问的代码和数据编译为适用于特定操作系统和体系结构的本机可执行文件。这整个过程称为构建镜像(或映像生成时间),以清楚地将其与Java源代码编译为字节码区分开。

本机映像支持基于JVM的语言,例如Java,Scala,Clojure,Kotlin。生成的图像可以选择执行动态语言,例如JavaScript,Ruby,R或Python。

 

https://www.graalvm.org/reference-manual/native-image/

-- GraalVM官网对原生镜像的解释

原生镜像提供了一种构建和运行具有不同于常规JVM部署特性的Spring Boot应用程序的方法:

  • 输出是一个本机可执行文件,其中包含您的应用程序以及JDK的子集以及运行它所需的依赖项。

  • 在实践中,可执行文件可能会以高度优化的容器映像(FROM scratch支持Docker镜像)的形式提供,并且减少了表面攻击,非常适合Kubernetes。

  • 启动时间几乎是即时的,并且可以立即获得峰值性能,从而支持从零缩放(无服务器)应用程序,包括常规的Spring Boot Web应用程序。

  • 减少了内存消耗,这非常适合拆分为多个微服务的系统。

正如您所期望的那样,原生镜像不是免费的午餐,并且这些有趣的功能还具有一些缺点:

  • GraalVM本机是一个年轻的平台,远没有JVM成熟。

  • JVM库尚未很好地支持这种Java的新风格并对其进行了测试。

  • 它需要初始化,资源,反射和代理显式配置。

  • 构建时间很长,并且构建内存消耗很高。

  • 较低的吞吐量和较高的延迟(更多详细信息)。

显然,原生镜像是一个移动的目标,并且其中一些特征可能会在将来发展。Spring团队目前正在与GraalVM团队积极合作,以确保通过Spring Boot集成为本地映像时,Spring以及在全球范围内通过Spring Boot集成的JVM生态系统都能正常工作。这项工作包括GraalVM本机中的修复和新功能,对Spring本身的更改,还包括为改善此GraalVM本机平台的可测试性和可维护性而进行的其他工作。

还值得注意的是,自Mark Reinhold最近宣布Project Leyden以来,原生镜像的范围现在已超过GraalVM ,该项目旨在在Java平台级别上对本地映像进行标准化。

这种对Spring Boot应用程序的原生镜像支持的独特之处在于,我们不仅针对新的Spring Boot应用程序,而且还针对数百万个现有的应用程序,以根据您的需求为您提供更多的部署选项。这是一个巨大的挑战,我们还没有处于每个Spring Boot应用程序都能“正常运行”的阶段,但是我们正在朝着正确的方向前进。

最后,值得一提的是,尽管许多增强功能都是出于创建最佳本机映像的目的而进行的,但这些更改不仅将改善本机映像的故事,而且还将改善Spring Boot应用程序在常规JVM上的运行方式。

https://spring.io/blog/2020/06/10/the-path-towards-spring-boot-native-applications

-- Spring官网对为何支持原生镜像的解释

 

显然原生镜像在内存占用与启动速度上要比 JVM 高很多, 那我们让 原生镜像编译器们 PK 一下基准与压力测试吧. GraalVM VS Quarkus Go !

基准测试环境

  • Spring-graalvm-native 0.7.1 (目前是0.9)

  • quarkus 1.5.2.Final

  • Java 11

  • SpringBoot 2.3.1.RELEASE

  • GCP

1.建设时间

闷棍暴打面试官 SpringNative 源码系列: (一) 打造更适合Spring的原生镜像_第4张图片

 

在尝试多次编译后,构建时间的不一致可能高达20-30秒。

2.一段时间内的CPU使用率(%)

 

3.随着时间的推移RAM使用率(%)

4.峰值RAM使用率

闷棍暴打面试官 SpringNative 源码系列: (一) 打造更适合Spring的原生镜像_第5张图片

 

5.二进制大小

闷棍暴打面试官 SpringNative 源码系列: (一) 打造更适合Spring的原生镜像_第6张图片

 

所有应用程序均以1s在2个vCPU或1个vCPU上启动,我认为不需要更详细地说明本节。

6.压力测试

数据库:6个vCPU,16个GiB RAM,SSD(us-west1-b)

应用:1个vCPU,2个GiB RAM(us-west1-b)

JMeter:4个vCPU,16个GiB RAM(us-west2-a)

JMeter VM位于不同的区域,因为我使用了每个区域限制有8个vCPU的免费试用帐户。

闷棍暴打面试官 SpringNative 源码系列: (一) 打造更适合Spring的原生镜像_第7张图片

闷棍暴打面试官 SpringNative 源码系列: (一) 打造更适合Spring的原生镜像_第8张图片

闷棍暴打面试官 SpringNative 源码系列: (一) 打造更适合Spring的原生镜像_第9张图片

GraalVM 是一种高性能的运行时环境,可显著提高应用程序的性能和效率,是微服务的理想选择。它设计用于以Java,JavaScript,基于LLVM的语言(例如C和C ++)以及其他动态语言编写的应用程序。它消除了编程语言之间的隔离,并实现了共享运行时的互操作性。

Quarkus 是一个为 Java 虚拟机(JVM)和原生编译而设计的全堆栈 Kubernetes 原生 Java 框架,用于专门针对容器优化 Java,并使其成为无服务器、云和 Kubernetes 环境的高效平台。

测试代码

https://github.com/ard333/native-binaries-benchmark​github.com

引用博文

https://medium.com/swlh/graalvm-native-image-spring-vs-quarkus-a738263df069​medium.com

看上去 Quarkus 性能要好一点, 但如果用Quarkus编译原生镜像可能要改代码的地方不少, 因为它对Spring支持不太友好, 在需要完美兼容现有的几百万Spring应用上, GraalVM 相对还是比较靠谱一点. 当然它们都在某些领域上对JVM进行了弯道超车.

 

如果我是Native, 你会爱我吗 ?

如果我们要将项目兼容原生镜像, 需要避免那些坑呢?

  1. 使用 start.spring.io 预先生成对应的项目以及加上SpringNative选项, 再把Spring-native 中的配置copy到项目中. 因为每次生产会创建HELP.md文件,其中包含有用的链接和文档,但还指示您是否选择了一些本机不支持的依赖项, 可以让你少趴一些坑。

  2. 确定 java 版本. 让 java -version 和 echo "%java_home%" 结果保持一致. 推荐升级 java 11 lts

  3. 安装 docker

具体可以参考该文章

https://www.infoq.com/news/2021/03/spring-native-beta-available/​www.infoq.com

 

 

扫码回复 "加群" 和我一起月入 20K+

 

闷棍暴打面试官 SpringNative 源码系列: (一) 打造更适合Spring的原生镜像_第10张图片

深入浅出分享 Java 干货 , 找回对代码的 Passion , 助力月入 20K+

 

 

你可能感兴趣的:(公众号,java,大数据,服务器,负载均衡,运维)