開篇
最近幾年,Spring全家桶橫掃其它Java框架,已然成為事實標準,單體應用使用Spring Framework+Spring Boot,服務治理Spring Cloud,生態完善,各種組件層出不窮。曾經還玩過JFinal和Nutz等國內的開發框架,但是僅僅是私下玩玩,實際工作過程中,還是Spring的天下,很少會選擇其它小眾的框架(誰知道會不會有填不完的大坑)。
最近在社區閑逛的時候,發現一個Red Hat開源的Java框架Quarkus,定位為GraalVM和OpenJDK HotSpot量身定制的一個Kurbernetes Native Java框架。雖然開源時間較短,但是生態方面也已經達到可用的狀態,自身包含擴展框架,已經支持像Netty、Undertow、Hibernate、JWT等框架,足以用于開發企業級應用,用戶也可以基于擴展框架自行擴展。
術語簡介
- Cloud Native Application:即云原生應用,是由 Pivotal 的Matt Stine在2013年提出的,個人認為所謂云原生應用也是SAAS服務的一種,針對近年來云計算平臺的發展,SAAS服務進一步發展的產物。
- Graalvm:Oracle在2018年開源的一個通用型虛擬機,可以用來構建多語言應用,也可以簡單地用來編譯和構建Java應用,甚至可以將Java應用構建成Native Image,以提高應用的啟動速度以及降低應用的內存占用,目前還是一個實驗性產品。
- 12-Factor::全稱為“The Twelve-Factor App”,可以認為是SAAS服務的參考標準,對SAAS服務開發的各個方面都提出了明確的參考標準,但是就像Restful API一樣,這是一個建議標準,每個開發人員理解都可能有偏差。
構建一個Quarkus應用
創建項目
開發環境
除了一般的Java開發環境外,你還需要額外安裝Graalvm,用于構建Native應用。
Graalvm安裝參考:Install GraalVM創建項目
你可以使用Maven命令快速創建一個Quarkus應用,也可以自行搭建。
方式一:快速創建命令如下(來源于官網):
mvn io.quarkus:quarkus-maven-plugin:0.15.0:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=getting-started \
-DclassName="org.acme.quickstart.GreetingResource" \
-Dpath="/hello"
方式二:自行搭建,首先創建一個Maven項目,添加Quarkus的依賴和plugin,參考如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.centychen</groupId>
<artifactId>quarkus-simple-example</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<surefire-plugin.version>3.0.0-M3</surefire-plugin.version>
<quarkus.version>0.14.0</quarkus.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- 管理Quarkus依賴包版本 -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bom</artifactId>
<version>${quarkus.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 使用Resteasy框架 -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<!-- Junit -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<!-- Rest接口測試 -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- quarkus maven插件 -->
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 用于單元測試 -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire-plugin.version}</version>
<configuration>
<systemProperties>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
</systemProperties>
</configuration>
</plugin>
</plugins>
</build>
</project>
編寫Resource
編寫Resource類,實際就是Restful接口,按照Restful思想,接口即資源,所以叫Resource挺貼切的。該類中實現一個/hello/{name}
接口,參考如下:
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
/**
* @author: cent
* @email: chenzhao@viomi.com.cn
* @date: 2019/5/4.
* @description:
*/
@Path("/hello")
public class GreetingResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/{name}")
public CompletionStage<String> hello(@PathParam("name") String name) {
//使用異步響應
return CompletableFuture.supplyAsync(() -> String.format("Hello,%s!", name));
}
}
啟動測試
你會發現,上面沒有像Spring Boot框架一樣編寫main方法,也沒有部署到Web容器(如Tomcat、Undertow等)中,那么應該如何啟動測試呢?很簡單,命令行進入項目根目錄,通過以下命令啟動開發測試:
mvn compile quarkus:dev
訪問http://localhost:8080/hello/cent
,返回如下:
至此,一個簡單的基于Quarkus框架的Restful服務已經搭建好了,好像跟Spring Boot比較,除了啟動方式,其它沒太大差別哦?下面才是差異的地方。
構建Native Image
Quarkus定位是一個Native Java的框架,那么怎樣將項目構建成Native應用呢?只需要兩個步驟:
- 在
pom.xml
中增加構建profile配置,如下:
<profiles>
<profile>
<id>native</id>
<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<version>${quarkus.version}</version>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<configuration>
<enableHttpUrlHandler>true</enableHttpUrlHandler>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
- 使用
mvn package -Pnative
命令構建Native Image,構建完成后,target目錄下會存在一個名字為[project name]-runner
的文件,這個就是應用的可執行文件,你可以拷貝到其它目錄運行,運行如下:
./quarkus-simple-example-1.0-SNAPSHOT-runner
2019-05-15 12:02:31,199 INFO [io.quarkus] (main) Quarkus 0.14.0 started in 0.012s. Listening on: http://[::]:8080
2019-05-15 12:02:31,201 INFO [io.quarkus] (main) Installed features: [cdi, resteasy]
總結
上面僅僅是Quarkus的一個簡單示例,搭建一個Restful服務并構建成Native Image。完成這一步之后,你還可以將Native Image構建成Docker鏡像并使用Kubernetes進行部署,后面的步驟與Spring Boot應用構建和發布沒太大差異,在本文就不說了。
Quarkus目前還是一個很輕量級的框架,使用簡單且啟動超快,希望后續版本演進能夠保持足夠的輕量,如果變得像Spring全家桶那么龐大,估計啟動也快不了了~