Quarkus是专为OpenJDK HotSpot(或zSeries上的OpenJ9)和GraalVM量身定制的Java堆栈,它是从优化的Java库和标准中精制而成的。对于构建高度可扩展的应用程序,同时使用比其他Java框架更少的CPU和内存资源,它是一个不错的选择。这些应用程序可以是传统的Web应用程序,无服务器应用程序,甚至可以充当服务。
有许多记录在案的组织将其应用程序迁移到Quarkus的实例。在本文中,让我们看一下从Spring Boot到Quarkus的这种迁移路径,这既是魔术又是疯狂!魔术将是挥舞双手并执行迁移而无需更改一行代码。疯狂将试图弄清楚它是如何完成的。
应用程序
该应用程序是一个简单的“待办事项”任务管理系统。用户可以输入待办事项,然后在完成后将其选中。这些项目存储在PostgreSQL数据库中。您可以在此处找到所有应用程序的源代码。有一个版本使用Gradle而不是Maven作为gradle分支上的构建工具。
启动数据库
该应用程序需要一个PostgreSQL数据库,所以我们要做的第一件事是使用Docker或Podman在本地启动实例:
docker run --ulimit memlock=-1:-1 -it --rm=true --memory-swappiness=0 --name tododb -e POSTGRES_USER=todo -e POSTGRES_PASSWORD=todo -e POSTGRES_DB=tododb -p 5432:5432 postgres:11.5
端口5432上的PostgreSQL 11.5实例现在应该正在运行。应该创建tododb用户todo可以使用密码访问的模式todo。
运行应用程序
发出命令运行应用程序./mvnw clean spring-boot:run。如果要使用Gradle而不是Maven,请首先切换到gradle分支(git checkout gradle),然后运行命令./gradlew clean bootRun。
./mvnw clean spring-boot:run
./gradlew clean bootRun
您应该看到标准的Spring Boot标语:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.4.1) INFO 68107 --- [ restartedMain] i.q.todospringquarkus.TodoApplication : Started TodoApplication in 4.074 seconds (JVM running for 4.645)
注意启动时间。我们将再讨论一下。
应用程序运行后,在您喜欢的浏览器中导航到http:// localhost:8080。您应该看到如图1所示的主应用程序屏幕。
http:// localhost:8080
“我的第一个待办事项”标记为已完成的Spring Todos应用程序。
试一下该应用程序。在文本框中输入新的待办事项,然后按Enter。该待办事项将显示在列表中,如图2所示。
带有新待办事项的Spring Todos已添加到列表中。
X
OpenAPI
Swagger UI
检查内部
该应用程序是具有以下功能的全功能Spring Boot应用程序:
src/main/java/io/quarkus/todospringquarkus/TodoController.java
src/main/java/io/quarkus/todospringquarkus/TodoEntity.java
src/main/java/io/quarkus/todospringquarkus/TodoRepository.java
Spring Boot
SpringDoc OpenAPI 3
Prometheus
src/main/resources/META-INF/resources
Configuration
打开src/main/resources/application.properties以找到应用程序配置:
src/main/resources/application.properties
spring.jpa.hibernate.ddl-auto=create-drop spring.datasource.url=jdbc:postgresql://localhost:5432/tododb spring.datasource.username=todo spring.datasource.password=todo springdoc.api-docs.path=/openapi springdoc.swagger-ui.path=/swagger-ui management.endpoints.web.exposure.include=prometheus,health
打开src/main/resources/import.sql以查找一些SQL,这些SQL将使用初始数据集预填充数据库表:
INSERT INTO todo(id, title, completed) VALUES (0, 'My first todo', 'true');
而已!对于功能齐全的应用程序,这里没有太多的代码,比“ Hello World!”要多得多。
The Magic
选择了此迁移的一个硬性要求:不能以任何方式修改应用程序的源代码。
您准备好魔术了吗?返回命令行并运行命令./.mvnw clean spring-boot:run。如果要使用Gradle而不是Maven,请首先切换到gradle分支(git checkout gradle),然后运行命令./.gradlew clean bootRun。
./.mvnw clean spring-boot:run
Gradle
Maven
(git checkout gradle)
./.gradlew clean bootRun
您会注意到的第一件事是Quarkus标语和启动消息,而不是Spring Boot:
__ ____ __ _____ ___ __ ____ ______ --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \ --\___\_\____/_/ |_/_/|_/_/|_|\____/___/ INFO [io.quarkus] (Quarkus Main Thread) todo-spring-quarkus 1.0.0-SNAPSHOT on JVM (powered by Quarkus 1.10.5.Final) started in 2.743s. Listening on: http://localhost:8080 INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated. INFO [io.quarkus] (Quarkus Main Thread) Installed features: [agroal, cdi, hibernate-orm, hibernate-orm-panache, jdbc-postgresql, kubernetes, micrometer, mutiny, narayana-jta, resteasy, resteasy-jackson, smallrye-context-propagation, smallrye-health, smallrye-openapi, spring-boot-properties, spring-data-jpa, spring-di, spring-web, swagger-ui]
等等,发生了什么事?该应用程序现在是Quarkus应用程序,不再是Spring Boot应用程序?太疯狂了!
要证明吗?返回浏览器窗口(如果您将其关闭,请访问http:// localhost:8080)并重新加载页面。相同的用户界面在那里,并且功能齐全。单击页面底部的所有各种链接。它们都像以前一样完全起作用。
另外,请注意启动时间。给定完全相同的代码库(在所示示例中,Spring为4.074s,而Quarkus为2.743s),Quarkus版本的启动时间几乎减少了一半。那就是超音速,亚原子,Java!
什么都没有改变,那么这一切是怎么发生的呢?一个好的魔术师不会透露他或她的秘密!
The Madness
所有优秀的魔术师用 sleight-of-hand表演一招时,分散他的或她的听众。这篇文章中还没有显示的一些东西是肉眼看不见的。您有发现可疑之处吗?让我们仔细看看该技巧是如何完成的。
sleight-of-hand
Execution
仔细查看用于运行应用程序的命令:使用Maven:
使用Gradle:
注意到有什么区别吗?在Quarkus版本中使用了另一个可执行文件(.mvnw/ .gradlew)。如果打开这些文件并仔细检查它们,您会发现一些棘手的事情:
.mvnw
#!/bin/sh ./mvnw clean quarkus:dev -Pquarkus
.gradlew
#!/bin/sh 2 ./gradlew -Pprofile=quarkus $@
我们使用了一些技巧来掩盖用于启动应用程序的实际命令。稍后更多关于Gradle和Maven配置文件的信息。
配置
您是说Quarkus知道如何阅读和理解其中的Spring Boot配置src/main/resources/application.properties吗?好吧,不。记住,这是一个魔术。魔术师从不说完整的事实。上面的示例中未显示的是特定于Quarkus的配置。它被隐藏在文件的更下方。
如果您重新打开src/main/resources/application.properties并一直滚动到底部(在第58行附近),则会看到一些其他配置:
quarkus.datasource.db-kind=postgresql quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/tododb quarkus.datasource.username=todo quarkus.datasource.password=todo quarkus.datasource.metrics.enabled=true quarkus.hibernate-orm.database.generation=drop-and-create quarkus.hibernate-orm.sql-load-script=import.sql quarkus.micrometer.export.prometheus.path=/actuator/prometheus quarkus.smallrye-health.root-path=/actuator/health
此配置类似于文件顶部的Spring Boot配置。但是,它所做的一件事是为Prometheus和运行状况探针端点重新定义路径,以便它们与Spring Boot执行器端点的路径匹配。这使屏幕底部的Prometheus度量标准和运行状况检查链接可以正常工作,而无需更改用户界面。
依存关系
可以想象,有许多依赖项需要更改,添加或更新。
简单地将一些Spring Boot依赖项交换为Quarkus依赖项将有很长的路要走。还有其他一些功能,例如Prometheus指标,OpenAPI文档,Swagger UI集成以及需要添加其他依赖项的运行状况检查。
现在您可能在想自己,“但是我什么都没做。我所做的只是运行Maven或Gradle命令,并且整个应用程序都以Quarkus应用程序而不是Spring Boot应用程序的身份运行。怎么可能?”
构建设置
构建文件是所有魔术发生的地方。但是,您使用的构建工具确定了依赖性解析魔术的实际发生方式。
在main分支上,打开pom.xml文件。你会立刻被构建文件分成多个Maven的配置文件,spring以及quarkus与spring轮廓是默认的配置文件。这些配置文件定义了在您运行./mvnw clean spring-boot:run或时./mvnw -Pquarkus clean quarkus:dev(其中使用上述.mvnw脚本中的某些重定向伪装而成)包含的依赖项和构建插件。
另一方面,Gradle没有配置文件的概念。您会在项目分支中注意到一些.gradle文件gradle:
build-common.gradle
包含适用于两个版本的应用程序的任何通用构建逻辑,包括设置所生成工件的groupId / version以及工件存储库定义。
build-spring.gradle
包含特定于该应用程序的Spring版本的所有构建逻辑,插件和依赖项。
build-quarkus.gradle
包含特定于Quarkus版本的应用程序的所有构建逻辑,插件和依赖项。build-quarkus.gradle甚至介绍了Spring Boot的bootRun任务,quarkusDev并通过Quarkus Gradle插件将其重新映射到任务。
settings.gradle
魔术真正发生的地方!该settings.gradle文件查找名为的Gradle项目属性profile: 如果找不到此属性,则默认值为spring。 然后,它将项目的构建文件build-spring.gradle或设置build-quarkus.gradle为要使用的主要构建文件。 通常,如果您需要Gradle模拟Maven配置文件的功能,那么这是一个非常好的模式。
应用主类
在本文开头提到,我们希望执行迁移而无需更改任何代码。每个Spring Boot应用程序都需要有一个“应用程序”类,其中包含一个main方法,并带有注释@SpringBootApplication。在我们的项目中,src/main/java/io/quarkus/todospringquarkus/TodoApplication.java是该类。
@SpringBootApplication
src/main/java/io/quarkus/todospringquarkus/TodoApplication.java
Quarkus不需要这样的类,任何Quarkus Spring兼容性扩展都@SpringBootApplication不会为注释或SpringApplication此类中引用的类提供解析。
那么,有什么用呢?我们没有进行任何代码更改,但是这些类在Quarkus中似乎可以很好地解决。
您会在pom.xml(对于Maven)/ build-quarkus.gradle(对于Gradle)中都注意到一个特殊的注释,就在依赖项的依赖项声明的正上方org.springframework.boot:spring-boot-autoconfigure:
pom.xml
org.springframework.boot:spring-boot-autoconfigure
This dependency is a hack for TodoApplication.java, which isn't required for Quarkus. Point of demo is to NOT have any code changes.
这是这一部分技巧的关键。这种依赖关系允许Spring Boot和Quarkus在构建时解析这些类。依赖optional在Maven / compileOnlyGradle中声明,这意味着它永远不会包含在Quarkus构建生成的应用程序二进制文件中。它会包含在Spring Boot构建所生成的二进制文件中,因为所有其他spring-boot-starter-*依赖项也都依赖于它,因此它是可传递的。
Wrap Up
您在本文中看到了如何获取现有的Spring Boot应用程序并在Quarkus上运行它,而无需对代码进行任何更改。方法是魔术还是疯狂?也许两者都有一点?由您自己决定。
这篇文章展示了一种将“ Hello World”以外的应用程序从Spring Boot迁移到Quarkus的方法,其硬性要求是不更改一行源代码。它根本不是要代表唯一的潜在迁移路径。此外,有时应用程序使用某些库或API时,可能没有Quarkus等效项。在这些情况下,可能需要更改代码或进行一些重构。
非常感谢Eric Murphy。他是该应用程序的原始作者,并提出了魔术技巧。
参考
这篇文章的所有源代码都可以在这里找到。该main分支包含Maven的版本和gradle分支包含的摇篮版本。两个分支上的应用程序源代码相同。
原文链接:http://codingdict.com/