![211ffbafdeb35ec1b0ee9623a76ed158.png](https://i-blog.csdnimg.cn/blog_migrate/90477ff28cd9d91ecc4a6af32c2d0923.jpeg)
既然要实现低资源占用的”皮皮调度“,那么面临的第一个选择是:可以编译为原生应用的Java应用框架。这里,我选择Quarkus。
Quarkus简介
前文中介绍了Java的新希望:GraalVM。
本文介绍一下基于GraalVM所带来的新应用框架:Quarkus。
正是:
- 由于有了GraalVM,以及其编译Java为原生程序的能力,才有了Quarkus
- 由于云原生(Kubernetes生态)的蓬勃发展,也促进了GraalVM和Quarkus的繁荣
Quarkus是一个比较新的Java应用框架,其主页: https://quarkus.io/, 起源于红帽公司(Redhat)。
它有几个特点:
- 容器优先(Container First),通过利用GraalVM编译Java为原生程序,使得Quarkus应用可以快速的启动(几十毫秒内),这样可以适应微服务和Serverless场景
- 低内存使用,传统的Java应用框架(比如Spring Boot)的应用,可能启动后就至少要占去100M以上的内存,而Quarkus的则可以小于10M
- 经过原生编译,可以使得生成的应用运行时不再依赖于JVM,大大减少了生成的docker image大小
另外,其设计理念是:更多的使用现有成熟的底层框架,而不是再自行写一堆新框架或发明一堆新的DSL,使得开发者的上手门槛大大降低:
- 融合了Eclipse MicroProfile, JPA/Hibernate, JAX-RS/RESTEasy, Eclipse Vert.x, Netty, Apache Camel 等,方便开发者仍然使用之前熟悉的框架来开发新的应用。 (快速上手)
- 正是基于这些成熟的底层框架,使得Quarkus虽然是一个相对新的应用框架,但是其质量已经足可以用于生产环境
Quarkus的功能
Quarkus的文档相对Spring Boot来说还是比较少的,可以从 https://quarkus.io/guides/ 来作为起点看一下各个功能的初步文档。
比如一些常见的功能:
- REST服务: https://quarkus.io/guides/rest-json
- REST客户端: https://quarkus.io/guides/rest-client
- ORM: https://quarkus.io/guides/hibernate-orm-panache 《Simplified Hibernate ORM with Panache》
- 事务(Transaction)管理: https://quarkus.io/guides/transaction 《Using Transactions》
- 登陆和授权管理: https://quarkus.io/guides/security-keycloak-authorization 《Using OpenID Connect and Keycloak to Centralize Authorizations》
- 分布式追踪: https://quarkus.io/guides/opentracing 《Using OpenTracing》
- 定时调度:https://quarkus.io/guides/quartz 《SCHEDULING PERIODIC TASKS WITH QUARTZ》
具体的功能这里就不再一一列举,感兴趣的朋友可自行查阅相关文档。
Quarkus的亮点
Quarkus的最大亮点是把GraalVM的先进理念(尤其是原生编译)和现有成熟框架(比如: RESTEasy, Vert.x等)进行了深度融合。
不过也有不少细节亮点,这里我简单的拿Spring Boot来和它相比较。
开发时,内置自动热加载(Live Reload)
Quarkus自带热加载功能,当开发时,只要执行
mvn quarkus:dev
进入开发模式启动,就可以修改代码的同时,框架自动热加载,实时看到修改的结果。而不用再每次修改后重新打包运行。
另外,这个自带的插件还可以实现远程热加载,也就是在远程服务器上启动该程序,然后开发人员本地修改代码,服务器上的程序马上相应更新(通过web socket),这样,即使是某些程序只能在服务器上运行(比如:针对微信或飞书等的一些绑定了服务器IP地址的应用),也能有非常好的开发体验。
Spring Boot通过一些插件应该也能实现类似的功能, 但是Quarkus框架自带了这个功能, 使得其更易用和稳定。
对于配置文件的配置项修改
随着应用程序的复杂度增大,其配置文件中的配置项往往是非常多的, 比如:
spark {
master = "local[4]"
webUrlPort = 8080
jobserver {
port = 8090
bind-address = "0.0.0.0"
sqldao {
slick-driver = slick.driver.H2Driver
jdbc-driver = org.h2.Driver
rootdir = /tmp/spark-jobserver/sqldao/data
jdbc {
url = "jdbc:h2:file:/tmp/spark-jobserver/sqldao/data/h2-db"
user = ""
password = ""
}
dbcp {
enabled = false
maxactive = 20
maxidle = 10
initialsize = 10
}
}
}
}
对于Spring系,不同的环境的配置文件的思路是:每套环境有自己的配置文件,比如有 dev环境的,prod环境的。当部署后,每个环境读取自己环境的配置文件。
不过随着kubernetes和云原生的发展,Quarkus是另一种思路,就是基础镜像中包含了所有的配置项,每个环境只通过 property 或者环境变量来重载不同的配置项。
比如我要替换 spark.jobserver.sqldao.jdbc.url
, 那我只需要在启动的时候,传入:
myprogram -Dspark.jobserver.sqldao.jdbc.url=jdbc:mysql://127.0.0.1:3306/jobserver
而对于Spring的配置,动态重载少数几个参数则会稍微麻烦一些。
挑战
Quarkus虽然理念很好,但毕竟比Spring年轻不少,所以,肯定有不少不完善的地方。
尤其是虽然”编译为原生程序“很具有吸引力,但是实际使用中,要是使用的类库都自带在Quarkus中还好,要是Quarkus仍然不支持,那就需要开发者自行去移植,难度还是比较高的(使用-H:JNIConfigurationFiles, -H:ReflectionConfigurationFiles 等配置文件,或编写Quarkus Extension)。而且当编译成原生程序后,很多JVM排查问题的工具则不再适用,比如 jvisualvm, jmap等,对于问题的排查也会变得更复杂。
总之,没有绝对好的应用框架,而是只有适合自己场景的框架,当明白了自己需要什么后,就自然知道哪些是重要的,哪些是可以绕过的。