Build GraalVM Native Image(Alpha)

Background

This section mainly introduces how to build the Native Image of ShardingSphere-Proxy and the corresponding Docker Image through the native-image component of GraalVM.

Notice

  1. version: "3.8"
  2. services:
  3. apache-shardingsphere-proxy-native:
  4. image: ghcr.io/apache/shardingsphere-proxy-native:latest
  5. volumes:
  6. - ./custom/conf:/opt/shardingsphere-proxy-native/conf
  7. ports:
  8. - "3307:3307"
  • If you find that the build process has missing GraalVM Reachability Metadata, A new issue should be opened at https://github.com/oracle/graalvm-reachability-metadata, And submit a PR containing GraalVM Reachability Metadata missing from ShardingSphere itself or dependent third-party libraries.

  • The master branch of ShardingSphere is not yet ready to handle unit tests in Native Image, Need to wait for the integration of Junit 5 Platform, you always need to build GraalVM Native Image in the process, Plus -DskipNativeTests or -DskipTests parameter specific to GraalVM Native Build Tools to skip unit tests in Native Image.

  • The following three algorithm classes are not available under GraalVM Native Image because they involve the groovy.lang.Closure class that is inconvenient for GraalVM Truffle Espresso to interact between the host JVM and the guest JVM.

    • org.apache.shardingsphere.sharding.algorithm.sharding.complex.ComplexInlineShardingAlgorithm
    • org.apache.shardingsphere.sharding.algorithm.sharding.hint.HintInlineShardingAlgorithm
    • org.apache.shardingsphere.sharding.algorithm.sharding.inline.InlineShardingAlgorithm
  • At the current stage, ShardingSphere Proxy in GraalVM Native Image is in the stage of mixed AOT ( GraalVM Native Image ) and JIT ( GraalVM Truffle Espresso ) operation. Since https://github.com/oracle/graal/issues/4555 has not been closed, the .so file required for GraalVM Truffle Espresso to run does not enter the GraalVM Native Image. So if you need to run ShardingSphere Proxy Native binary files outside the Docker Image, you need to ensure that the system environment variable JAVA_HOME points to the bin directory of GraalVM, and this GraalVM instance already has the espresso component installed via the GraalVM Updater.

  • This section assumes a Linux (amd64, aarch64), MacOS (amd64) or Windows (amd64) environment. If you are on MacOS (aarch64/M1) environment, you need to follow https://github.com/oracle/graal/issues/2666 which is not closed yet.

Premise

  1. Install and configure GraalVM CE or GraalVM EE for JDK 17 according to https://www.graalvm.org/downloads/. GraalVM CE for JDK 17 can also be installed via SDKMAN!.

  2. Install the native-image and espresso component via the GraalVM Updater tool.

  3. Install the local toolchain as required by https://www.graalvm.org/22.3/reference-manual/native-image/#prerequisites.

  4. If you need to build a Docker Image, make sure docker-ce is installed.

Steps

  1. Get Apache ShardingSphere Git Source
  1. Build the product on the command line, in two cases.
  • Scenario 1: No need to use JARs with SPI implementations or 3rd party dependencies

  • Execute the following command in the same directory of Git Source to directly complete the construction of Native Image.

  1. ./mvnw -am -pl distribution/proxy-native -B -Pnative -DskipTests -Dmaven.javadoc.skip=true -Dcheckstyle.skip=true -Dspotless.apply.skip=true -Drat.skip=true clean package
  • Scenario 2: It is necessary to use a JAR that has an SPI implementation or a third-party dependent JAR of a LICENSE such as GPL V2.

  • Add SPI implementation JARs or third-party dependent JARs to dependencies in distribution/proxy-native/pom.xml. Examples are as follows

  1. <dependencies>
  2. <dependency>
  3. <groupId>com.mysql</groupId>
  4. <artifactId>mysql-connector-j</artifactId>
  5. <version>8.0.32</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.apache.shardingsphere</groupId>
  9. <artifactId>shardingsphere-sql-translator-jooq-provider</artifactId>
  10. <version>5.3.1</version>
  11. </dependency>
  12. </dependencies>
  • Build GraalVM Native Image via command line.
  1. ./mvnw -am -pl distribution/proxy-native -B -Pnative -DskipTests -Dmaven.javadoc.skip=true -Dcheckstyle.skip=true -Dspotless.apply.skip=true -Drat.skip=true clean package
  1. To start Native Image through the command line, you need to bring 4 parameters. The first parameter is the port used by ShardingSphere Proxy, the second parameter is the /conf folder containing server.yaml written by you, the third parameter is the Address of the bound port, and the fourth parameter is Force Start, if it is true, it will ensure that ShardingSphere Proxy Native can start normally no matter whether it is connected or not. Assuming the folder ./custom/conf already exists, the example is
  1. ./apache-shardingsphere-proxy-native 3307 ./custom/conf "0.0.0.0" false
  1. If you need to build a Docker Image, execute the following command on the command line after adding dependencies that exist for SPI implementation or third-party dependencies.
  1. ./mvnw -am -pl distribution/proxy-native -B -Pnative,docker.native -DskipTests -Dmaven.javadoc.skip=true -Dcheckstyle.skip=true -Dspotless.apply.skip=true -Drat .skip=true clean package
  • Assuming that there is a conf folder containing server.yaml as ./custom/conf, you can start the Docker Image corresponding to GraalVM Native Image through the following docker-compose.yml file.
  1. version: "3.8"
  2. services:
  3. apache-shardingsphere-proxy-native:
  4. image: apache/shardingsphere-proxy-native:latest
  5. volumes:
  6. - ./custom/conf:/opt/shardingsphere-proxy-native/conf
  7. ports:
  8. - "3307:3307"
  • If you don’t make any changes to the Git Source, the commands mentioned above will use oraclelinux:9-slim as the Base Docker Image. But if you want to use a smaller Docker Image like busybox:glic, gcr.io/distroless/base or scratch as the Base Docker Image, you need according to https://www.graalvm.org/22.3/reference-manual/native-image/guides/build-static-executables/, Add operations such as -H:+StaticExecutableWithDynamicLibC to jvmArgs as the native profile of pom.xml. Also note that some 3rd party dependencies will require more system libraries such as libdl to be installed in the Dockerfile. So make sure to tune distribution/proxy-native according to your usage pom.xml and Dockerfile below.

Observability

  1. Download https://dlcdn.apache.org/skywalking/java-agent/8.12.0/apache-skywalking-java-agent-8.12.0.tgz and untar it to distribution/proxy-native in ShardingSphere Git Source.

  2. Modify the native profile of distribution/proxy-native/pom.xml, Add the following jvmArgs to the configuration of org.graalvm.buildtools:native-maven-plugin.

  1. <jvmArgs>
  2. <arg>-Dskywalking.agent.service_name="your service name"</arg>
  3. <arg>-Dskywalking.collector.backend_service="your skywalking oap ip and port"</arg>
  4. <arg>-javaagent:./skywalking-agent/skywalking-agent.jar</arg>
  5. </jvmArgs>
  1. Build the GraalVM Native Image from the command line.
  1. ./mvnw -am -pl distribution/proxy-native -B -Pnative -DskipTests -Dmaven.javadoc.skip=true -Dcheckstyle.skip=true -Dspotless.apply.skip=true -Drat.skip =true clean package