雲原生時代高效能Java框架—Quarkus(一)
阿新 • • 發佈:2020-07-18
*[**——— Quarkus&GraalVM介紹、建立並啟動第一個專案**](http://blog.dongxishaonian.tech/?p=824)*
------
***Quarkus系列博文***
- *[Quarkus&GraalVM介紹、建立並啟動第一個專案](http://blog.dongxishaonian.tech/archives/789(在新視窗中開啟))*
- *構建Quarkus本地映象、容器化部署Quarkus專案*
- *...*
------
## Quarkus介紹
Quarkus 是一個為 **Java 虛擬機器(JVM)**和**原生編譯(native compilation)**而設計的全棧Kubernetes 原生 [Java 框架](https://www.redhat.com/zh/topics/cloud-native-apps/what-is-a-Java-framework),用於優化Java特別是Java專案的容器化,並使其成為[serverless](https://www.redhat.com/en/topics/cloud-native-apps/what-is-serverless)、[雲](https://www.redhat.com/en/topics/cloud)和 [Kubernetes](https://www.redhat.com/en/topics/containers/what-is-kubernetes) 環境的高效平臺。
Quarkus 可與常用 Java 標準、框架和庫協同工作,例如 Eclipse MicroProfile、Apache Kafka、RESTEasy(JAX-RS)、Hibernate ORM(JPA)、Spring、Infinispan、Camel 等。
Quarkus 的依賴注入解決方案基於 CDI(上下文和依賴注入),且包含一個擴充套件框架來擴充套件功能並將其配置、引導並整合到您的應用中。新增[擴充套件](https://quarkus.io/extensions/)就像新增依賴項一樣容易;或者,您可以使用 Quarkus 工具。
此外也是引人注目的一個特點,它還向 GraalVM(一種通用虛擬機器,用於執行以多種語言(包括 Java 和 JavaScript)編寫的應用)提供正確資訊,以便對應用進行原生編譯。
Rad Hat列出了一下清單來表明使用Quarkus的好處:[檢查清單](https://www.redhat.com/cms/managed-files/cl-4-reasons-try-quarkus-checklist-f19180cs-201909-a4-zh.pdf)
### Quarkus與傳統Java框架對比
![img](http://images.dongxishaonian.tech/quarkus_metrics_graphic_bootmem_wide.png)Quarkus與傳統技術棧對比
來自官方的一張圖,展示了使用Quarkus框架開發專案和使用傳統框架開發的一些執行時資料明細對比,可以看到Quarkus專案在JVM中執行時所消耗的記憶體和介面響應能力要明顯好於傳統的Java技術棧。而將Quarkus編譯成本地可執行檔案(本地映象)之後,其優勢可以說非常明顯了。
## GraalVM簡介
GraalVM是一種高效能的虛擬機器,它可以顯著的提高程式的效能和執行效率,非常適合微服務。其設計初衷是實現可以執行不同語言(Java、JavaScript、基於LLVM的語言(例如C和C ++)以及其他動態語言)編寫的應用程式。它消除了不同程式語言之間的隔閡,並實現了多語言共享執行時的互操作性。它可以獨立執行,也可以在OpenJDK,Node.js或Oracle資料庫的上下文中執行。
![GraalVM system diagram](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggtxy2x3gej30qo0f0whi.jpg)
對於Java應用程式,GraalVM可以帶來很多有價值的好處:更快地執行它們,通過指令碼語言(JavaScript, R, Python...)提供可擴充套件性或建立提前編譯的本機映像(native-image)。
更多關於GraalVM的資訊可參考:[此篇文章](http://blog.dongxishaonian.tech/archives/799)。
## GraalVM安裝
本文我們使用[SDKMAN](https://sdkman.io/)來安裝GraalVM。SDKMAN是一款用於在大多數基於Unix的系統上管理多個軟體開發套件的並行版本的工具。它提供了一個方便的命令列介面(CLI)和API,用於安裝,切換,刪除和列出候選人。它以前被稱為Groovy enVironment Manager (GVM),受到了非常有用的RVM和rbenv工具的啟發,該工具在Ruby社群中廣泛使用。
### 安裝SDKMAN
執行如下命令進行安裝:
```bash
$ curl -s "https://get.sdkman.io" | bash
$ source "$HOME/.sdkman/bin/sdkman-init.sh"
```
執行如下命令,驗證是否已安裝ADKMAN:
```bash
$ sdk version
```
### 安裝GraalVM
執行如下命令:
```bash
$ sdk list java
```
可以看到SDKMAN列出了所支援的所有Java發行版
![image-20200717142755813](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggtycsyfe9j30wc0bugnb.jpg)
我們找到GraalVM的發行版
![image-20200717142840033](https://tva1.sinaimg.cn/large/007S8ZIlgy1ggtydk3m8bj30xm05sdgb.jpg)
截至編寫本文時,GraalVM的最新版本為20.1.0.r11-grl,所以我們會安裝此版本。執行如下命令安裝GraalVM:
```bash
$ sdk install java 20.1.0.r11-grl
```
至此,GraalVM安裝完畢!我們可以執行如下命令來判斷GraalVM是否已安裝:
```bash
$ java -version
```
![image-20200717143216643](https://tva1.sinaimg.cn/large/007S8ZIlly1ggud02g9t0j315i02ywf2.jpg)
## 建立專案
我們有多種方式建立Quarkus專案
### 使用Intellij IDEA建立Quarkus專案
點選選單欄File>New>Project... 建立新專案
![image-20200717150609041](https://tva1.sinaimg.cn/large/007S8ZIlly1ggtzgp2cydj319c0qkwhx.jpg)
點選Next,並填寫適當的資訊,Next>Next...,建立完畢。
### 使用Maven命令列建立Quarkus專案
執行如下命令,建立Quarkus專案:
```bash
mvn io.quarkus:quarkus-maven-plugin:1.6.0.Final:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=getting-started \
-DclassName="org.acme.getting.started.GreetingResource" \
-Dpath="/hello"
cd getting-started
```
至此,建立專案完畢!
## 啟動專案
我們使用IDEA開啟專案
![image-20200717152929281](https://tva1.sinaimg.cn/large/007S8ZIlly1ggu04ucrrnj31ee0u0td7.jpg)
Quarkus並沒有類似Spring Boot、Helidon之類框架一樣的啟動類,我們需要通過執行Maven命令來啟動專案。
在IDEA控制檯執行如下命令來啟動專案:
```bash
./mvnw compile quarkus:dev
```
啟動成功!
![image-20200717153314096](https://tva1.sinaimg.cn/large/007S8ZIlly1ggu08uubvzj32560qk0zj.jpg)
當然每次執行命令列會顯得不便,我們可以通過如下配置來配置專案快捷啟動:
![image-20200717153444892](https://tva1.sinaimg.cn/large/007S8ZIlly1ggu0aary6ej30xa08ymzi.jpg)
點選左上角"+"圖示新增一個Maven配置如左邊欄,在右邊欄中的Command line中填入"compile quarkus:dev",點選OK。
![image-20200717153542033](https://tva1.sinaimg.cn/large/007S8ZIlly1ggu0bahsmuj315w0sqdir.jpg)
此時可以點下下圖所示圖示來便捷啟動專案
![image-20200717153914940](https://tva1.sinaimg.cn/large/007S8ZIlly1ggu0eytva6j30na01ogln.jpg)
## 執行測試
開啟專案中的測試類,看到如下程式碼:
```java
@QuarkusTest //1
public class ExampleResourceTest {
@Test
public void testHelloEndpoint() {
given()
.when().get("/hello")
.then()
.statusCode(200) //2
.body(is("hello"));
}
}
```
1. 通過使用@QuarkusTest註解執行程式,可以指示JUnit在測試之前啟動應用程式。
2. 檢查HTTP響應狀態程式碼和內容。
預設情況下,測試將在埠8081上執行,以免與正在執行的應用程式衝突。Quarkus自動將RestAssured配置為使用此埠。如果要測試其他路徑,則可以使用@TestHTTPResource註解將被測試的URL直接注入到測試類的欄位中。該欄位的型別可以是字串,URL或URI。我們需要為該註解指定測試路徑的值。例如,如果我要測試對映到/myservlet的Servlet,只需在測試中新增以下內容:
```java
@QuarkusTest
public class ExampleResourceTest {
@TestHTTPResource("/myservlet")
URL testUrl;
@Test
public void testHelloEndpoint() {
given()
.when().get(testUrl)
.then()
.statusCode(200)
.body(is("hello"));
}
}
```
可以通過在專案配置檔案中配置quarkus.http.test-port屬性控制測試埠。 Quarkus還建立了一個名為test.url的系統屬性,該屬性值將被設定成基礎測試URL(BasePath)。
## 總結
我們進入了雲原生、微服務的時代,我們告別了大型單體應用的龐大和複雜,並且收穫了微服務帶來的極大的好處 。但是一些問題也開始接踵而至。隨著微小服務的增多,曾經在單個應用上發生的多餘無用依賴、Java專案與生俱來的啟動過程緩慢、JIT優化問題擴散到了每個微服務上面。而且傳統的Java EE規範並沒有微服務的模式解決方案,問題很迫切需要解決。幸運的事,隨著Quarkus、Helidon等等一些新型Java開發框架的出現緩解了這個局面(以及目前Spring生態也開始了對GraalVM的大力支援),他們使Java變得更加本地化,不管是專案的體量方面還是資源消耗和執行效率方面都有顯著