支援 Graal VM
dubbo 3.0 支援 native-image 文件
功能說明
本文將介紹 dubbo 3.0 專案連接 GraalVM 並將 native-image 編譯成二進位檔的過程。
更多關於 GraalVM 的資訊可以閱讀https://graalvm.dev.org.tw/docs/getting-started/container-images/此文件。
使用場景
使用方法
在編譯我們的 dubbo 專案之前,我们需要確保我們基於 graalVM 環境。
安裝 GraalVM
前往https://graalvm.dev.org.tw/官方網站,根據您的系統選擇最新版本進行安裝
安裝完成後,修改路徑配置 JAVA_HOME,生效後檢查本地 jdk,可以看到如下
這裡我們使用基於 jdk1.8 版本的 GraalVM。
- 要安裝 native-image,只需執行 gu install native-image。
- 拉取 dubbo 程式碼並切換到 apache:3.0 分支。
- 手動執行生成的 SPI 程式碼。
由於目前 native-image 的編譯不支援程式碼動態產生和編譯,因此需要手動產生與程式碼動態產生相關的部分。這裡有一個工具函式
執行 CodeGenerator 在 dubbo-native 模組下產生 SPI 程式碼。
在根目錄執行 install
MacdeMacBook-pro-3:incubator-dubbo mac$ pwd
/Users/mac/Documents/Mi/project/incubator-dubbo
MacdeMacBook-pro-3:incubator-dubbo mac$ mvn clean package install -Dmaven.test.skip=true
編譯 demo 專案
這裡我們提供了一個可以直接編譯的範例專案,dubbo-demo/dubbo-demo-native。安裝完上述步驟後,先到 dubbo-demo-native 的 provider 執行 native-image 編譯
mvn clean package -P native -Dmaven.test.skip=true
這裡,由於我們在 maven 中引入了 native-image 外掛,可以直接執行外掛 -P native。
編譯成功後,您可以在 target 目錄下看到生成的二進位檔案,在本機啟動一個 ZooKeeper,然後直接執行該二進位檔案。可以看到如下所示的啟動成功畫面。
consumer 端也執行編譯,在 consumer 的 target 目錄下也會生成一個二進位檔案:demo-native-consumer。執行此二進位檔案,您可以看到如下所示的呼叫結果。
具體步驟
實際上,我們已經在此 demo 下完成了一些工作,以確保專案可以編譯和執行。主要步驟如下:
- 引入 dubbo-native 依賴
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-native</artifactId>
<version>${project.version}</version>
</dependency>
此模組下是我們生成的 SPI 程式碼。
- 引入 native-image 插件
<plugin>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>native-image-maven-plugin</artifactId>
<version>21.0.0.2</version>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<skip>false</skip>
<imageName>demo-native-provider</imageName>
<mainClass>org.apache.dubbo.demo.graalvm.provider.Application</mainClass>
<buildArgs>
--no-fallback
--initialize-at-build-time=org.slf4j.MDC
--initialize-at-build-time=org.slf4j.LoggerFactory
--initialize-at-build-time=org.slf4j.impl.StaticLoggerBinder
--initialize-at-build-time=org.apache.log4j.helpers.Loader
--initialize-at-build-time=org.apache.log4j.Logger
--initialize-at-build-time=org.apache.log4j.helpers.LogLog
--initialize-at-build-time=org.apache.log4j.LogManager
--initialize-at-build-time=org.apache.log4j.spi.LoggingEvent
--initialize-at-build-time=org.slf4j.impl.Log4jLoggerFactory
--initialize-at-build-time=org.slf4j.impl.Log4jLoggerAdapter
--initialize-at-build-time=org.eclipse.collections.api.factory.Sets
--initialize-at-run-time=io.netty.channel.epoll.Epoll
--initialize-at-run-time=io.netty.channel.epoll.Native
--initialize-at-run-time=io.netty.channel.epoll.EpollEventLoop
--initialize-at-run-time=io.netty.channel.epoll.EpollEventArray
--initialize-at-run-time=io.netty.channel.DefaultFileRegion
--initialize-at-run-time=io.netty.channel.kqueue.KQueueEventArray
--initialize-at-run-time=io.netty.channel.kqueue.KQueueEventLoop
--initialize-at-run-time=io.netty.channel.kqueue.Native
--initialize-at-run-time=io.netty.channel.unix.Errors
--initialize-at-run-time=io.netty.channel.unix.IovArray
--initialize-at-run-time=io.netty.channel.unix.Limits
--initialize-at-run-time=io.netty.util.internal.logging.Log4JLogger
--initialize-at-run-time=io.netty.channel.unix.Socket
--initialize-at-run-time=io.netty.channel.ChannelHandlerMask
--report-unsupported-elements-at-runtime
--allow-incomplete-classpath
--enable-url-protocols=http
-H:+ReportExceptionStackTraces
</buildArgs>
</configuration>
</plugin>
它定義了生成映像的名稱以及構建映像的一些參數。
- 掛載 native-image-agent
由於我們需要先指定一些反射、JNI 和其他類別,因此需要使用 agent 以正常方式執行它,以便為這些類別生成 json 格式的資訊。
在啟動參數中新增
-agentlib:native-image-agent=config-output-dir=/tmp/config/,config-write-period-secs=300,config-write-initial-delay-secs=5
以正常方式啟動,在專案的 resources 目錄下建立一個 META-INF.native-image 資料夾,並將在本機目錄中生成的檔案貼上到該資料夾中。
(可能會有缺少未生成的類別資訊,需要根據編譯或執行時的錯誤訊息手動新增。)
**完成上述步驟後,即可編譯專案。**