使用 GraalVM 打包 Native Image

2022-04-24 16:08 更新

dubbo3.0支持native-image文檔

概述

本文檔將介紹將dubbo3.0項(xiàng)目接入GraalVM,進(jìn)行native-image編譯為二進(jìn)制的流程。

關(guān)于GraalVm的更多信息可以閱讀 https://www.graalvm.org/docs/getting-started/container-images/ 此文檔。

使用樣例

在編譯我們的dubbo項(xiàng)目之前,需要確保我們正基于graalVm的環(huán)境。

  1. 安裝GraalVM

進(jìn)入https://www.graalvm.org/ 官網(wǎng)根據(jù)自己的系統(tǒng)選取最新版本安裝:

安裝完成后,修改配置JAVA_HOME的路徑,生效后查看本地jdk可以看到如下:

 這里我們使用的基于jdk1.8版本的GraalVM。

  • 安裝native-image,只需執(zhí)行g(shù)u install native-image即可。
  1. 拉取dubbo代碼,切換到apache:3.0分支。
  2. 手動(dòng)執(zhí)行生成SPI代碼。

由于目前編譯native-image不支持代碼動(dòng)態(tài)生成編譯,所以有關(guān)代碼動(dòng)態(tài)生成的部分需要我們手動(dòng)先生成,這里提供了工具函數(shù):

 執(zhí)行CodeGenerator即可在dubbo-native模塊下生成SPI代碼。

  1. 在根目錄下執(zhí)行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
  1. 編譯demo項(xiàng)目

這里我們提供了可直接進(jìn)行編譯的示例項(xiàng)目,dubbo-demo/dubbo-demo-native。上面步驟install完成后,先到dubbo-demo-native的provider下,執(zhí)行native-image編譯:

 mvn clean package -P native -Dmaven.test.skip=true

這里由于我們?cè)趍aven中引入了native-image插件,所以直接-P native即可執(zhí)行該插件。

 編譯成功后可以在target下看到已經(jīng)生成的二進(jìn)制文件,本地啟動(dòng)一個(gè)zookeeper,直接執(zhí)行該二進(jìn)制,可見啟動(dòng)成功如下:

 consumer端同樣執(zhí)行編譯,在consumer的target下也會(huì)生成二進(jìn)制文件:demo-native-consumer,執(zhí)行該二進(jìn)制可以看到調(diào)用結(jié)果如下:

具體步驟

實(shí)際上在這個(gè)demo下我們做了一些工作來確保項(xiàng)目可以編譯執(zhí)行,主要有以下幾個(gè)步驟

  • 引入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>

其中定義了生成的鏡像名以及一些構(gòu)建鏡像的參數(shù)。

  • 掛載native-image-agent

由于我們需要將一些反射、JNI等類先指定出來,我們需要先使用該agent以正常方式運(yùn)行一遍生成這些類的json形式的信息。

在啟動(dòng)參數(shù)中添加:

-agentlib:native-image-agent=config-output-dir=/tmp/config/,config-write-period-secs=300,config-write-initial-delay-secs=5

以正常方式啟動(dòng),在項(xiàng)目的resources下建立文件夾META-INF.native-image,把在本地目錄中生成的文件粘進(jìn)去:

 (可能會(huì)有缺漏沒有生成的類信息,需要根據(jù)編譯或運(yùn)行時(shí)的報(bào)錯(cuò)信息手動(dòng)添加。)

完成以上幾步后就可以進(jìn)行項(xiàng)目的編譯了。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)