Quarkus-云原生时代Java的曙光

00 引言

至今已满27岁的Java语言已经长期占据服务端编程语言开发榜的榜首,无论是从生产环境的部署规模,还是从在开发者群体中的受欢迎程度来看,Java都拥有绝对的“统治”地位。庞大的开发者基础、丰富完善的类库和生态、以及大规模的线上服务和应用都使得Java拥有其他编程语言难以超越的优势,也奠定了Java如今的地位。但居安思危,Java能否一直保持这种领先优势以及如何保持这种优势地位是包括Oracle官方在内的所有开发者应该思考的问题,也值得每位使用Java作为生产力工具的开发者关注。

01 云原生时代下Java的挑战

(1)Compile Once,Run AnyWhere

Java诞生之初,得益于虚拟机的优势,使得“一次编译,到处运行”成为其最响亮的Slogan,在一定程度上加速了Java的火热,然而这种根植在Java基因中的优势在“容器时代”正在逐渐被淡化,至少不像之前那样重要。在以前,如果需要一套代码同时运行在Linux、Solaris、Windows等系统之上,那开发人员不得不考虑不同平台甚至不同指令集之间的差异性,而Java虚拟机恰好将开发/运维人员从这种“苦海”中解脱了出来。但随着容器等云原生技术的普及,能够包含底层操作系统和程序代码的镜像成为了一种更加标准化和通用的交付产品,并且开发人员只需要修改几行Dockerfile就能修改程序的运行时环境。在云原生时代,通过镜像屏蔽底层系统的差异,以极低的成本更新程序的运行环境等,这些都削弱了Java的传统优势特性。

(2)启动耗时&内存占用

无论是从JVM垃圾回收器的演进方向还是从JIT优化的角度来看,这都表明Java更适用于大规模、长时间运行的应用,对于运行时间很短或者需要频繁更新的应用来说,Java难免会表现出一些不适应。但随着Kubernetes等技术的飞速发展,应用的实时更新、蓝绿发布、动态扩缩容相比以前更加容易实现,而这些功能都需要应用频繁启停,不可能像之前一样长时间运行。从启动过程来看,Java程序在启动时需要执行虚拟机初始化、字节码文件加载解析、JIT预热等功能,这些都使得启动时间过长,难以在毫秒级时间内完成。从系统资源占用的角度来看,Java程序必须运行在虚拟机之上,虚拟机运行所必需的资源即是应用程序运行时占用资源的下限,一个简单的Spring Web应用即使在没有流量的情况下也会达到百兆级别的内存占用。

J ava程序启动耗时,图片来源:周志明-云原生时代的Java

从上图可以看出:应用程序在启动过程中,类加载和JIT编译消耗了比较多的时间,并且在容器环境中,每个Java应用程序启动时都需要先启动Docker容器,然后在Docker内启动JVM,最后JVM再加载应用,整个过程的耗时将进一步增加。

在当前炙手可热的Serverless领域,Java应用的一些特性似乎都跟Serverless的设计理念背道而驰,比如:Java本身适合大规模长时间运行的应用,而Serverless要求应用程序尽量快速的运行完,AWS的Lambda的最长运行时间仅为15min;Java在启动时执行的一系列操作导致启动耗时较长,而Serverless按需极速扩容的特点却要求应用必须在尽量短的时间内启动。在Servlerless领域,“冷启动”一直是个“火热”的话题,如何保证函数的第一个请求能在尽量短的时间内完成计算并返回结果一直是大家反复探讨的话题,这个过程中涉及到准备Pod和镜像、打通网络、启动容器及应用,运行函数等多个步骤,如果应用本身的启动时间过长,那么无疑会增加“冷启动”耗时,甚至会成为“冷启动”优化的瓶颈。

02 Quarkus入局

面对危机和挑战,Oracle官方提出了很多“面向未来的变革”项目以保持Java未来的活力与竞争力,包括:Leyden、Valhalla、Loom、Portola等,此处只介绍相关名词,感兴趣的读者可以自行查阅相关资料。除此之外,社区和开发者也都在它们在各自的领域给出了一些优秀的解决方案,比如Quarkus—云原生时代的Java框架。

(1)Quarkus简介

Quarkus是由Red Hat于2018年开始研发的一款面向云原生的开源Java框架, 旨在使 Java 成为 Kubernetes 和无服务环境中的领先平台 ,目前Star数已接近1W,累计发布了168个版本,有超过620位开发者贡献了代码,最新版本为V2.8.1。主要特点是:

1) 云原生 :支持通过GraalVM native-image将Java应用打包成 可执行的本地二进制镜像,减少内存使用、缩短应用启动时间

2) 低使用成本 :遵循已有的标准,兼容常用的框架,如:Spring、Hibernate、Netty、RestEasy等,无需学习新的标准和规范

3) 高开发效率 :支持代码热更新,无需重启即可查看代码改动后的运行结果(dev环境下)

4)同时支持命令式和响应式代码

5)支持同时运行在GraalVM和HotSpot两种虚拟机上

Quarkus运行时内存、启动时间对比,图片来源:Quarkus官网

(2)Quarkus基本原理

Quarkus是基于GraalVM进行设计和开发的,因此只要我们理解了GraalVM的基本原理,对Quarkus的工作原理的理解也就水到渠成了。

GraalVM是Oracle发布的 通用型虚拟机,可以用来运行Java程序,被称为下一代Java虚拟机 ,于2016年6月发布第一个release版本。主要特点有:

1) 高性能 :GraalVM 的高性能AOT(Ahead Of Time,运行前编译)编译器支持在构建阶段生成可直接运行的本地代码,得益于一系列高级的编译器优化和积极的内联技术,使得生成的本地代码运行速度更快,产生的垃圾对象和占用的 CPU均更少,可极大降低云和基础设施的成本。同时,由于没有使用JIT运行时优化,程序在启动时即可达到峰值性能,不需要预热时间。

AOT编译过程 ,图片来源自网络

从上图可以看出,AOT编译主要分为静态分析和提前编译两个阶段。其中,静态分析阶段主要是利用代码的可达性分析将运行期间不会用到的类排除在打包之外,以此来减少打包后的代码体积;提前编译阶段主要是将程序代码和运行时所需的环境打包成本地二进制文件并执行初始化代码以及将结果保存为堆镜像,程序在真正运行时直接基于堆镜像启动,以减少程序启动耗时。

2) 快速启动、减少内存使用 :GraalVM 0.20版本开始出现的一个极小型(相比于HotSpot)的运行时环境Substrate VM,其具有如下特点:1. 完全脱离了HotSpot虚拟机,拥有独立的运行时,包含异常处理、同步、线程管理、内存管理(垃圾回收)和JNI等组件;2. 在AOT编译时保存初始化好的堆内存快照,并支持以此为入口直接开始运行,避免重复运行初始化代码,以缩短启动时间。

内存占用对比 图片源自GraalVM官网

从上图可知,在利用GraalVM将Java应用打包成Native Image之后,运行时占用的内存约为在传统HotSpot上的五分之一左右。

说明:图中的Helidon、

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值