From bffa8c0cf78ce19d52946c146909aa77a88e909a Mon Sep 17 00:00:00 2001 From: linghengqian Date: Wed, 2 Oct 2024 00:16:44 +0800 Subject: [PATCH] Let ShardingSphere Proxy Native be able to start and be used normally --- .github/workflows/nightly-build.yml | 2 +- distribution/proxy-native/Dockerfile | 20 +-- distribution/proxy-native/pom.xml | 69 +++------- ...phere-proxy-native-binary-distribution.xml | 10 +- .../startup/graalvm-native-image.cn.md | 108 ++++++++------- .../startup/graalvm-native-image.en.md | 130 +----------------- test/native/pom.xml | 6 + .../proxy/commons/ProxyTestingServer.java | 51 +++++++ .../natived/proxy/features/ShardingTest.java | 114 +++++++++++++++ .../proxy/features/database-sharding.yaml | 66 +++++++++ .../yaml/proxy/features/global.yaml | 30 ++++ 11 files changed, 365 insertions(+), 241 deletions(-) create mode 100644 test/native/src/test/java/org/apache/shardingsphere/test/natived/proxy/commons/ProxyTestingServer.java create mode 100644 test/native/src/test/java/org/apache/shardingsphere/test/natived/proxy/features/ShardingTest.java create mode 100644 test/native/src/test/resources/test-native/yaml/proxy/features/database-sharding.yaml create mode 100644 test/native/src/test/resources/test-native/yaml/proxy/features/global.yaml diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 5cdf218bce12b..03bb5922b1f0c 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -133,7 +133,7 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Push Docker Image run: | - ./mvnw -am -pl distribution/proxy-native -Prelease.native,docker.buildx.push.native -B -T1C -DskipTests -Dproxy.image.repository=${{ env.PROXY_NATIVE }} -Dproxy.image.tag=${{ github.sha }} clean package + ./mvnw -am -pl distribution/proxy-native -Prelease.native,docker.buildx.push.native -B -T1C -DskipTests -Dproxy.native.image.repository=${{ env.PROXY_NATIVE }} -Dproxy.native.image.tag=${{ github.sha }} clean package build-agent-image: if: github.repository == 'apache/shardingsphere' name: Build Agent Image diff --git a/distribution/proxy-native/Dockerfile b/distribution/proxy-native/Dockerfile index a65a1b219d32f..d44cab5d04e34 100644 --- a/distribution/proxy-native/Dockerfile +++ b/distribution/proxy-native/Dockerfile @@ -14,19 +14,9 @@ # See the License for the specific language governing permissions and # limitations under the License. # -FROM alpine AS prepare - -ARG APP_NAME -ENV LOCAL_PATH /opt/shardingsphere-proxy-native - -ADD target/${APP_NAME}.tar.gz /opt -RUN mv /opt/${APP_NAME} ${LOCAL_PATH} - FROM oraclelinux:9-slim -MAINTAINER ShardingSphere "dev@shardingsphere.apache.org" - -ARG NATIVE_IMAGE_NAME -ENV LOCAL_PATH /opt/shardingsphere-proxy-native - -COPY --from=prepare ${LOCAL_PATH} ${LOCAL_PATH} -ENTRYPOINT ${LOCAL_PATH}/${NATIVE_IMAGE_NAME} 3307 ${LOCAL_PATH}/conf "0.0.0.0" false +LABEL org.opencontainers.image.authors="ShardingSphere dev@shardingsphere.apache.org" +ENV LOCAL_PATH=/opt/shardingsphere-proxy-native +ARG OUTPUT_DIRECTORY_NAME +COPY target/${OUTPUT_DIRECTORY_NAME} ${LOCAL_PATH} +ENTRYPOINT ${LOCAL_PATH}/proxy-native 3307 ${LOCAL_PATH}/conf "0.0.0.0" false diff --git a/distribution/proxy-native/pom.xml b/distribution/proxy-native/pom.xml index 068b223f8234e..0374908c34c9e 100644 --- a/distribution/proxy-native/pom.xml +++ b/distribution/proxy-native/pom.xml @@ -24,11 +24,14 @@ 5.5.1-SNAPSHOT shardingsphere-proxy-native-distribution + pom ${project.artifactId} - apache-shardingsphere-proxy-native - apache/shardingsphere-proxy-native + proxy-native + linux/amd64,linux/arm64 + apache/shardingsphere-proxy-native + ${project.version} @@ -86,6 +89,7 @@ true org.apache.shardingsphere.proxy.Bootstrap + ${proxy.native.image.name} -H:+AddAllCharsets @@ -116,7 +120,7 @@ - shardingsphere-proxy-native-bin + build and package single @@ -133,10 +137,6 @@ docker.native - - ${native.image.repository} - ${project.version} - @@ -145,7 +145,7 @@ ${exec-maven-plugin.version} - build + build docker image exec @@ -154,16 +154,13 @@ docker build - --pull --build-arg - APP_NAME=${project.build.finalName}-shardingsphere-proxy-native-bin - --build-arg - NATIVE_IMAGE_NAME=${imageName} + OUTPUT_DIRECTORY_NAME=${project.build.finalName}-shardingsphere-proxy-native-bin . -t - ${proxy.image.repository}:${proxy.image.tag} + ${proxy.native.image.repository}:${proxy.native.image.tag} -t - ${proxy.image.repository}:latest + ${proxy.native.image.repository}:latest @@ -174,11 +171,6 @@ docker.buildx.push.native - - linux/amd64,linux/arm64 - ${native.image.repository} - ${project.version} - @@ -197,40 +189,17 @@ buildx create - --use --driver docker-container --name shardingsphere-builder --platform - ${proxy.image.platform} - - - - - build - - exec - - package - - docker - - buildx - build - --pull - --platform - ${proxy.image.platform} - --build-arg - APP_NAME=${project.build.finalName}-shardingsphere-proxy-native-bin - --build-arg - NATIVE_IMAGE_NAME=${imageName} - . + ${proxy.native.image.platform} - push + build and push docker image exec @@ -241,17 +210,17 @@ buildx build --push + --builder + shardingsphere-builder --platform - ${proxy.image.platform} - --build-arg - APP_NAME=${project.build.finalName}-shardingsphere-proxy-native-bin + ${proxy.native.image.platform} --build-arg - NATIVE_IMAGE_NAME=${imageName} + OUTPUT_DIRECTORY_NAME=${project.build.finalName}-shardingsphere-proxy-native-bin . -t - ${proxy.image.repository}:${proxy.image.tag} + ${proxy.native.image.repository}:${proxy.native.image.tag} -t - ${proxy.image.repository}:latest + ${proxy.native.image.repository}:latest diff --git a/distribution/proxy-native/src/main/assembly/shardingsphere-proxy-native-binary-distribution.xml b/distribution/proxy-native/src/main/assembly/shardingsphere-proxy-native-binary-distribution.xml index 383baaaf5d6fe..21929def1d478 100644 --- a/distribution/proxy-native/src/main/assembly/shardingsphere-proxy-native-binary-distribution.xml +++ b/distribution/proxy-native/src/main/assembly/shardingsphere-proxy-native-binary-distribution.xml @@ -19,16 +19,18 @@ xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.0.0 http://maven.apache.org/xsd/assembly-2.0.0.xsd"> shardingsphere-proxy-native-bin + dir tar.gz true - ${project.build.finalName}-shardingsphere-proxy-native-bin + proxy-native ${project.build.directory} - ${imageName} + ${proxy.native.image.name} + *.so / 0755 @@ -41,7 +43,9 @@ ../../distribution/proxy/src/main/release-docs - **/* + licenses/* + LICENSE + NOTICE / diff --git a/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.cn.md b/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.cn.md index f2f12789569cf..344dac73738c4 100644 --- a/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.cn.md +++ b/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.cn.md @@ -5,17 +5,18 @@ weight = 2 ## 背景信息 -本节主要介绍如何通过 `GraalVM` 的 `native-image` 组件构建 ShardingSphere-Proxy 的 `Native Image` 和对应的 `Docker Image`。 +`GraalVM Native Image` 是一种将 Java 代码提前编译为二进制文件( native executable )的技术。 +此 native executable 仅包含运行时所需的代码,即应用程序类、标准库类、语言运行时和来自 JDK 的静态链接本机代码。 + +本节主要介绍如何通过 `GraalVM` 的 `native-image` 命令行工具构建 ShardingSphere-Proxy 的 `GraalVM Native Image`, +以及包含此 `GraalVM Native Image` 的 `Docker Image`。 ## 注意事项 -- ShardingSphere Proxy 尚未准备好与 GraalVM Native Image 集成。 Proxy 的 Native Image 产物在 - https://github.com/apache/shardingsphere/pkgs/container/shardingsphere-proxy-native 存在每夜构建。假设存在包 - 含`global.yaml` 的 `conf` 文件夹为 `./custom/conf`,你可通过如下的 `docker-compose.yml` 文件进行测试。 +Proxy 的 Native Image 产物在 https://github.com/apache/shardingsphere/pkgs/container/shardingsphere-proxy-native 存在每夜构建。 +假设存在包含`global.yaml` 的 `conf` 文件夹为 `./custom/conf`,你可通过如下的 `docker-compose.yml` 文件进行测试。 ```yaml -version: "3.8" - services: apache-shardingsphere-proxy-native: image: ghcr.io/apache/shardingsphere-proxy-native:latest @@ -25,57 +26,75 @@ services: - "3307:3307" ``` -- 本节假定处于 Linux(amd64,aarch64),MacOS(amd64,aarch64/M1)或 Windows(amd64)环境。 +默认情况下,ShardingSphere Proxy Native 的 GraalVM Native Image 中仅包含, + +1. ShardingSphere 维护的自有及部分第三方依赖的 GraalVM Reachability Metadata +2. H2database, OpenGauss 和 PostgreSQL 的 JDBC Driver +3. HikariCP 的数据库连接池 +4. Logback 的日志框架 + +如果用户需要在 ShardingSphere Proxy Native 中使用第三方 JAR,则需要修改 `distribution/proxy-native/pom.xml` 的内容,以构建以下的任意输出, + +1. 自定义的 GraalVM Native Image +2. 包含自定义的 GraalVM Native Image 的自定义 Docker Image + +本节假定处于以下的系统环境之一, -- 本节依然受到 ShardingSphere JDBC 一侧的 [GraalVM Native Image](/cn/user-manual/shardingsphere-jdbc/graalvm-native-image) 的已记录内容的限制。 +1. Linux(amd64,aarch64) +2. MacOS(amd64,aarch64/M1) +3. Windows(amd64) + +若处于 Linux(riscv64)等 Graal compiler 不支持的系统环境, +请根据 https://medium.com/graalvm/graalvm-native-image-meets-risc-v-899be38eddd9 的内容启用 LLVM backend 来使用 LLVM compiler。 + +本节依然受到 ShardingSphere JDBC 一侧的 [GraalVM Native Image](/cn/user-manual/shardingsphere-jdbc/graalvm-native-image) 的已记录内容的限制。 ## 前提条件 -1. 根据 https://www.graalvm.org/downloads/ 要求安装和配置 JDK 23 对应的 `GraalVM Community Edition` - 或 `GraalVM Community Edition` 的下游发行版。若使用 `SDKMAN!`, +1. 根据 https://www.graalvm.org/downloads/ 要求安装和配置 JDK 22 对应的 `GraalVM Community Edition` 或 `GraalVM Community Edition` 的下游发行版。 +若使用 `SDKMAN!`, ```shell -sdk install java 23-graalce +sdk install java 22.0.2-graalce +sdk use java 22.0.2-graalce ``` 2. 根据 https://www.graalvm.org/jdk23/reference-manual/native-image/#prerequisites 的要求安装本地工具链。 -3. 如果需要构建 Docker Image, 确保 `docker-ce` 已安装。 +3. 如果需要构建 Docker Image, 确保 `Docker Engine` 已安装。 ## 操作步骤 1. 获取 Apache ShardingSphere Git Source -- 在[下载页面](https://shardingsphere.apache.org/document/current/en/downloads/) - 或 https://github.com/apache/shardingsphere/tree/master 获取。 +在[下载页面](https://shardingsphere.apache.org/document/current/en/downloads/)或 https://github.com/apache/shardingsphere/tree/master 获取。 2. 在命令行构建产物, 分两种情形。 -- 情形一:不需要使用存在 SPI 实现的 JAR 或第三方依赖的 JAR - -- 在 Git Source 同级目录下执行如下命令, 直接完成 Native Image 的构建。 +情形一:不需要使用存在自定义 SPI 实现的 JAR 或第三方依赖的 JAR 。在 Git Source 同级目录下执行如下命令, 直接完成 Native Image 的构建。 ```bash ./mvnw -am -pl distribution/proxy-native -T1C -Prelease.native -DskipTests clean package ``` -- 情形二:需要使用存在 SPI 实现的 JAR 或 GPL V2 等 LICENSE 的第三方依赖的 JAR。 +情形二:需要使用存在自定义 SPI 实现的 JAR 或第三方依赖的 JAR。在 `distribution/proxy-native/pom.xml` 的 `dependencies` 加入如下选项之一, -- 在 `distribution/proxy-native/pom.xml` 的 `dependencies` 加入存在 SPI 实现的 JAR - 或第三方依赖的 JAR。示例如下 +(1) 存在 SPI 实现的 JAR +(2) 第三方依赖的 JAR -```xml +示例如下,这些 JAR 应预先置入本地 Maven 仓库或 Maven Central 等远程 Maven 仓库。 +```xml - - com.mysql - mysql-connector-j - 8.1.0 - + + com.mysql + mysql-connector-j + 9.0.0 + ``` -- 通过命令行构建 GraalVM Native Image。 +随后通过命令行构建 GraalVM Native Image。 ```bash ./mvnw -am -pl distribution/proxy-native -T1C -Prelease.native -DskipTests clean package @@ -84,24 +103,21 @@ sdk install java 23-graalce 3. 通过命令行启动 Native Image, 需要带上 4 个参数。 第一个参数为 ShardingSphere Proxy 使用的端口,第二个参数为你编写的包含 `global.yaml` 的 `/conf` 文件夹, 第三个参数为绑定端口的 Address,第四个参数为 Force Start,如果为 true 则保证 ShardingSphere Proxy Native 无论能否连接都能正常启动。 - 假设已存在文件夹`./custom/conf`,示例为 + 假设已存在文件夹`./custom/conf`,示例为, ```bash ./apache-shardingsphere-proxy-native 3307 ./custom/conf "0.0.0.0" false ``` -4. 如果需要构建 Docker Image, 在添加存在 SPI 实现的依赖或第三方依赖后, 在命令行执行如下命令。 +4. 如果需要构建 Docker Image, 在添加存在 SPI 实现的依赖或第三方依赖后, 在命令行执行如下命令, ```shell ./mvnw -am -pl distribution/proxy-native -T1C -Prelease.native,docker.native -DskipTests clean package ``` -- 假设存在包含`global.yaml` 的 `conf` 文件夹为 `./custom/conf`,可通过如下的 `docker-compose.yml` 文件启动 GraalVM Native - Image 对应的 Docker Image。 +假设存在包含`global.yaml` 的 `conf` 文件夹为 `./custom/conf`,可通过如下的 `docker-compose.yml` 文件启动包含 GraalVM Native Image 的 Docker Image。 ```yaml -version: "3.8" - services: apache-shardingsphere-proxy-native: image: apache/shardingsphere-proxy-native:latest @@ -111,25 +127,23 @@ services: - "3307:3307" ``` -- 如果你不对 Git Source 做任何更改, 上文提及的命令将使用 `oraclelinux:9-slim` 作为 Base Docker Image。 - 但如果你希望使用 `busybox:glic`,`gcr.io/distroless/base` 或 `scratch` 等更小体积的 Docker Image 作为 Base Docker - Image,你需要根据 https://www.graalvm.org/jdk23/reference-manual/native-image/guides/build-static-executables/ 的要求, - 做为 `pom.xml`的 `native profile` 添加 `-H:+StaticExecutableWithDynamicLibC` 的 `jvmArgs` 等操作。 - 另请注意,某些第三方依赖将需要在 `Dockerfile` 安装更多系统库,例如 `libdl`。 - 因此请确保根据你的使用情况调整 `distribution/proxy-native` 下的 `pom.xml` 和 `Dockerfile` 的内容。 +如果你不对 Git Source 做任何更改, 上文提及的命令将使用 `oraclelinux:9-slim` 作为 Base Docker Image。 +但如果你希望使用 `busybox:glic`,`gcr.io/distroless/base` 或 `scratch` 等更小体积的 Docker Image 作为 Base Docker +Image,你需要根据 https://www.graalvm.org/jdk23/reference-manual/native-image/guides/build-static-executables/ 的要求, +做为 `pom.xml`的 `native profile` 添加 `-H:+StaticExecutableWithDynamicLibC` 的 `jvmArgs` 等操作。 +另请注意,某些第三方依赖将需要在 `Dockerfile` 安装更多系统库,例如 `libdl`。 +因此请确保根据你的使用情况调整 `distribution/proxy-native` 下的 `pom.xml` 和 `Dockerfile` 的内容。 ## 可观察性 -针对 GraalVM Native Image 形态的 ShardingSphere Proxy,其提供的可观察性的能力与 -[可观察性](/cn/user-manual/shardingsphere-proxy/observability) 并不一致。 +针对 GraalVM Native Image 形态的 ShardingSphere Proxy,其提供的可观察性的能力与[可观察性](/cn/user-manual/shardingsphere-proxy/observability)并不一致。 你可以使用 https://www.graalvm.org/jdk23/tools/ 提供的一系列命令行工具或可视化工具观察 GraalVM Native Image 的内部行为, -并根据其要求使用 VSCode 完成调试工作。如果你正在使用 IntelliJ IDEA 并且希望调试生成的 GraalVM Native Image,你可以关注 -https://blog.jetbrains.com/idea/2022/06/intellij-idea-2022-2-eap-5/#Experimental_GraalVM_Native_Debugger_for_Java -及其后继。如果你使用的不是 Linux,则无法对 GraalVM Native Image 进行 Debug,请关注尚未关闭的 -https://github.com/oracle/graal/issues/5648 。 +并根据其要求使用 VSCode 完成调试工作。如果你正在使用 IntelliJ IDEA 并且希望调试生成的 GraalVM Native Image, +你可以关注 https://blog.jetbrains.com/idea/2022/06/intellij-idea-2022-2-eap-5/#Experimental_GraalVM_Native_Debugger_for_Java 及其后继。 +如果你使用的不是 Linux,则无法对 GraalVM Native Image 进行 Debug,请关注尚未关闭的 https://github.com/oracle/graal/issues/5648 。 -对于使用 `ShardingSphere Agent` 等 Java Agent 的情形, GraalVM 的 `native-image` 组件尚未完全支持在构建 Native -Image 时使用 javaagent,你需要关注尚未关闭的 https://github.com/oracle/graal/issues/1065 。 +对于使用 `ShardingSphere Agent` 等 Java Agent 的情形, GraalVM 的 `native-image` 组件尚未完全支持在构建 Native Image 时使用 javaagent, +你需要关注尚未关闭的 https://github.com/oracle/graal/issues/1065 。 若用户期望在 ShardingSphere Proxy Native 下使用这类 Java Agent,则需要关注 https://github.com/oracle/graal/pull/8077 涉及的变动。 diff --git a/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.en.md b/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.en.md index 2ce594e5f8bac..e6ce44addc189 100644 --- a/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.en.md +++ b/docs/document/content/user-manual/shardingsphere-proxy/startup/graalvm-native-image.en.md @@ -5,140 +5,20 @@ weight = 2 ## 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`. +TODO ## Notice -- ShardingSphere Proxy is not yet ready to integrate with GraalVM Native Image. Proxy's Native Image artifacts are - built nightly at https://github.com/apache/shardingsphere/pkgs/container/shardingsphere-proxy-native . - Assuming there is a `conf` folder containing `global.yaml` as `./custom/conf`, you can test it with the - following `docker-compose.yml` file. - -````yaml -version: "3.8" - -services: - apache-shardingsphere-proxy-native: - image: ghcr.io/apache/shardingsphere-proxy-native:latest - volumes: - - ./custom/conf:/opt/shardingsphere-proxy-native/conf - ports: - - "3307:3307" -```` - -- This section assumes a Linux (amd64, aarch64), MacOS (amd64, aarch64/M1) or Windows (amd64) environment. - -- This section is still subject to the documented content of [GraalVM Native Image](/en/user-manual/shardingsphere-jdbc/graalvm-native-image) on the ShardingSphere JDBC side. +TODO ## Premise -1. Install and configure `GraalVM Community Edition` or a downstream distribution of `GraalVM Community Edition` for -JDK 23 according to https://www.graalvm.org/downloads/. If `SDKMAN!` is used, - -```shell -sdk install java 23-graalce -``` - -2. Install the local toolchain as required by https://www.graalvm.org/jdk23/reference-manual/native-image/#prerequisites. - -3. If you need to build a Docker Image, make sure `docker-ce` is installed. +TODO ## Steps -1. Get Apache ShardingSphere Git Source - -- Get it at the [download page](https://shardingsphere.apache.org/document/current/en/downloads/) - or https://github.com/apache/shardingsphere/tree/master. - -2. 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. - -```bash -./mvnw -am -pl distribution/proxy-native -T1C -Prelease.native -DskipTests 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 - -```xml - - - - com.mysql - mysql-connector-j - 8.1.0 - - -``` - -- Build GraalVM Native Image via command line. - -```bash -./mvnw -am -pl distribution/proxy-native -T1C -Prelease.native -DskipTests clean package -``` - -3. 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 `global.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 - -```bash -./apache-shardingsphere-proxy-native 3307 ./custom/conf "0.0.0.0" false -```` - -4. 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. - -```shell -./mvnw -am -pl distribution/proxy-native -T1C -Prelease.native,docker.native -DskipTests clean package -``` - -- Assuming that there is a `conf` folder containing `global.yaml` as `./custom/conf`, you can start the Docker Image - corresponding to GraalVM Native Image through the following `docker-compose.yml` file. - -```yaml -version: "3.8" - -services: - apache-shardingsphere-proxy-native: - image: apache/shardingsphere-proxy-native:latest - volumes: - - ./custom/conf:/opt/shardingsphere-proxy-native/conf - ports: - - "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/jdk23/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. +TODO ## Observability -ShardingSphere for GraalVM Native Image form Proxy, which provides observability capabilities -with [Observability](/en/user-manual/shardingsphere-proxy/observability) not consistent. - -You can observe GraalVM Native Image using a series of command line tools or visualization tools available -at https://www.graalvm.org/jdk23/tools/, and use VSCode to debug it according to its requirements. -If you are using IntelliJ IDEA and want to debug the generated GraalVM Native Image, You can follow -https://blog.jetbrains.com/idea/2022/06/intellij-idea-2022-2-eap-5/#Experimental_GraalVM_Native_Debugger_for_Java -and its successors. If you are not using Linux, you cannot debug GraalVM Native Image, please pay attention -to https://github.com/oracle/graal/issues/5648 which has not been closed yet. - -For the use of Java Agents such as `ShardingSphere Agent`, GraalVM's `native-image` component does not yet fully support building Native -when using javaagent with Image, you need to pay attention to https://github.com/oracle/graal/issues/1065 which has not yet been closed. - -If users expect to use this type of Java Agent under ShardingSphere Proxy Native, they need to pay attention to the changes involved in https://github.com/oracle/graal/pull/8077 . +TODO diff --git a/test/native/pom.xml b/test/native/pom.xml index 07c1acab77638..b78616dfed5f7 100644 --- a/test/native/pom.xml +++ b/test/native/pom.xml @@ -33,6 +33,12 @@ ${project.version} test + + org.apache.shardingsphere + shardingsphere-proxy-bootstrap + ${project.version} + test + org.apache.shardingsphere shardingsphere-infra-database-testcontainers diff --git a/test/native/src/test/java/org/apache/shardingsphere/test/natived/proxy/commons/ProxyTestingServer.java b/test/native/src/test/java/org/apache/shardingsphere/test/natived/proxy/commons/ProxyTestingServer.java new file mode 100644 index 0000000000000..98959b50b699c --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/test/natived/proxy/commons/ProxyTestingServer.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.test.natived.proxy.commons; + +import lombok.Getter; +import org.apache.curator.test.InstanceSpec; +import org.apache.shardingsphere.proxy.Bootstrap; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.concurrent.CompletableFuture; + +@Getter +public final class ProxyTestingServer { + + private final int proxyPort = InstanceSpec.getRandomPort(); + + private final CompletableFuture completableFuture; + + public ProxyTestingServer(final String configAbsolutePath) { + completableFuture = CompletableFuture.runAsync(() -> { + try { + Bootstrap.main(new String[]{String.valueOf(proxyPort), configAbsolutePath, "0.0.0.0", "false"}); + } catch (final IOException | SQLException ex) { + throw new RuntimeException(ex); + } + }); + } + + /** + * Force close ShardingSphere Proxy. + */ + public void close() { + completableFuture.cancel(true); + } +} diff --git a/test/native/src/test/java/org/apache/shardingsphere/test/natived/proxy/features/ShardingTest.java b/test/native/src/test/java/org/apache/shardingsphere/test/natived/proxy/features/ShardingTest.java new file mode 100644 index 0000000000000..743c3c7b7c153 --- /dev/null +++ b/test/native/src/test/java/org/apache/shardingsphere/test/natived/proxy/features/ShardingTest.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.shardingsphere.test.natived.proxy.features; + +import com.mysql.cj.jdbc.exceptions.CommunicationsException; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import org.apache.shardingsphere.test.natived.jdbc.commons.TestShardingService; +import org.apache.shardingsphere.test.natived.proxy.commons.ProxyTestingServer; +import org.awaitility.Awaitility; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.testcontainers.containers.FixedHostPortGenericContainer; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import javax.sql.DataSource; +import java.nio.file.Paths; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.time.Duration; +import java.util.Properties; + +@SuppressWarnings({"SqlNoDataSourceInspection", "SameParameterValue"}) +@Testcontainers +class ShardingTest { + + private static ProxyTestingServer proxyTestingServer; + + private TestShardingService testShardingService; + + @SuppressWarnings({"resource", "deprecation", "unused"}) + @Container + public static final GenericContainer CONTAINER = new FixedHostPortGenericContainer<>("mysql:9.0.1-oraclelinux9") + .withFixedExposedPort(23306, 3306) + .withEnv("MYSQL_DATABASE", "test") + .withEnv("MYSQL_ROOT_PASSWORD", "yourStrongPassword123!"); + + @BeforeAll + static void beforeAll() throws SQLException { + Awaitility.await().atMost(Duration.ofMinutes(30L)).ignoreExceptionsMatching(e -> e instanceof CommunicationsException).until(() -> { + openConnection("root", "yourStrongPassword123!", "jdbc:mysql://127.0.0.1:" + CONTAINER.getMappedPort(3306) + "/test") + .close(); + return true; + }); + try ( + Connection connection = openConnection("root", "yourStrongPassword123!", "jdbc:mysql://127.0.0.1:" + CONTAINER.getMappedPort(3306) + "/test"); + Statement statement = connection.createStatement()) { + statement.executeUpdate("CREATE DATABASE demo_ds_0"); + statement.executeUpdate("CREATE DATABASE demo_ds_1"); + statement.executeUpdate("CREATE DATABASE demo_ds_2"); + } + String absolutePath = Paths.get("src/test/resources/test-native/yaml/proxy/features").toAbsolutePath().normalize().toString(); + proxyTestingServer = new ProxyTestingServer(absolutePath); + Awaitility.await().atMost(Duration.ofMinutes(30L)).ignoreExceptionsMatching(e -> e instanceof CommunicationsException).until(() -> { + openConnection("root", "root", "jdbc:mysql://127.0.0.1:" + proxyTestingServer.getProxyPort() + "/sharding_db").close(); + return true; + }); + } + + @AfterAll + static void afterAll() { + proxyTestingServer.close(); + } + + @Test + void assertShardingInLocalTransactions() throws SQLException { + HikariConfig config = new HikariConfig(); + config.setDriverClassName("com.mysql.cj.jdbc.Driver"); + config.setJdbcUrl("jdbc:mysql://127.0.0.1:" + proxyTestingServer.getProxyPort() + "/sharding_db"); + config.setUsername("root"); + config.setPassword("root"); + DataSource dataSource = new HikariDataSource(config); + testShardingService = new TestShardingService(dataSource); + initEnvironment(); + testShardingService.processSuccess(); + testShardingService.cleanEnvironment(); + } + + private void initEnvironment() throws SQLException { + testShardingService.getOrderRepository().createTableIfNotExistsInMySQL(); + testShardingService.getOrderItemRepository().createTableIfNotExistsInMySQL(); + testShardingService.getAddressRepository().createTableIfNotExistsInMySQL(); + testShardingService.getOrderRepository().truncateTable(); + testShardingService.getOrderItemRepository().truncateTable(); + testShardingService.getAddressRepository().truncateTable(); + } + + private static Connection openConnection(final String username, final String password, final String jdbcUrl) throws SQLException { + Properties props = new Properties(); + props.setProperty("user", username); + props.setProperty("password", password); + return DriverManager.getConnection(jdbcUrl, props); + } +} diff --git a/test/native/src/test/resources/test-native/yaml/proxy/features/database-sharding.yaml b/test/native/src/test/resources/test-native/yaml/proxy/features/database-sharding.yaml new file mode 100644 index 0000000000000..48bf9af17aaf0 --- /dev/null +++ b/test/native/src/test/resources/test-native/yaml/proxy/features/database-sharding.yaml @@ -0,0 +1,66 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +databaseName: sharding_db +dataSources: + ds_0: + url: jdbc:mysql://127.0.0.1:23306/demo_ds_0 + username: root + password: yourStrongPassword123! + ds_1: + url: jdbc:mysql://127.0.0.1:23306/demo_ds_1 + username: root + password: yourStrongPassword123! + ds_2: + url: jdbc:mysql://127.0.0.1:23306/demo_ds_2 + username: root + password: yourStrongPassword123! +rules: +- !SHARDING + tables: + t_order: + actualDataNodes: ds_$->{0..2}.t_order + keyGenerateStrategy: + column: order_id + keyGeneratorName: snowflake + t_order_item: + actualDataNodes: ds_$->{0..2}.t_order_item + keyGenerateStrategy: + column: order_item_id + keyGeneratorName: snowflake + defaultDatabaseStrategy: + standard: + shardingColumn: user_id + shardingAlgorithmName: inline + shardingAlgorithms: + # `groovy.lang.Closure` related classes are not available on GraalVM Native Image. + # This CLASS_BASE algorithm class is designed to emulate INLINE's `ds_${user_id % 2}`. + # See https://github.com/oracle/graal/issues/5522 . + inline: + type: CLASS_BASED + props: + strategy: STANDARD + algorithmClassName: org.apache.shardingsphere.test.natived.jdbc.commons.algorithm.ClassBasedInlineShardingAlgorithmFixture + keyGenerators: + snowflake: + type: SNOWFLAKE + auditors: + sharding_key_required_auditor: + type: DML_SHARDING_CONDITIONS +- !BROADCAST + tables: + - t_address diff --git a/test/native/src/test/resources/test-native/yaml/proxy/features/global.yaml b/test/native/src/test/resources/test-native/yaml/proxy/features/global.yaml new file mode 100644 index 0000000000000..5572ece5c2787 --- /dev/null +++ b/test/native/src/test/resources/test-native/yaml/proxy/features/global.yaml @@ -0,0 +1,30 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +mode: + type: Standalone + repository: + type: JDBC +authority: + users: + - user: root@% + password: root + privilege: + type: ALL_PERMITTED +props: + sql-show: false + proxy-frontend-database-protocol-type: MySQL