Quarkus -- A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards.
该框架定义为Kubernetes原生框架,可以很好的解决Serverless架构下资源占用大、冷启动慢等问题,实际效果还是挺惊艳的。这一篇开始学习Quarkus框架,本篇内容如下:
- 介绍基本概念
- 学习写简单的RESTful项目
- 学习构建可执行文件以及构建Docker镜像
Quarkus介绍
什么是Quarkus?
官方对Quarkus的介绍是A Kubernetes Native Java stack tailored for OpenJDK HotSpot and GraalVM, crafted from the best of breed Java libraries and standards.
所以我们可以管窥它的特点:
- Kubernetes原生,即对容器化技术友好
- 底层虚拟机可以使用HotSpot或者GraalVM
- 集成了现存的很多优秀的Java库和标准
为什么要用Quarkus?
根据2020年NewRelic调查,在云服务领域,Java只占了6%的使用,具体如图:(图片来源:A guide to Java serverless functions | Opensource.com)
那么造成这个的原因是什么?很难在如Kubernetes的容器平台中优化Java的应用程序,我们可以使用NodeJs、Go语言进行一个对比,看看同样资源下支持的应用程序数目:
由于需要给每一个JVM堆分配内存,导致了Java应用程序较高的内存开销,相比与其他语言,尤其是内存开极小的GO,那基本上没得看,所以Go在云服务领域很流行。
为什么不继续用Spring?
上一节的原因导致了直接上Spring不是很合适,虽然,Spring Function支持使用java.util.function包来编写反应式函数,Spring也支持你把应用程序部署到Serverless平台上去,比如Kubeless、Apache OpenWhisk、Fission、Project Riff等。但是却也造成了包括上一节的问题:
- 较大的内存开销
- 冷启动慢
- 响应时间缓慢
上述的问题如果放到不是Serverless的平台上,比如Kubernetes上,只会更严重。而对于Quarkus框架,官方宣称的开销如下:
可以看到不管是搭配HotSpot或者GraalVM,这个开销都要小得多得多。尤其是搭配GraalVM,它和HotSpot一样,属于JVM的一种,典型的GraalVM就是graalvm/graalvm-ce-builds,或者graalvm/mandrel (github.com)。
常用注解以及RESTful程序编写
生成项目
官方项目生成网页
类似start.spring.io一样,Quarkus官方也有类似的网页,地址:Quarkus - Start coding with code.quarkus.io
比如在RESTful项目中,最基本需要两个依赖库:
直接下载到本地就可以使用了。
IDEA生成项目
在Ultimate版本中继承了Jetbrains闭源的插件,直接从这里进去就可以了,和Spring那个一样一样的。
quarkus中最基本的rest服务需要JAX-RS这个组件,关于json的插件你可以用自己喜欢的,比如Jackson或者JSON-B,这里用Jackson。
安利一个工具:Quarkus-cli
在官方的教程里,每次新建一个项目都需要敲很多的参数,个人觉得有点麻烦,好比这样的:
1 | mvn io.quarkus:quarkus-maven-plugin:2.1.3.Final:create \ |
实际上在官方的页面里有推荐这么一个官方的小工具,可以帮助你新建一个项目,其实和Go语言里的Beego
中的bee
工具作用差不多:
只不过这玩意儿貌似还在改进中,但是实测可以用。安装方法如下:
1 | # 先安装JBang,这个小玩意儿还挺有意思的,可以看看:https://www.jbang.dev/ |
安装后就可以正常用了:
默认的create不带子命令就是在创建应用,Quarkus-cli创建项目时候有一个非常Nice的参数:--dry-run,对没错就是k8s那个dry-run,你可以预览并检查生成的选项而不是直接生成项目。好比这样:
我只能说好用的一批。好比我们创建一个rest-demo项目:
1 | quarkus create cn.edu.xidian:quarkus-rest-demo -P 2.1.3.Final |
项目结构如下,可以对比Spring发现多了docker的文件夹,其他没啥区别。
编写结束后如果要启动项目只需要在项目文件夹下执行quarkus dev
就可以了,也不需要mvn compile quarkus:dev
了,这个工具还是很方便的。
常用注解
下面小结一下在Quarkus框架中常用的注解,这里主要是编写Restful服务常用的。Quarkus的ioc和rest规范都是跟从的官方,即:
- ioc使用的是JSR 299和JSR 330
- rest使用的是JAX-RS
所以其实很多注解都是从上面这些依赖中了来的。下表是我自己总结的常用的Quarkus中的注解,后续我会继续添加这个表
注解名称 | 注解含义 |
---|---|
Rest类: javax.wx.rs包 | |
@Path | 指明web的请求路径,比如@Path('/book/{name}'),类似Spring的@RequestMapping |
@PathParameter | 配合@Path注解获取GET参数,比如上面那个的获取方法:public void func (@PathParameter('name') String name) {} |
@Produces | 指明这个类所有函数/单个函数返回的参数类型,比如REST项目@Produces(MediaType.APPLICATION_JSON) |
@Consumes | 指明这个函数所有函数/单个函数接收的参数类型,比如REST项目@Consumes(MediaType.APPLICATION_JSON) |
@GET | 声明GET方法,类似Spring的@GetMapping |
@POST | 声明POST方法,类似Spring的@PostMapping |
@DELETE | 声明DELETE方法 |
@PUT | 声明PUT方法 |
Bean相关类 | |
@Injection | 声明一个可以被注入的类、方法、变量,类似@Autowired |
@Singleton | 同@Inject,但是同时他也是个单例,类似Spring的@Component |
@ApplicationScoped | 声明一个全局变量的bean |
配置类 | |
@ConfigProperty | 从配置文件(application.properties)中读取变量,比如@ConfigProperty(name="vartest", default="test"),即从配置文件中读取'vartest'变量的值,没有的话就是用default值 |
一个RESTful程序示例
下面写一个简单的图书restful服务。
Spring中我们将业务控制器分开,xxxController这种,Quarkus中喜欢把这个叫Resource,
我们先定义一个实体Book,这里注意,我们将使用Jackson来对对象进行序列化处理,所以一定要设置Getter,不然会获取不到属性,你也可以用@JsonIgnore
注解来屏蔽一些属性。
1 | import java.util.Objects; |
然后我们定义对应的Resource,可以看到所有与RESTful相关的注解,都来自javax.ws.rx包,都是JAX-RS规范。
1 | import javax.ws.rs.Path; |
代码编写后,我们quarkus dev
让他运行:
然后就可以请求服务了:
构建可执行文件
接下来的两小节包括构建可执行文件和Docker镜像,这里不推荐使用那个quarkus-cli,它不支持打包到docker,建议用mvn命令。
这里我是在Linux下构建的可执行文件,windows下我会报只能使用AMD平台的错误,而且即使是在x64 Native Tools Command Prompt for VS 2019
下不能解决。
构建直接使用命令mvn package -Pnative
。
我虽然是在虚拟机里构建的,但是这个速度也有点慢了吧。。构建完成后会生成一个xx-runner的文件:
然后我们直接./xxx-runner
启动就可以了,我这里用的是官方基于Oracle
GraavlVM定制的一个下游版本,叫Mandrel,这时候你就发现牛逼的地方了:
好家伙,22ms就起来了,我直呼
当然运行结果是一样的。
构建Docker镜像
这里只介绍最简单的办法,前面我们已经通过mvn package -Pnative
命令完成构建了,此时在你的src/main/docker
目录里可以看到一个Dockerfile.native,内容如下,这个不需要你写。
1 | #### |
然后我们按照说明去Docker中构建镜像:
docker build -f src/main/docker/Dockerfile.native -t quarkus/quarkus-rest-demo .
到这里镜像就构建好了,就可以投入使用了:
参考学习
- A guide to Java serverless functions | Opensource.com
- Quarkus - Building Quarkus apps with Quarkus Command Line Interface (CLI)
- Releases · graalvm/mandrel (github.com)
- Quarkus - Writing JSON REST Services
- Quarkus - Building a Native Executable
- Quarkus - Container Images