feature: add GraalVM native image build support for seata-server - #8162
Open
xuxiaowei-com-cn wants to merge 127 commits into
Open
feature: add GraalVM native image build support for seata-server#8162xuxiaowei-com-cn wants to merge 127 commits into
xuxiaowei-com-cn wants to merge 127 commits into
Conversation
- Add native-maven-plugin version management in build/pom.xml - Add native and nativeTest profiles in server/pom.xml for GraalVM AOT compilation - Add Makefile targets: package-server-native, package-server-native-pre, package-server-native-only
…5.5.0 in native workflow 1. actions/setup-java@v3.12.0: No supported distribution was found for input graalvm 2. Node.js 20 is deprecated. The following actions target Node.js 20 but are being forced to run on Node.js 24: actions/checkout@v3, actions/setup-java@v3.12.0. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
…ing" This reverts commit 08341c1.
- Add ubuntu-latest-arm to native build matrix alongside ubuntu-latest - Update step names to include OS identifier for clarity - Add -am flag to Makefile package-server-native-pre target to also build server module dependencies
…runners Add matrix.os to concurrency group and cancel-in-progress to avoid ubuntu-latest and ubuntu-latest-arm builds cancelling each other.
…rent OS runners" This reverts commit d5fbf67.
Comment out concurrency group and cancel-in-progress to avoid interference between multiple native build workflow runs.
This reverts commit 0e8c990.
Replace ubuntu-latest with ubuntu-24.04 for more reproducible builds.
Add macos-26-intel, macos-26-large, and windows-latest to the native build CI matrix alongside existing Linux runners.
…ve profiles Add --initialize-at-run-time=io.netty.channel.kqueue to both native and nativeTest profiles to fix GraalVM native image issues related to Netty's kqueue transport on non-macOS platforms.
- Add OS/arch-specific Maven profiles (linux-amd64, linux-arm64, darwin-amd64,
darwin-arm64, windows-amd64) to set native.platform property
- Configure native-maven-plugin imageName to
seata-server-{version}-{platform}, e.g. seata-server-2.8.0-SNAPSHOT-linux-amd64
- Add upload-artifact step to native CI workflow
- Exclude .jar files from uploads to only ship the native binary
…server $GRAALVM_HOME/bin/java -agentlib:native-image-agent=config-output-dir=./target/native-image-config -jar ./server/target/seata-server.jar
- reflect-config.json: rename 'type' to 'name' key per GraalVM 25 schema - reflect-config.json: remove deprecated 'jniAccessible' attribute - reflect-config.json: extract proxy entries to separate proxy-config.json - resource-config.json: convert array to object format with 'resources.includes' - resource-config.json: rename 'glob' to 'pattern' key - server/pom.xml: add --initialize-at-build-time=com.alibaba.fastjson2
…er directory for GraalVM 25 compatibility
Add Spotless Jackson JSON formatter in pom.xml and reformat proxy-config.json, reflect-config.json, resource-config.json
Add constructor and method entries for Apollo config classes (ConfigPropertySourceFactory, PlaceholderHelper, SpringValueRegistry), Iterable.iterator(), Iterator.hasNext()/next(), and comprehensive StringBuilder methods to ensure proper reflection access in native image.
…H_DIR logic Remove the if/else branch that switched between resource and file includes based on LOG_BASH_DIR property. Unify to always use resource includes. Also remove conditional appender-refs for logstash, kafka, and metric appenders, replacing them with comments. logback-spring.xml: remove <if> conditionals that require janino runtime compilation (not supported in native image)
… and fix formatting - Add Apollo Guice FastClassByGuice entries (ConfigPropertySourceFactory, PlaceholderHelper, SpringValueRegistry) with GUICE$INVOKERS fields to reachability-metadata.json for GraalVM native image support - Include test-native-server profile in Makefile spotless-apply target - Remove trailing blank line in HealthRestController.java
…inates subdirectory Move reachability-metadata.json from: META-INF/native-image/org.apache.seata/seata-server/ to: META-INF/native-image/ This simplifies the directory structure and aligns with GraalVM's flat metadata lookup convention. All references are updated: - pom.xml: Spotless JSON include pattern simplified - Makefile: spotless-apply includes test-native-metadata-merge profile - ExecuteMergeNativeImageMetadataTests: target path updated
… separate native config Introduce logback-spring-jvm.xml (with <if> conditional and LOG_BASH_DIR support) for the JVM distribution, while keeping the default logback-spring.xml simplified for GraalVM native image compatibility. - Add logback-spring-jvm.xml: restored <if> conditional that loads appender includes from either classpath or external conf directory based on LOG_BASH_DIR, plus conditional logstash/kafka/metric appender support (requires Janino runtime compilation) - Update logback-spring.xml: add comment documenting the JVM/native split and distribution packaging behavior - Update distribution/release-seata.xml: use logback-spring-jvm.xml as source, renamed to logback-spring.xml in conf/ so the existing launch script picks up the JVM variant with external conf support This fixes the JVM behavior regression where modifications to external conf/logback/console-appender.xml and conf/logback/file-appender.xml were ignored after the GraalVM optimization removed conditional logic.
…native image Add NacosPayloadRegistryInitializer to pre-populate PayloadRegistry since Reflections classpath scanning is unavailable in GraalVM native images, preventing 'Unknown payload type' errors during Nacos gRPC communication. Introduce NACOS_MODE_ENV macro and separate Makefile targets: - run-server-native-file-metadata / run-server-native-file-mode - run-server-native-nacos-metadata / run-server-native-nacos-mode Enrich reachability-metadata.json with Nacos gRPC, Netty, protobuf, and SPI service entries required for native image compilation.
…-GraalVM # Conflicts: # Makefile # changes/en-us/2.x.md # changes/zh-cn/2.x.md # pom.xml # server/pom.xml # test-suite/test-native-metadata-merge/src/test/java/org/apache/seata/metadata/ExecuteMergeNativeImageMetadataTests.java
…ignore Delete the standalone MergeNativeImageConfig.java tool that was used to merge reachability-metadata.json into native-image config files. Add __pycache__/ entry to .gitignore for Python cache directories.
2 tasks
…rgets to Makefile
… mode in Makefile - Rename run-server-native-jar to run-server-native-file-jar and add explicit SEATA_CONFIG_TYPE/REGISTRY_TYPE/STORE_TYPE=file env vars - Add run-server-native-nacos-jar target with NACOS_MODE_ENV macro for config(nacos)+registry(nacos)+store(file) mode - Add install-server-native and package-server-native targets for building seata-server GraalVM native image - Add run-server-native-file and run-server-native-nacos targets for running the compiled native image in file and nacos modes - Add NACOS_MODE_ENV macro to consolidate Nacos config+registry env vars - Add NACOS_NAMESPACE, NACOS_GROUP, NACOS_DATAID, NACOS_USERNAME, NACOS_PASSWORD variables with sensible defaults - Change NATIVE_PLATFORM to conditional assignment (?=) for external override
…PayloadRegistryInitializer
Normalize FastClassByGuice dynamic numeric suffixes during merge key matching so entries with different hash suffixes are recognized as the same logical element. Target values are preserved to avoid meaningless metadata churn from transient suffix changes. - Add normalizeType() to strip variable numeric suffix from FastClassByGuice type names for stable identity keys - Remove 9 accumulated duplicate FastClassByGuice entries from reachability-metadata.json (3 base classes x 4 versions -> 3) - Add tests for deduplication and Spring CGLIB non-interference
Move JAR cleanup from upload/verify steps into the compile step, removing duplicated rm commands and upload-artifact exclude rules.
…Java FFM API - Add NativeLibraryUtil for Nacos shaded Netty native library loading - Add java.lang.foreign types (Linker, SymbolLookup, ValueLayout, etc.) - Add Foreign Function & Memory API downcalls metadata - Add Netty epoll native .so resources for Nacos shaded gRPC
- When an object with a recognized key is appended, register the key so subsequent source elements with the same key merge instead of duplicating. - For objects without a recognizable key (e.g. foreign.downcalls entries), use containsNode to skip already-present elements.
… native image metadata
- Rename build job to 'build & test (file)' to reflect file config mode - Add new 'test (nacos)' job to verify native binary with nacos config mode - Nacos job runs on ubuntu-24.04 / ubuntu-24.04-arm with Docker MySQL
Replace the extensive per-module path list with a single targeted path 'server/src/main/resources/META-INF/native-image/**' since that directory is the key trigger for native image build changes.
The nacos job downloads the native binary artifact from the build job, so it must depend on build completing first.
…nacos job - Remove needs: build dependency so nacos job can start independently - Replace actions/download-artifact with gh run download loop - Add MAX_RETRIES (60) and SLEEP_SECONDS (30) env vars for polling - Retry for up to 30 minutes waiting for artifact availability
…n nacos job - Add 'Wait for build job' step that polls gh api to check build job status - Replace gh run download polling with actions/download-artifact - Move MAX_RETRIES and SLEEP_SECONDS to job-level env with github expression syntax
Increase MAX_RETRIES to 180 for Windows runners to account for slower startup times.
download-artifact does not preserve execute permissions, causing Permission denied when running the native binary.
Start nacos/nacos-server:v3.2.3 container with standalone mode and custom auth configuration for integration testing.
Remove jar files from server/target to avoid conflicts with downloaded native binary artifacts.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ⅰ. Describe what this PR did
This PR adds GraalVM Native Image packaging support to the Seata Server, enabling users to build and deploy the Seata Server as a self-contained native binary with sub-second startup time, lower memory footprint, and no JDK dependency at runtime.
Changes Overview (14 files, +3636 / −105)
1. GraalVM Native Image Build Profiles (
server/pom.xml)nativeMaven profile that configuresspring-boot-maven-plugin(AOT processing) andnative-maven-plugin(GraalVM native image compilation).nativeTestprofile for AOT-based native testing withjunit-platform-launcher.native-linux-amd64,native-linux-aarch64,native-darwin-x86_64,native-darwin-aarch64,native-windows-amd64) that set thenative.platformclassifier were later promoted to the rootpom.xmlso the property is available to all submodules.logback,slf4j,fastjson2and run-time initialization fornetty.channel.kqueue.mainClasstoorg.apache.seata.server.ServerApplication.Spring-Boot-Native-Processed: truemanifest entry.spring-boot-devtoolsfrom native compilation.2. GraalVM Reachability Metadata (3 new config files)
reflect-config.json(~2801 lines) — registers classes, methods, and fields for reflective access at native image build time, covering Seata's core components (serializers, codecs, RPC handlers, store managers, configuration providers, discovery providers, etc.).resource-config.json(~463 lines) — registers resource bundles and configuration files (Spring factories, SPI service descriptors, SQL scripts, configuration templates) for inclusion in the native image.proxy-config.json— registers dynamic proxy interfaces used by Seata (e.g., Spring AOP proxies, configuration binding interfaces).All metadata files are placed under
META-INF/native-image/org.apache.seata/seata-server/for GraalVM 25 compatibility.3. CI/CD: Multi-Platform Native Build Workflow (
.github/workflows/native.yml)Native Build) that builds GraalVM native images for the Seata Server across 5 platforms:ubuntu-24.04(amd64),ubuntu-24.04-arm(arm64),macos-26-intel(x86_64),macos-26(apple silicon),windows-latest(amd64).actions/setup-java@v5.5.0.actions/cache/restore@v4/actions/cache/save@v4) with SNAPSHOT cleanup.actions/upload-artifact@v7.0.1.2.x,develop,masterbranches (ignores markdown-only changes).4. logback-spring.xml Simplification (GraalVM Compatibility)
<if>conditional logic (e.g.,<if condition='property("LOGSTASH_APPENDER_ENABLED").equals("true")'>) because Janino's dynamic bytecode compilation is not supported in GraalVM native images.console-appenderandfile-appenderby default.LOG_BASH_DIRexternal directory path logic.<appender-ref>elements — these are documented with inline comments.5. Spring AOT Compatibility:
@Resource→@AutowiredSetter InjectionAbstractSeataInstanceStrategy: Replaced@Resourcefield injection with@Autowiredsetter-based injection forregistryProperties,serverProperties, andregistryNamingServerProperties. RemovedApplicationContextdependency and@PostConstructinitialization — properties are now injected directly via setters, which is compatible with Spring AOT's closed-world analysis.ServerInstanceStrategyConfig: ChangedseataInstanceStrategy()bean method to accept dependencies via constructor parameters and pass them to the strategy via setters, eliminating the implicitApplicationContext.getBean()lookup.SpringBootConfigurationProvider: Adjusted for AOT compatibility.6. Build Infrastructure (
build/pom.xml, rootpom.xml,Makefile)build/pom.xml:native-maven-pluginversion (1.1.3) topluginManagement.native.platformproperty (promoted fromserver/pom.xml) so it is available to all submodules for GraalVM native-image builds.pom.xml:native-linux-*,native-darwin-*,native-windows-*) — promoted fromserver/pom.xmlso thenative.platformproperty is available to all submodules for GraalVM native-image builds.Makefile:package-server-native-pre,package-server-native,package-server-native-onlytargets for building native images.spotless-checkandspotless-applytargets.-eflag to all Maven commands for consistent error output.7. Dependency Update
zstd-jnifrom1.5.0-4to1.5.7-3(dependencies/pom.xml).8. Test Adjustment
AppenderTest(@Disabled) due to the logback configuration simplification that removed Janino-based conditional appender logic.Usage
Regenerate GraalVM Reachability Metadata (e.g., after adding new components that use reflection):
Run the Seata Server with the Native Image Agent to generate metadata into a temporary directory:
Update the generated metadata into the project resource directory:
server/src/main/resources/META-INF/native-image/org.apache.seata/seata-server/Compile the Native Image
Build the Native Image:
Run the native binary (no JDK required):
./server/target/seata-server-{version}-{platform}Ⅱ. Does this pull request fix one issue?
#8161
This PR implements the feature proposal described in issue #8137 (Spring Boot 4 upgrade) follow-up — adding GraalVM Native Image support to the Seata Server for improved deployment efficiency and cloud-native compatibility.
Ⅲ. Why don't you add test cases (unit test/integration test)?
native.yml) builds native binaries on 5 platforms on every PR/push, and a successful native image compilation validates the GraalVM reachability metadata and AOT compatibility.AppenderTesthas been disabled because it tested Janino<if>conditional logic inlogback-spring.xml, which was removed for GraalVM compatibility. The logback appender behavior (console, file) is implicitly verified by the native image build succeeding and the server starting correctly.nativeTestMaven profile is provided for future AOT-based native testing usingjunit-platform-launcher.Config Mode Tests
filenacosconsulapollozketcd3Registry Mode Tests
filenacoseurekarediszkconsuletcd3sofaseataStore Mode Tests
filedbredisraftTest Plan for Each Mode
Each mode test should verify:
ClassNotFoundException,NoSuchMethodException, or reflection errors at runtime for the mode-specific components.Ⅳ. Describe how to verify it
Option 1: Local verification (requires GraalVM JDK 25)
Expected: The Seata Server starts in milliseconds (vs. seconds in JVM mode) and is ready to accept transactions.
Option 2: CI verification
Check the
Native Buildworkflow results on this PR — it builds native images on ubuntu-24.04 (amd64), ubuntu-24.04-arm (arm64), macos-26-intel, macos-26 (apple silicon), and windows-latest.Ⅴ. Special notes for reviews
GraalVM reachability metadata (
reflect-config.json,resource-config.json,proxy-config.json): These files were generated through iterative native image builds and testing. They register all classes, methods, resources, and proxies that Seata accesses via reflection at runtime. Reviewers should focus on whether any critical Seata components are missing from these configs.Injection style change:
@Resourcefield injection was replaced with@Autowiredsetter/constructor injection inAbstractSeataInstanceStrategyandServerInstanceStrategyConfig. This is required because Spring AOT's closed-world analysis cannot resolve@Resource-injected fields during native compilation. The runtime behavior is identical.logback-spring.xml breaking change: The removal of Janino
<if>conditions means thatLOGSTASH_APPENDER_ENABLED,KAFKA_APPENDER_ENABLED, andMETRIC_APPENDER_ENABLEDproperties no longer dynamically control appender inclusion at runtime. Users who need these appenders must manually uncomment the corresponding<appender-ref>elements inlogback-spring.xml. This is a known limitation of GraalVM native images (no runtime bytecode generation). A follow-up PR could add programmatic appender registration via Spring's@Conditionalbeans.Phased approach: This PR focuses on Phase 1 — basic server startup, configuration loading, and core transaction coordination in native mode. Full feature parity with JVM mode (all serializers, all store modes, all discovery modes) will be addressed in follow-up PRs as testing coverage expands.
PGO (Profile-Guided Optimization): Not included in this PR. Can be added later to further improve native image runtime performance.