5743 words
29 minutes
Nacos Native Image

Language: English | 简体中文 | 繁體中文 | 日本語

为什么Nacos需要GraalVM?#

Nacos /nɑəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。

GraalVM Native Image 是 Java 在 JDK17 时引入的一个新特性,它可以将 Java 代码提前编译成二进制文件——一个本地可执行文件。一个本地可执行文件只包含运行时所需的代码,即应用程序类、标准库类、语言运行时以及来自 JDK 的静态链接的本地代码,以提高Java应用的启动和运行效率。

随着 SpringBoot 3 的成熟和推广,且能够支持 Java Native Image 运行,越来越多的应用开始以 Native Image 的方式进行启动,Nacos 社区中也涌现出大量需要 Nacos 支持 Native Image 运行的支持需求,例如:#9997#11402 等。

因此 Nacos 社区希望能让 Nacos 的 Java 客户端和服务端,都能够支持 Native Image,以提高 Nacos 的启动速度和运行效率,同时满足社区的需求。

微服务全景图#

技术方案评估#

Nacos 整体模块多、依赖关系复杂,借助 mvn dependency:tree 进行依赖分析是必要的手段之一,在结果中去除测试模块以及与测试范围相关的依赖后,将帮助我们快速定位到需要进行 Spring 和 GraalVM 代码升级的模块。

从 SpringBoot 3.0 开始,SpringBoot 提供了官方的对 GraalVM Native Image 的支持,这意味着不再需要单独引入 spring-native 依赖。同时 SpringBoot 3.x 内置了对 GraalVM Native Image 的支持,通过提供自动配置和优化,使得 SpringBoot 应用程序能够更轻松地编译为原生的二进制文件。

将 Nacos 各模块中的 SpringBoot 依赖从 2.7.18 升级至 3.3.1 版本,一方面是为了更好地支持项目打包编译为 GraalVM Native Image 程序,另一方面是为了能让 Nacos 不断跟进并支持下一个 Spring 大版本功能。

SpringBoot 3升级流程#

对 Nacos 各模块进行 Spring 依赖版本升级,是一个复杂的过程,涉及多个方面的工作,包括依赖管理、代码迁移、测试和验证。在初步版本更新调研中,我们确定了以下需要一同升级的依赖的最终版本:

Archive旧版本新版本Description
java1.817Spring 6/SpringBoot 3 最低支持的 JDK 版本
spring-boot-dependencies2.7.183.3.1SpringBoot 相关的依赖
servlet-api3.06.1.0Servlet 相关的依赖
spring5.3.346.1.10Spring 相关的依赖
spring-security5.7.126.3.1Spring Security 相关的依赖
apache-http-components4.1.55.3.1Apache HTTP Components 相关的依赖
micrometer1.9.171.13.1Micrometer 相关的依赖
maven-pmd-plugin3.83.15.0pmd 代码格式相关的插件
p3c-pmd1.3.02.1.1p3c 代码格式相关的插件
maven-shade-plugin3.2.43.6.0Maven Shade 相关的打包插件
grpc-java1.57.21.65.1grpc 相关的依赖
grpc-util-1.65.1grpc 新版本中拆分出来的 util 模块
grpc-inprocess-1.65.1grpc 新版本中拆分出来的 inprocess 模块
findbugs-maven-plugin3.0.4-因不再支持 JDK 17 被移除
soptbugs-maven-plugin-4.8.6.2在 JDK 17 中替代 findbugs

根据梳理完成的依赖关系图,可以进一步明确与 Spring 相关的依赖,并明确它们之间的上下级关系以及未来的更新顺序:

SpringBoot Upgrade Order

GraalVM适配细节#

与 Java Virtual Machine 相比,Native Image 可以为许多工作类型提供高效、可持续的托管。其中包括微服务、云函数、容器和 Kubernetes。使用 GraalVM Native Image 可以将 Nacos 打包为二进制可执行程序,并期望能在启动性能和运行时性能上取得较大的收益。

Native Image 有多种实现技术,但都各具优势和缺陷,经过比较与筛选,GraalVM 是将 Nacos 升级并支持 Native Image 启动方式的最佳选择。

  • GraalVM,是一个高性能的运行时,提供了多语言支持,并可以将 Java 应用程序编译成原生可执行文件。提供高效的原生编译功能、与现有的 Java 工具和框架具有良好的兼容性、强大的社区和文档支持。
  • Excelsior JET,是一个商业的 Java SE 执行环境和优化编译器,可以将 Java 应用程序编译成原生代码。提供AOT编译以减少启动时间、具有增强的安全性和代码保护、支持多重平台和操作系统。
  • Avian,是一个轻量级的 Java 虚拟机,为嵌入式设备和小型系统而设计,支持将 Java 应用程序编译成原生代码。轻量级,适用于资源受限的设备、支持 AOT 编译、开源项目可灵活定制。
  • LLVM/Clang,主要是用于 C/C++ 编译,但也提供了其他语言的支持,可以通过将 Java 字节码编译成 LLVM IR,生成原生代码。具有强大的编译优化和代码生成能力、支持多种语言、拥有丰富的生态系统和工具链支持。

我们的目标是为了让 nacos-client、nacos-console 都支持 Native Image 的启动方式,最终让上游依赖(如:nacos-spring-context、nacos-spring-context-aop、nacos-spring-samples、spring-cloud-starter-alibaba-nacos-config等)都能够顺利通过 Native Image 打包运行。目前 Nacos 仓库中与 GraalVM Native Image 相关的 ISSUE 如下:

  1. ISSUE#9997 nacos client 支持 spring native:https://github.com/alibaba/nacos/issues/9997
  2. ISSUE#11402 support a native docker image:https://github.com/alibaba/nacos/issues/11402
  3. ISSUE#11790 No serializer found for class com.alibaba.nacos.common.remote.client.RpcClientTlsConfig (native-image run failed):https://github.com/alibaba/nacos/issues/11790
  4. ISSUE#11853 GraalVM support for nacos-client:https://github.com/alibaba/nacos/issues/11853
  5. ISSUE#11860 Update reflect-config.json:https://github.com/alibaba/nacos/pull/11860
  6. ISSUE#11861 [Graalvm] Use spring boot maven plugin generation hints files appeared warning info:https://github.com/alibaba/nacos/issues/11861
  7. ISSUE#11902 GraalVM Reachability Metadata Lose:https://github.com/alibaba/nacos/issues/11902
  8. ISSUE#12028 [Summer 2024] Nacos 支持 Java native-image 运行方式:https://github.com/alibaba/nacos/issues/12028

截至目前,Nacos Client 中已经完成了部分对 Native Image 启动方式的反射元数据采样工作(如:Merge了ISSUE#11860)但这些操作目前看来已经取得了一些成效,但并没有向上支持到 nacos-console 中,也没有解决 SpringBoot 3 带来的新的 Native 技术问题,这些问题都将在该次工作中实现。

GraalVM Upgrade Order

评估与性能测试#

NOTE

性能报告中,所有功能在 Native 与 Java 平台上表现出的内存占用的差距与启动功能的内存占用、线程数差距相当,因而不统计其运行期间的内存占用和创建的线程数。

单机模式#

压测环境:

  • 操作系统:10c6g,macos aarch64,apple silicon
  • 数据库:localhost MySQL 8.0
  • Nacos:2.5.0-snapshot.springboot3,2.5.0-snapshot.native
模块功能2.5.0-SNAPSHOT with Spring Boot 32.5.0-SNAPSHOT Native性能对比
启动耗时: 3800ms
CPU: 33.5%
内存: 470MB
线程: 300
耗时: 48ms
CPU: 33.1%
内存: 190MB
线程: 298
耗时: ↓98.73%
CPU: -
内存: ↓59.57%
线程: -
config配置查询CPU: 35.62%
QPS: 12050
CPU: 29.94%
QPS: 12035
CPU: ↓15.95%
配置发布CPU: 52.41%
QPS: 6733
CPU: 54.69%
QPS: 6784
CPU: ↑4.35%
naming服务注册CPU: 25.64%
QPS: 7328
CPU: 29.43%
QPS: 7584
CPU: ↑14.78%
服务查询CPU: 33.59%
QPS: 7370
CPU: 27.8%
QPS: 7380
CPU: ↓17.24%

集群模式#

压测环境:

  • 集群环境:2核4G 3 节点部署,ECS 规格 ecs.e-c1m2.large。
  • 负载均衡:slb.s2.small。
  • 数据库:MySQL.x2.xlarge.2c MySQL5.7。
  • Nacos:2.5.0-snapshot.springboot3,2.5.0-snapshot.native。
模块功能2.5.0-SNAPSHOT with Spring Boot 32.5.0-SNAPSHOT Native性能对比
启动耗时: 12800ms
CPU: 33.52%
耗时: 45ms
CPU: 46%
耗时: ↓99.65%
CPU: ↑37.23%
config配置查询CPU: 82%
QPS: 9981.96
CPU: 93.3%
QPS: 9980.2
CPU: ↑13.78%
配置发布CPU: 73%
QPS: 802.18
CPU: 81.6%
QPS: 796.37
CPU: ↑11.78%
naming服务注册CPU: 84.6%
TPS: 6986.14
CPU: 83.3%
TPS: 6982.12
CPU: ↓1.53%
服务查询CPU: 70.6%
QPS: 8991
CPU: 83%
QPS: 8982
CPU: ↑17.56%
变更发布CPU: 78.3%
TPS: 1197.67
CPU: 95.31%
TPS: 1192
CPU: ↑21.72%

总结#

性能报告中,所有功能在 Native 与 Java 平台上表现出的内存占用的差距与启动功能的内存占用、线程数差距相当,因而不统计其运行期间的内存占用和创建的线程数。

如何构建Nacos Native?#

通过Maven手动构建#

如果你不希望配置复杂的 GraalVM 环境、补齐缺失的 glic 相关的库,只希望快速构建一个 Nacos Native 那么你应该选择使用 Docker 来自动构建。在使用 Maven 构建开始前,你需要确保你的本地操作系统必须满足 GraalVM 能编译的基本环境:

  1. 你的操作系统必须安装 Oracle GraalVM JDK 17.0.12+8.1,且必须让环境变量 GRAALVM_HOMEJAVA_HOME 指向 GraalVM 的目录。
  2. 确保你的操作系统是完全基于 GNU 的,而不是 MUSL 或其他。
  3. 确保你的 Unix 类型的操作系统中装有如下的基本库:bzip2-devel, ed, gcc, gcc-c++, gcc-gfortran, gzip, file, fontconfig, less, libcurl-devel, make, openssl, openssl-devel, readline-devel, tar, glibc-langpack-en, vi, which, xz-devel, zlib-devel, findutils, glibc-static, libstdc++, libstdc++-devel, libstdc++-static, zlib-static 。
  4. 确保你的计算机中安装有 9.0 及以上版本的 Maven。
  5. 如果你不希望编译构建时间太长,推荐你在多核且频率较高的 CPU 上进行改工作。

这里以符合上述条件的 macOS(Apple Silicon) 操作系统作为演示环境。将仓库 git@github.com:alibaba/nacos.git 克隆至本地,并按照如下的步骤来通过 Maven 构建 Nacos Native:

  1. 进入到你的 Nacos 目录并切换至分支 summer-ospp#12028git checkout summer-ospp#12028

  2. 使用 Maven 指令进行 installmvn clean install -DskipTests=true -Pnative -Pnative-osx-arm64 -Prelease-native

    • 如果你正在使用其他版本的操作系统或环境请参考如下的表格选择你需要的 Profile 并替换参数中的 -Pnative-osx-arm64 进行构建。

      OS FamilyArchProfile
      Linuxaarch64native-linux-aarch64
      Linuxppc64lenative-linux-ppc64le
      Linuxs390xnative-linux-s390x
      Linuxx86native-linux32
      Linuxx64native-linux64
      OSXarm64native-osx-arm64
      OSXx86_64native-osx-x86_64
      Windowsx64native-win64
  3. 等待你的 Maven 完成 Nacos Native Image 的构建工作,通常这需要 10 分钟左右(具体时间需要依据你的 CPU 性能)。若构建过程中出现了异常欢迎提供 Issue 至 Nacos 仓库。

  4. 构建完成后相关文件会被存放在 distribution/target 文件夹下,如果你希望自己封装这个执行包那么请按照以下操作系统对应的最终构建文件表格从 console/target 文件夹中拷贝出来:

    OSRelated Files
    windowsnacos-server, libinstrument.dll
    unixnacos-server, libinstrument.so
    macosnacos-server

若你的 Maven 在最后输出了如下的日志,则表明你的 Nacos Native 构建成功。

[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary for Alibaba NACOS 2.5.0-SNAPSHOT 2.5.0-SNAPSHOT:
[INFO] 
[INFO] Alibaba NACOS 2.5.0-SNAPSHOT ....................... SUCCESS [02:08 min]
...
[INFO] nacos-console 2.5.0-SNAPSHOT ....................... SUCCESS [06:34 min]
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  11:12 min
[INFO] Finished at: 2024-10-30T09:08:11Z
[INFO] ------------------------------------------------------------------------
Build successful.
Copying build artifacts to /opt/output

通过Docker自动构建#

使用 Docker 来构建你的 Nacos Native Image 是一个更方便的选择,即便这还是会占用你的绝大部分 CPU。我们按照 Oracle GraalVM Native Image 构建环境标准搭建了一套完备的 Docker 容器,借助于容器你不再需要单独配置臃肿而复杂的 GraalVM Unix 环境,你还可以自定义这个 Dockerfile 来选择其他经过修改的 Nacos Native 的 Git 仓库进行编译,同时这个容器还会自动将构建完成的程序全部打包映射到你指定的希望获取构建结果的目录中,一切都由你自己来决定。

你可以直接拉取 Docker Hub (预计于 2025 年晚些时候推出) 中的官方镜像或 Nacos Docker 仓库中的标准代码进行使用,同时这里会直接给出 Dockerfile 与构建脚本的源代码,以供任何开发者进行参考:

# Copyright 1999-2024 Alibaba Group Holding Ltd.
# Licensed 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.
# 
# 构建镜像: docker build -f Dockerfile.builder -t nacos-native-builder:latest .
# 运行镜像: docker run -v /local/output:/opt/output --name nacos-native-builder nacos-native-builder:latest

ARG BASE_IMAGE=container-registry.oracle.com/os/oraclelinux:8-slim

FROM ${BASE_IMAGE}

LABEL maintainer="Moritz Clifford <me@biu.kim>"

ENV PS1="nacos-native-builder>" \
    GRAALVM_HOME="/opt/graalvm-jdk-17.0.12+8.1" \
    JAVA_HOME="/opt/graalvm-jdk-17.0.12+8.1" \
    PATH="/opt/graalvm-jdk-17.0.12+8.1/bin:$PATH"

RUN microdnf update -y oraclelinux-release-el8 \
    && microdnf --enablerepo ol8_codeready_builder install bzip2-devel ed gcc gcc-c++ gcc-gfortran gzip file fontconfig less libcurl-devel make openssl openssl-devel readline-devel tar glibc-langpack-en \
    vi which xz-devel zlib-devel findutils glibc-static libstdc++ libstdc++-devel libstdc++-static zlib-static wget git \
    && microdnf clean all

WORKDIR /opt

# 设置 GraalVM
RUN wget https://download.oracle.com/graalvm/17/latest/graalvm-jdk-17_linux-x64_bin.tar.gz -O graalvm.tar.gz && \
    mkdir -p /opt && \
    tar -xzf graalvm.tar.gz -C /opt && \
    rm graalvm.tar.gz && \
    ln -s /opt/graalvm-jdk-${GRAALVM_VERSION}/bin/java /usr/bin/java && \
    gu install native-image

# 设置 Maven 3.9
RUN wget https://downloads.apache.org/maven/maven-3/3.9.5/binaries/apache-maven-3.9.5-bin.tar.gz -O maven.tar.gz && \
    tar -xzf maven.tar.gz -C /opt && \
    rm maven.tar.gz && \
    ln -s /opt/apache-maven-3.9.5/bin/mvn /usr/bin/mvn

RUN git clone https://github.com/alibaba/nacos.git && \
    cd nacos && \
    git checkout summer-ospp#12028

ADD bin/build.sh /opt/build.sh
ADD etc/settings.xml /root/.m2/settings.xml
RUN chmod +x /opt/build.sh

ENTRYPOINT ["sh","/opt/build.sh"]

在这个 Dockerfile 中你可以指定任何配置文件,包括:目标仓库、Maven 配置、构建脚本、Docker Volume 等,理论上这个容器将具备构建任何 GraalVM Native Image 的能力,但这里仍然以 Nacos 为例给出一个构建脚本(build.sh)的示例代码:

#!/bin/bash
# Copyright 1999-2024 Alibaba Group Holding Ltd.
# Licensed 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.
set -x

if [ "$(pwd)" != "/opt/nacos" ]; then
  echo "Not in /opt/nacos, switching to /opt/nacos"
  cd /opt/nacos || exit 1
fi

echo "Refreshing Maven and applying settings.xml..."
mvn clean --settings /root/.m2/settings.xml

OUTPUT_DIR="/opt/output"
mkdir -p "$OUTPUT_DIR"
echo "Output directory: $OUTPUT_DIR"

# 自动拉取git分支进行更新
REMOTE_REPO="summer-ospp#12028"
git fetch origin "$REMOTE_REPO"
LOCAL=$(git rev-parse HEAD)
REMOTE=$(git rev-parse origin/"$REMOTE_REPO")

if [ "$LOCAL" != "$REMOTE" ]; then
  echo "Local branch is behind the remote branch. Pulling latest changes..."
  git pull origin "$REMOTE_REPO"
else
  echo "Local branch is up to date with the remote branch."
fi

# 使用Maven进行install
echo "Building nacos native..."
mvn clean install -DskipTests=true -Paliyun-maven -Pnative -Pnative-linux64

# 将构建完成的文件拷贝到映射卷
if [ $? -eq 0 ]; then
  echo "Build successful."
  if [ -f "/opt/nacos/console/target/nacos-server" ] && [ -f "/opt/nacos/console/target/libinstrument.so" ]; then
    echo "Copying build artifacts to $OUTPUT_DIR"
    cp /opt/nacos/console/target/nacos-server "$OUTPUT_DIR"
    cp /opt/nacos/console/target/nacos-server.debug "$OUTPUT_DIR"
    cp /opt/nacos/console/target/libinstrument.so "$OUTPUT_DIR"
  else
    echo "Build artifacts not found."
  fi
else
  echo "Build failed."
fi

exec /bin/bash

运行并测试Nacos Native#

运行并测试构建完成的 Nacos Native 程序对于后续的使用过程来说是极为重要的一步。接下来将以最新版本的 debian 操作系统为演示环境,介绍如何启动单机模式、集群模式的 Nacos Native。截至目前为止 Nacos Native 无法完全支持 Derby 内置数据库模式,因此在测试时你必须确保搭建了一个完整的能够供 Nacos 使用的 PostgreSQL 或其他类型的数据库。

单机模式#

Nacos Native Standalone 的启动方法与 Java 版本的启动方法几乎没有太大的差异,除了一些属于 JVM 的优化参数不可用之外(GraalVM 的工作原理与 JVM 并不相同),适用于 Nacos 本身的参数依然能起作用。在 Windows 平台上你可以直接双击你的 nacos-server.exe 文件直接启动。同时,在这里给出 Debian 下的一个 bash 启动脚本用作参考。

#!/bin/bash
set -x

if [ "$(pwd)" != "/opt/nacos" ]; then
  echo "Not in /opt/nacos, switching to /opt/nacos"
  cd /opt/nacos || exit 1
fi

# 定义参数
export SERVER="nacos-server"
export BASE_DIR="/opt/nacos"
export NACOS_HOME="${BASE_DIR}/home/"
export APP_DIR="${BASE_DIR}/application"
export LOGS_DIR="${APP_DIR}/logs"
export CUSTOM_DIR="file:${APP_DIR}/custom/"

# 创建文件夹
mkdir -p "${NACOS_HOME}"
mkdir -p "${APP_DIR}/logs"
mkdir -p "${APP_DIR}/custom"

chmod -R +x "${BASE_DIR}"

APP_OPT="${APP_OPT} -Dnacos.standalone=true -Dnacos.home=${NACOS_HOME}"

if [ -f "${APP_DIR}/custom/application.properties" ]; then
  echo "Using custom application.properties."
  APP_OPT="${APP_OPT} --spring.config.additional-location=${CUSTOM_DIR}"
fi

# 通过nohup启动Nacos
echo "nacos native is starting. check the ${LOGS_DIR}/start.out"

nohup ./${SERVER} ${APP_OPT} nacos.nacos >> ${LOGS_DIR}/start.out 2>&1 &
NACOS_PID=$!

wait $NACOS_PID
EXIT_CODE=$?

if [ $EXIT_CODE -ne 0 ]; then
  echo "Nacos process exited with code $EXIT_CODE, stopping container..."
  exit $EXIT_CODE
fi

启动脚本中的 Nacos 参数你可以直接参考Nacos官网中的参数解释,通过命令运行这个启动脚本(或将其挂载到守护线程保障持续运行)后若你的控制台输出了与下面类似的日志则表明你的 Nacos Native 启动成功。

         ,--.
       ,--.'|
   ,--,:  : |                                           Nacos 
,`--.'`|  ' :                       ,---.               Running in stand alone mode, All function modules
|   :  :  | |                      '   ,'\   .--.--.    Port: 8848
:   |   \ | :  ,--.--.     ,---.  /   /   | /  /    '   Pid: 12
|   : '  '; | /       \   /     \.   ; ,. :|  :  /`./   Console: http://172.17.0.2:8848/nacos/index.html
'   ' ;.    ;.--.  .-. | /    / ''   | |: :|  :  ;_
|   | | \   | \__\/: . ..    ' / '   | .; : \  \    `.      https://nacos.io
'   : |  ; .' ," .--.; |'   ; :__|   :    |  `----.   \
|   | '`--'  /  /  ,.  |'   | '.'|\   \  /  /  /`--'  /
'   : |     ;  :   .'   \   :    : `----'  '--'.     /
;   |.'     |  ,     .-./\   \  /            `--'---'
'---'        `--`---'     `----'

2024-09-19T03:25:54.202Z  INFO 12 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port 8848 (http)
2024-09-19T03:25:54.205Z  INFO 12 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 37 ms
2024-09-19T03:25:55.504Z  WARN 12 --- [           main] r$InitializeUserDetailsManagerConfigurer : Global AuthenticationManager configured with an AuthenticationProvider bean. UserDetailsService beans will not be used for username/password login. Consider removing the AuthenticationProvider bean. Alternatively, consider using the UserDetailsService in a manually instantiated DaoAuthenticationProvider.
2024-09-19T03:25:55.535Z  INFO 12 --- [           main] o.s.b.a.w.s.WelcomePageHandlerMapping    : Adding welcome page: class path resource [static/index.html]
2024-09-19T03:25:55.643Z  INFO 12 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 1 endpoint beneath base path '/actuator'
2024-09-19T03:25:55.651Z  WARN 12 --- [           main] o.s.s.c.a.web.builders.WebSecurity       : You are asking Spring Security to ignore Deferred [Mvc [pattern='/**'], Ant [pattern='/**']]. This is not recommended -- please use permitAll via HttpSecurity#authorizeHttpRequests instead.
2024-09-19T03:25:55.651Z  WARN 12 --- [           main] o.s.s.c.a.web.builders.WebSecurity       : You are asking Spring Security to ignore Deferred [Mvc [pattern='/prometheus'], Ant [pattern='/prometheus']]. This is not recommended -- please use permitAll via HttpSecurity#authorizeHttpRequests instead.
2024-09-19T03:25:55.652Z  WARN 12 --- [           main] o.s.s.c.a.web.builders.WebSecurity       : You are asking Spring Security to ignore Deferred [Mvc [pattern='/prometheus/namespaceId/{namespaceId}'], Ant [pattern='/prometheus/namespaceId/{namespaceId}']]. This is not recommended -- please use permitAll via HttpSecurity#authorizeHttpRequests instead.
2024-09-19T03:25:55.652Z  WARN 12 --- [           main] o.s.s.c.a.web.builders.WebSecurity       : You are asking Spring Security to ignore Deferred [Mvc [pattern='/prometheus/namespaceId/{namespaceId}/service/{service}'], Ant [pattern='/prometheus/namespaceId/{namespaceId}/service/{service}']]. This is not recommended -- please use permitAll via HttpSecurity#authorizeHttpRequests instead.
2024-09-19T03:25:55.665Z  INFO 12 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port 8848 (http) with context path '/nacos'
2024-09-19T03:25:55.667Z  INFO 12 --- [           main] c.a.n.c.l.StartingApplicationListener    : Nacos started successfully in stand alone mode. use external storage
2024-09-19T03:26:21.080Z  INFO 12 --- [nio-8848-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2024-09-19T03:26:21.082Z  INFO 12 --- [nio-8848-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 1 ms

Nacos Native Standalone 通常只需要 100 毫秒以内的启动时间,相较于 Nacos SpringBoot 2 的 15 秒启动时间来说,这是一个巨大的提升。

集群模式#

启动 Nacos Native Cluster 非常容易,只需要按照 Standalone 的启动方法进行一些修改即可。让我们以 3 个节点的 Nacos Native 主机(每台主机按照 2H2G 50G 进行配置)并设置为 Hostname 模式为例来启动一个集群,在 cluster.conf 中配置好每个节点的 IP 地址。

nacos1:8848
nacos2:8848
nacos3:8848

同时,这里给出一个简单的 bash 脚本来帮助你启动每台 Nacos Native Cluster 服务器上的 Nacos 程序。

#!/bin/bash
set -x
export MEMBER_LIST=""
export SERVER="${BASE_DIR}/nacos-server"
export CUSTOM_SEARCH_LOCATIONS="file:${BASE_DIR}/conf/"
function print_servers() {
  echo "" >"$CLUSTER_CONF"
  for server in ${NACOS_SERVERS}; do
    echo "$server" >>"$CLUSTER_CONF"
  done
}

# 创建文件夹
chmod -R +x "${BASE_DIR}"

print_servers
APP_OPT="${APP_OPT} -Dnacos.home=${BASE_DIR}"
APP_OPT="${APP_OPT} -Dnacos.member.list=${MEMBER_LIST}"
APP_OPT="${APP_OPT} --spring.config.additional-location=${CUSTOM_SEARCH_LOCATIONS}"

if [[ "${NACOS_START_MODE}" == "standalone" ]]; then
  APP_OPT="${APP_OPT} -Dnacos.standalone=true"
fi

if [[ ! -z "${NACOS_AUTH_ENABLE}" ]]; then
  APP_OPT="${APP_OPT} -Dnacos.core.auth.enabled=${NACOS_AUTH_ENABLE}"
fi

if [[ "${PREFER_HOST_MODE}" == "hostname" ]]; then
  APP_OPT="${APP_OPT} -Dnacos.preferHostnameOverIp=true"
fi

# 启动Nacos
echo "Nacos native is now starting with ${NACOS_START_MODE} mode"
exec ${SERVER} ${APP_OPT}

你可以利用 Docker Compose 或 Oracle VirtualBox 等平台构建这个集群服务,现在让我们启动这 3 台服务器上的 Nacos Native,当每台服务器的终端输出了如下的日志,则表明你的 Nacos 集群启动成功。

         ,--.
       ,--.'|
   ,--,:  : |                                           Nacos 
,`--.'`|  ' :                       ,---.               Running in cluster mode, All function modules
|   :  :  | |                      '   ,'\   .--.--.    Port: 8848
:   |   \ | :  ,--.--.     ,---.  /   /   | /  /    '   Pid: 1
|   : '  '; | /       \   /     \.   ; ,. :|  :  /`./   Console: http://nacos1:8848/nacos/index.html
'   ' ;.    ;.--.  .-. | /    / ''   | |: :|  :  ;_
|   | | \   | \__\/: . ..    ' / '   | .; : \  \    `.      https://nacos.io
'   : |  ; .' ," .--.; |'   ; :__|   :    |  `----.   \
|   | '`--'  /  /  ,.  |'   | '.'|\   \  /  /  /`--'  /
'   : |     ;  :   .'   \   :    : `----'  '--'.     /
;   |.'     |  ,     .-./\   \  /            `--'---'
'---'        `--`---'     `----'

2024-09-20T13:35:03.946+08:00  INFO 1 --- [            main] c.a.n.c.l.StartingApplicationListener    : The server IP list of Nacos is [nacos1:8848, nacos2:8848, nacos3:8848]
2024-09-20T13:35:04.982+08:00  INFO 1 --- [nacos-starting.0] c.a.n.c.l.StartingApplicationListener    : Nacos is starting...
2024-09-20T13:35:05.846+08:00  INFO 1 --- [            main] c.a.n.c.l.StartingApplicationListener    : Nacos started successfully in cluster mode. use external storage

即便 Nacos Native Cluster 节点数达到 15 或以上时,他们的启动时间仍然能保持在 100 毫秒以内,这对于 Nacos SpringBoot 2 来说是一个惊人的提升。

Nacos快速开始#

NOTE
  • 快速开始旨在帮助您快速上手安装、部署及入门使用Nacos,本快速开始所生产出的Nacos服务为单机模式未开启鉴权,建议仅在测试中使用,若在实际生产环境中部署,请部署集群模式开启鉴权,以避免存在稳定性和安全性的风险。
  • Nacos定义为一个IDC内部应用组件,并非面向公网环境的产品,建议在内部隔离网络环境中部署,强烈不建议部署在公共网络环境。

这个快速开始手册是帮忙您快速在您的电脑上,下载、安装并使用 Nacos。

环境需求#

WARNING

如果期望将 Nacos Native 构建在基于 Unix 的操作系统上,那么你必须确保你的操作系统是完全基于 GNU 而进行开发的(而不是 Musl 或其他框架)。

Nacos Native 是 Nacos 源码基于 GraalVM 打包而成,其运行不再依赖系统中单独的 JDK 程序。Nacos Native 目前提供了 Linux(GNU)、MacOS 三类操作系统所对应的可执行程序,当前 Nacos Native 对应的 Java Nacos 版本为 2.5.0,可执行程序可以在对应的 release 页面下进行下载。推荐使用完备(包含完备的 libstdc++ 库)的 64bit 的操作系统来运行 Nacos Native。

下载安装包#

在对应页面下载得到程序包后进行解压,解压后检视文件是否完备:

  1. 在 Linux 操作系统中应当包含 nacos-server 二进制程序、libinstrument.so 链接文件与相关其他配置。
  2. 在 MacOS 操作系统中应当包含 nacos-server 二进制程序与相关其他配置。

对于其他操作系统未发布的 Nacos Native 版本,您可以选择在该操作系统上手动进行源码编译得到 Nacos Native 二进制程序包。

启动服务器#

Nacos Native 的运行建议至少在 1C2G 60G 的机器配置下运行。对于 Linux/Unix/Mac 操作系统,启动命令为:

# standalone 代表着单机模式运行,非集群模式
sh startup.sh -m standalone

若要启动 Nacos Native 集群,则需要在相应的 conf 文件夹位置下包含对应的 cluster.conf 文件,该步骤与 Java Nacos 保持一致,在启动 Nacos Native 集群后会自动扫描并获取集群 IP。

关闭服务器#

对于 Linux/Unix/Mac 操作系统,关闭命令为:

sh shutdown.sh

日志检视#

以 Linux/Unix 操作系统为例,Nacos Native 的运行日志会被记录在 /root/nacos/logs 目录中,其日志结构与 Java Nacos 保持一致。

参与Nacos Native贡献#

非常欢迎每一位开发者的贡献和加入,无论是微不足道的清理或大的新功能。Nacos 社区非常重视文档、与其他项目的集成,并欣然接受这些方面的改进。如果你希望为 Nacos Native Image 贡献代码,请先参考《贡献规约》后再参考本文的 Native Image 方面的规约进行贡献。关于 Nacos Native 的贡献,你需要明确以下几点:

  1. 与 GraalVM initialize-at-build-time 相关的类你必须将其添加到 console/pom.xmlnative-maven-plugin 插件的 buildArgs 下,并保证参数的结构不被破坏。
  2. 不与 SpringBoot Aot 相关的元数据,应当作为 GraalVM 的 initialize-at-run-time 参数,添加到console/pom.xmlnative-maven-plugin插件的 buildArgs 下,同时添加到 src/main/resources/META-INF/native-image/com.alibaba.nacos/nacos-console 文件夹中对应的元数据文件中,并保证参数的结构不被破坏。
  3. 与 SpringBoot Aot 直接相关的元数据,应当添加到 com.alibaba.nacos.console.aot.NacosRuntimeHints 类中的合适位置,并保证参数的结构不被破坏。
  4. 若你正在添加的元数据需要对 GraalVM 环境、Java 环境进行分开操作,那么请将其实现逻辑添加至 com.alibaba.nacos.console.aot.AotConfiguration 类中。

相关工程#

alibaba
/
nacos
Waiting for api.github.com...
0K
0K
No License
Waiting...

翻译贡献#

Nacos Native Image
https://biu.kim/posts/nacos/zh-cn/
Author
Moritz Arena
Published at
2024-10-31