在当前的开发社区中,微服务和云原生是两个炙手可热的话题。微服务是一种软件架构体系风格。微服务的特征是把应用拆分成若干个独立部署的单元,从而降低单个服务的实现复杂度。服务通过相互之间的交互来完成复杂的业务流程。由于每个服务可以独立地进行扩展,这就有效地解决了应用面对海量请求时的扩展问题。

 

下图给出了微服务架构的应用的扩展模式。每个微服务都是独立的扩展单元。


云原生时代,为什么要学习Quarkus?_微服务



1

微服务架构和云原生



微服务架构也带来了新的问题。应用自身的复杂度并没有消失,而是以新的形式来出现。把应用划分成多个服务之后,单个服务的开发复杂度降低了,而复杂度则被转移到了服务之间的交互上。使用微服务架构之后,应用变成了一个分布式系统。

 

下图是亚马逊的CTO Werner Vogels给出的亚马逊网站的微服务之间的依赖关系。从中可以看出来微服务架构的复杂性。


云原生时代,为什么要学习Quarkus?_微服务_02


相较于Spring Cloud,基于Kubernetes的云原生(Cloud Native)技术是实现微服务架构的一个更好的选择。云原生微服务架构是云原生技术和微服务架构的结合。微服务作为一个架构风格,所解决的问题是复杂软件系统的架构与设计。云原生技术作为一种实现方式,所解决的问题是复杂软件系统的运行和维护。这两者所要解决的问题是相辅相成的。微服务架构可以选择不同的实现方式,如Spring Cloud或私有实现,并不一定非要使用云原生技术。同样地,云原生技术可以用来实现不同架构的应用,包括微服务架构的应用或是单体应用。

 

云原生技术和微服务架构确实是非常适合的组合。这其中的原因在于,云原生技术可以有效的解决微服务架构所带来的实现上的复杂度。微服务架构难以落地的一个重要原因是它过于复杂,对开发团队的组织管理方式、技术水平和运维能力都提出了极高的要求。因此,一直以来只有少数技术实力雄厚的大企业会采用微服务架构。云原生技术可以弥补微服务架构的这一个短板,极大的降低微服务架构实现的复杂度,使得广大的中小企业有能力在实践中应用微服务架构。云原生技术促进了微服务架构的推广,也是微服务架构在实际项目中落地的最佳搭配。

 

对于云原生应用来说,不管是微服务架构中的单个服务,或者是独立运行的应用,本质上与一般的应用并没有太大的区别。但是由于云平台的特殊性,云原生应用的侧重点有所不同。

 

● 对于云原生应用来说,平台无关性变得无关紧要。云原生应用都是以容器化的形式运行的,所运行的底层平台是固定的。

●  云原生应用对启动速度的要求比较高。当需要进行水平扩展时,要求这些新的实例必须在足够短的时间内完成启动,从而尽快的处理新增的请求。

●  云原生应用要求在运行时占用尽可能少的资源。尽可能的减少单个实例占用的资源,就意味着可以用同样的成本,支持更多的访问请求。

●  云原生应用要求更小的打包体积。云原生应用以容器镜像的形式打包。应用镜像的尺寸越大,所需要的存储空间也会越大,推送和拉取镜像所耗费的时间也会更长。

 

综合上述要求,可以分析出一个结论,那就是以JVM模式运行的Java应用,并不太适合于云原生应用的开发。Java应用的启动时间通常会比较长。Java应用运行需要JVM的支持。JVM自身在运行时就需要占用一定的资源,而且也会占用容器镜像的体积。



2


GraalVM的重要作用



为了弥补Java在云原生应用开发时的这个劣势,就需要用到GraalVM。GraalVM是Oracle开发的高性能的多语言运行时。除了Java和其他JVM语言(如Kotlin、Groovy和Scala等)之外,GraalVM还提供了对JavaScript、Python、Ruby、R、C/C++和Rust等的支持。下图是GraalVM的架构图。


云原生时代,为什么要学习Quarkus?_微服务_03


(图片来源:GraalVM官方网站)


GraalVM的另外一个重要功能是创建原生可执行文件。Java源代码被编译成平台无关的字节代码,再由虚拟机在不同的平台上运行。虚拟机屏蔽了底层平台的差异性。Java的这个特点简化了Java应用的部署和运维,但是也不可避免地影响了Java应用的性能。

 

在运行Java应用时需要Java虚拟机的支持。即便是最简单的输出“Hello World”的Java应用也需要一个完整的Java虚拟机才能运行。在部署Java应用时,必须首先确保目标环境提供了兼容的Java虚拟机。当以容器镜像来部署时,虚拟机本身会占据镜像的大部分空间。应用自身的JAR文件可能只有几十MB,而虚拟机自身的文件在解压之后有数百MB。这就意味着大量的存储空间被消耗在应用无关的地方。

 

GraalVM提供的原生镜像(native image)功能可以把Java代码预先编译(Ahead-Of-Time,AOT)成独立的可执行文件。该可执行文件包括了应用本身的代码、所依赖的第三方库和 JDK 本身。该执行文件并不运行在Java虚拟机之上,而是名为Substrate的虚拟机。与运行在传统的Java虚拟机上相比,原生可执行文件在运行时的启动速度更快,所耗费的内存资源更少。可执行文件的体积也更小。

 

GraalVM生成的原生可执行文件与底层平台相关,不能在当前平台之外的其他平台上运行。对云原生应用来说,这并不是一个问题。云原生应用的设计目标是在容器中运行,所运行的底层平台是固定的。


3

Quarkus的优势



提到Java应用开发,就不得不提到Spring框架。Spring框架是目前大部分Java应用开发时会使用到的框架。作为一个通用的框架,Spring和Spring Boot也经常用在云原生微服务应用的开发中。在使用Spring开发微服务时的一个突出问题是它过于复杂。这主要是因为Spring框架有很长的历史,所包含的内容非常多。这些限制使得Spring开发云原生应用的性能不是很理想。

 

与Spring不同的是,Quarkus从一开始就是针对Kubernetes设计的云原生应用开发框架。这使得Quarkus可以针对Kubernetes进行优化。

 

Quarkus的设计哲学是容器优先,对在容器中运行进行了针对性的优化。在容器中运行时,Quarkus应用的启动速度非常快,运行时所消耗的资源也更少。Quarkus框架的内核很小,大部分工作都由不同的扩展来完成。应用可以根据需要来选择要启用的扩展。这就保证了Quarkus应用所包含的第三方依赖尽可能的少。

 

Quarkus使用多种方式来提升Java微服务的性能。Quarkus在构建时会进行尽可能多的处理,提升应用的启动速度。构建之后的应用中只包含在运行时真正需要的类,减少了应用的尺寸。Quarkus也尽可能地减少反射的使用。在创建原生可执行文件时,Quarkus会在构建阶段进行预启动,并把部分代码的运行结果直接记录在可执行文件中。当应用运行时,框架的启动代码已经被执行过了,可以进一步提升启动速度。

 

一般的应用在启动时需要进行很多初始化的工作。这些操作都会耗费一定的时间,越复杂的应用所需要的时间越长。只有完成这些初始化工作之后,应用才能执行自身的业务逻辑。

 

在应用运行时,有些代码只会在启动时运行一次,仅作为应用初始化的辅助。典型的例子是XML类型的配置文件的解析。解析XML文件需要相应的第三方库的支持,而解析操作只在启动时执行一次。在完成解析之后,XML相关的库就不再需要,但是会一直存在于运行的应用中。这会造成不必要的内存浪费。

 

Quarkus应用的构建和启动一共分成三个阶段,分别是增强、静态初始化和运行时初始化。


1)在增强阶段,Quarkus的扩展会加载并扫描应用的字节代码和配置。这些扩展会根据收集到的应用的元数据来进行预先的处理。处理的结果会直接记录在字节代码中,作为应用的一部分。比如,Hibernate会对添加了注解@Entity的实体类进行处理来改写其字节代码。Quarkus的Hibernate扩展在增强阶段就完成了对实体类的处理,在运行时可以直接使用。

2)静态初始化阶段负责执行一些额外的动作。这个阶段主要是针对原生可执行程序的构建。在构建原生可执行程序时,静态初始化的代码会在一个正常的JVM中运行,所产生的对象会被直接序列化到可执行文件中。

3)运行时初始化阶段的代码在应用的主方法中运行。


增强阶段所需的依赖并不需要出现在应用运行时。以前面提到的读取XML配置文件为例,当Quarkus扩展读取配置文件并解析之后,所生成的字节代码被记录在应用中。XML解析相关的库不会出现在应用中。

 

Quarkus的扩展由两个模块组成,分别是运行时模块和部署模块。运行时模块提供了Quarkus应用在运行时使用的API,作为应用的依赖;部署模块在Quarkus应用构建时进行处理,并不是应用的依赖,而是由Quarkus在构建时自动添加。这两种模块的划分,可以更好地区分构建和运行时所需的依赖。

 

通过一个简单的数字对比可以看出Quarkus对应用的性能提升。下图是Quarkus官方网站上给出的性能对比图。从图中可以看出,使用Quarkus和 GraalVM的简单的REST应用的启动时间仅为16毫秒,占用内存仅12MB。如果使用传统的基于Java虚拟机实现,应用的启动时间需要4.3秒,占用内存为136MB


云原生时代,为什么要学习Quarkus?_java应用_04

(图片来源:Quarkus官方网站)


4

如何学习Quarkus



Quarkus学习起来并不困难。Quarkus基于Eclipse提出的MicroProfile规范。MicroProfile的目标是提供一套通用的API和功能集来满足微服务开发的需求。从作用上来说,MicroProfile与Spring Cloud存在一定的相似性,不过MicroProfile只关注在规范和API层次,并不关心具体的实现。MicroProfile也会用到Jakarta EE相关的规范,侧重在企业级Java应用的开发。

 

Quarkus中使用的第三方框架包括Eclipse Vert.x、RESTEasy、JPA、Hibernate、MicroProfile规范及其实现库和SmallRyeMessaging等。

 

学习Quarkus最好的做法是通过一个完整的实战案例的开发,来贯通整个云原生微服务应用的开发全过程。


小编为大家推荐一本融合了云原生领域资深专家14年一线工作经验,以一个完整的实战应用的开发过程作为主线,介绍如何以Quarkus为框架来开发微服务架构的云原生应用的实用图书。



云原生时代,为什么要学习Quarkus?_原生应用_05 Qarkus云原生微服务开发实战




作者:成富

ISBN:978-7-111-68955-3


以一个完整的实战应用的开发过程作为主线,介绍如何以Quarkus为框架来开发微服务架构的云原生应用。书中介绍了微服务和云原生开发的各个方面,包括微服务的开发和测试以及在Kubernetes上的部署运行,还包括应用的可观察性、安全和服务调用的健壮性等非功能性需求。通过本书的介绍,读者可以了解一个真实的云原生应用的开发过程,并学会如何从头开始开发个人的应用。



本书采用双色印刷,突出重点核心内容,并配有二维码视频,扫码即可观看,使读者身临其境,迅速、深入地掌握各种经验和技巧。