返回首頁Cloud Native

Cloud Native Java 開發指南:Spring Boot 3 雲原生應用實戰【2025】

15 min 分鐘閱讀
#java#spring-boot#cloud-native#graalvm#kubernetes

Cloud Native Java 開發指南:Spring Boot 3 雲原生應用實戰【2025】

Java 已經 30 歲了,還適合 Cloud Native 嗎?答案是肯定的。Spring Boot 3 和 GraalVM Native Image 讓 Java 應用可以在幾十毫秒內啟動,記憶體佔用大幅降低。Java 在雲原生時代依然是主流選擇。

這篇文章會介紹如何用 Java 開發 Cloud Native 應用,重點放在 Spring Boot 3 的雲原生特性、Spring Cloud 生態系,以及 GraalVM Native Image 的實戰應用。

台灣 Java 工程師在電腦前撰寫 Spring Boot 程式碼,IDE 顯示 Kubernetes 部署配置


Java 在 Cloud Native 的定位

Java 適合 Cloud Native 嗎?

先面對這個問題:Java 的啟動慢、記憶體佔用大,這在容器環境不是問題嗎?

傳統 Java 的挑戰:

指標傳統 JavaGo/Node.js
啟動時間2-10 秒毫秒級
記憶體佔用200-500 MB20-50 MB
容器映像大小300+ MB10-50 MB

這些數字讓 Java 在 Serverless 和快速擴展場景較為吃力。

但 Java 有它的優勢:

  • 成熟的生態系:Spring、Hibernate 等框架經過二十年驗證
  • 人才充足:全球最多開發者使用的語言之一
  • 企業級功能:交易處理、安全性、監控等完整支援
  • 效能穩定:JVM 的 JIT 編譯在長時間運行時效能優秀

現代 Java 的改進:

GraalVM Native Image 解決了啟動和記憶體問題:

指標JVM 模式Native Image
啟動時間2-10 秒10-50 毫秒
記憶體佔用200-500 MB30-100 MB
容器映像大小300+ MB50-100 MB

Java Cloud Native 演進

2010-2014:Spring 框架時代

  • Spring Framework 3.x/4.x
  • 傳統的 WAR 部署在 Tomcat
  • 設定繁瑣,XML 地獄

2014-2018:Spring Boot 崛起

  • Spring Boot 1.x/2.x
  • 嵌入式伺服器,JAR 部署
  • 自動配置,開箱即用

2018-2022:Cloud Native 整合

  • Spring Cloud 生態系成熟
  • Kubernetes 整合加強
  • Reactive 程式設計支援

2022-現在:原生編譯時代

  • Spring Boot 3.x
  • GraalVM Native Image 正式支援
  • Java 17+ 為最低要求

Java vs Go/Rust 在雲原生的比較

面向JavaGoRust
啟動速度中等(Native Image 快)
記憶體效率中等最高
開發速度快(框架成熟)中等
學習曲線中等
生態系最豐富良好成長中
企業採用最廣成長中較少

選擇建議:

  • 企業應用、複雜業務邏輯 → Java
  • 基礎設施工具、CLI → Go
  • 極致效能、系統程式 → Rust

想了解 Cloud Native 完整概念?請參考 Cloud Native 完整指南


Spring Boot 3 Cloud Native 特性

Spring Boot 3 新功能

Spring Boot 3 是 Spring 生態系的重大升級,帶來多項雲原生增強:

1. Java 17+ 必須

Spring Boot 3 最低要求 Java 17,可以使用:

  • Records
  • Sealed Classes
  • Pattern Matching
  • Virtual Threads(Java 21)

2. Jakarta EE 10

從 javax.* 遷移到 jakarta.*,這是最大的變動:

// Spring Boot 2.x
import javax.servlet.http.HttpServletRequest;

// Spring Boot 3.x
import jakarta.servlet.http.HttpServletRequest;

3. GraalVM Native Image 支援

Spring Boot 3 對 Native Image 的支援變成一等公民:

<plugin>
    <groupId>org.graalvm.buildtools</groupId>
    <artifactId>native-maven-plugin</artifactId>
</plugin>

4. 可觀測性增強

內建 Micrometer Tracing,整合 OpenTelemetry:

management:
  tracing:
    sampling:
      probability: 1.0
  otlp:
    tracing:
      endpoint: http://otel-collector:4318/v1/traces

雲原生相關特性

1. Actuator 端點

Spring Boot Actuator 提供健康檢查、指標、追蹤等端點:

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  endpoint:
    health:
      show-details: always
      probes:
        enabled: true

Kubernetes 可以直接使用這些端點:

livenessProbe:
  httpGet:
    path: /actuator/health/liveness
    port: 8080
readinessProbe:
  httpGet:
    path: /actuator/health/readiness
    port: 8080

2. 配置外部化

符合 12 Factor 的 Config 原則

# application.yml
spring:
  datasource:
    url: ${DATABASE_URL}
    username: ${DATABASE_USER}
    password: ${DATABASE_PASSWORD}

支援多種配置來源:

  • 環境變數
  • ConfigMap(K8s)
  • Spring Cloud Config Server
  • HashiCorp Vault

3. 優雅關閉

容器被終止時,正確處理進行中的請求:

server:
  shutdown: graceful
spring:
  lifecycle:
    timeout-per-shutdown-phase: 30s

配置外部化

Spring Cloud Kubernetes

直接讀取 K8s 的 ConfigMap 和 Secret:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-client-config</artifactId>
</dependency>
# ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: my-app
data:
  application.yml: |
    app:
      feature-flag: true
      max-connections: 100

應用程式會自動載入 ConfigMap 中的設定。

12 Factor 實踐

Spring Boot 如何對應 12 Factor:

原則Spring Boot 實踐
CodebaseGit + Spring Initializr
DependenciesMaven/Gradle
ConfigEnvironment Variables + ConfigMap
Backing ServicesSpring Data + 連線池
Build, Release, RunDocker + CI/CD
ProcessesStateless + Redis Session
Port BindingEmbedded Tomcat/Netty
Concurrency水平擴展 + K8s HPA
DisposabilityGraceful Shutdown
Dev/Prod ParityDocker Compose + K8s
LogsLogback + stdout
Admin ProcessesSpring Batch + K8s Jobs

Spring Cloud 生態系

Spring Cloud 核心元件

Spring Cloud 提供微服務開發的完整工具包:

1. 服務發現

// 使用 Spring Cloud Kubernetes
@SpringBootApplication
@EnableDiscoveryClient
public class MyApp {
    public static void main(String[] args) {
        SpringApplication.run(MyApp.class, args);
    }
}

2. 負載平衡

@Configuration
public class RestClientConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

3. 熔斷器(Resilience4j)

@CircuitBreaker(name = "userService", fallbackMethod = "fallback")
public User getUser(Long id) {
    return userClient.getUser(id);
}

public User fallback(Long id, Exception e) {
    return new User(id, "Unknown");
}

4. API Gateway(Spring Cloud Gateway)

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - StripPrefix=1

Spring Cloud Kubernetes

專為 Kubernetes 設計的 Spring Cloud 元件:

功能:

  • 服務發現(直接用 K8s Service)
  • 配置管理(讀取 ConfigMap/Secret)
  • 負載平衡(整合 K8s DNS)

和傳統 Spring Cloud 的差異:

功能Spring Cloud NetflixSpring Cloud Kubernetes
服務發現EurekaK8s Service
配置中心Config ServerConfigMap
負載平衡RibbonK8s DNS
外部依賴需要部署 Eureka Server

建議: 如果已經用 Kubernetes,優先選擇 Spring Cloud Kubernetes,減少額外元件。

Spring Cloud vs K8s 原生方案

需求Spring Cloud 方案K8s 原生方案
服務發現EurekaK8s Service
配置管理Config ServerConfigMap + Secret
負載平衡Spring Cloud LoadBalancerK8s Service
API GatewaySpring Cloud GatewayIngress + API Gateway
熔斷限流Resilience4jIstio

選擇建議:

  • 簡單專案:用 K8s 原生方案
  • 複雜邏輯(如動態路由):用 Spring Cloud 方案
  • 混合使用:大部分用 K8s 原生,特定需求用 Spring Cloud

Java 微服務架構設計需要協助?預約架構諮詢,讓專家幫你規劃最適合的技術方案。

電腦螢幕顯示 Spring Boot 應用的 Grafana 監控儀表板,呈現 JVM 記憶體和請求延遲指標


GraalVM Native Image

什麼是 Native Image?

GraalVM Native Image 是一種 AOT(Ahead-of-Time)編譯技術,可以把 Java 應用編譯成原生可執行檔。

運作方式:

Java 程式碼 → GraalVM 編譯器 → 原生可執行檔
                    ↓
            靜態分析、無 JVM

效果:

  • 啟動時間:從秒級降到毫秒級
  • 記憶體:減少 50-80%
  • 映像大小:減少 50-70%

Spring Native 支援

Spring Boot 3 原生支援 Native Image:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.0</version>
</parent>

<build>
    <plugins>
        <plugin>
            <groupId>org.graalvm.buildtools</groupId>
            <artifactId>native-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

編譯命令:

# Maven
./mvnw -Pnative native:compile

# Gradle
./gradlew nativeCompile

建置容器映像:

./mvnw -Pnative spring-boot:build-image

優勢與限制

優勢:

  1. 極快啟動:適合 Serverless、快速擴展
  2. 低記憶體:降低雲端成本
  3. 小映像:加快部署速度
  4. 預熱不需要:不需要等待 JIT 編譯

限制:

  1. 反射限制:需要在編譯時提供反射配置
  2. 動態載入限制:不支援動態類別載入
  3. 編譯時間長:Native Image 編譯比 JVM 慢很多
  4. 除錯困難:原生執行檔的除錯較複雜
  5. 不是所有程式庫都支援:需要確認相容性

適用場景

適合 Native Image:

  • Serverless Functions(AWS Lambda、Cloud Functions)
  • CLI 工具
  • 需要快速擴展的微服務
  • 對記憶體敏感的場景

不適合 Native Image:

  • 長時間運行的服務(JIT 最終會更快)
  • 大量使用反射的框架
  • 需要動態類別載入的應用
  • 開發階段(編譯太慢)

混合策略:

# 開發環境用 JVM
spring:
  profiles:
    active: dev

# 生產環境可選 Native
---
spring:
  config:
    activate:
      on-profile: prod-native

Cloud Native Java 最佳實踐

1. 容器化最佳實踐

多階段建置 Dockerfile:

# 建置階段
FROM eclipse-temurin:21-jdk as builder
WORKDIR /app
COPY . .
RUN ./mvnw package -DskipTests

# 執行階段
FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar

# 非 root 使用者
RUN addgroup --system spring && adduser --system --ingroup spring spring
USER spring

EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]

Native Image Dockerfile:

FROM ghcr.io/graalvm/native-image-community:21 as builder
WORKDIR /app
COPY . .
RUN ./mvnw -Pnative native:compile

FROM gcr.io/distroless/base-debian12
COPY --from=builder /app/target/my-app /app
ENTRYPOINT ["/app"]

2. 健康檢查

@Component
public class DatabaseHealthIndicator implements HealthIndicator {

    private final DataSource dataSource;

    @Override
    public Health health() {
        try (Connection conn = dataSource.getConnection()) {
            if (conn.isValid(1)) {
                return Health.up().build();
            }
        } catch (SQLException e) {
            return Health.down()
                .withException(e)
                .build();
        }
        return Health.down().build();
    }
}

3. 日誌最佳實踐

輸出 JSON 格式,方便日誌系統解析:


<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

4. 安全最佳實踐

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/actuator/health/**").permitAll()
                .requestMatchers("/api/**").authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(Customizer.withDefaults())
            );
        return http.build();
    }
}

了解更多安全議題?請參考 Cloud Native Security 完整指南


實戰範例

完整的 Cloud Native Spring Boot 應用結構:

my-app/
├── src/
│   └── main/
│       ├── java/
│       │   └── com/example/
│       │       ├── MyApplication.java
│       │       ├── config/
│       │       ├── controller/
│       │       ├── service/
│       │       └── repository/
│       └── resources/
│           ├── application.yml
│           └── logback-spring.xml
├── Dockerfile
├── pom.xml
└── k8s/
    ├── deployment.yaml
    ├── service.yaml
    └── configmap.yaml

Kubernetes 部署配置:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: my-app:1.0.0
        ports:
        - containerPort: 8080
        envFrom:
        - configMapRef:
            name: my-app-config
        - secretRef:
            name: my-app-secrets
        resources:
          requests:
            memory: "256Mi"
            cpu: "200m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /actuator/health/liveness
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5

了解更多 Kubernetes 部署配置?請參考 Cloud Native 技術棧入門


FAQ

Q1: Spring Boot 3 值得升級嗎?

如果你要使用 GraalVM Native Image 或新的 Java 特性(Virtual Threads),值得升級。但要注意 javax 到 jakarta 的遷移工作。

Q2: Native Image 的編譯時間太長怎麼辦?

開發時用 JVM 模式,只在 CI/CD 建置生產映像時用 Native Image。也可以考慮增加建置機器的資源。

Q3: 現有的 Spring Boot 2.x 專案如何遷移?

建議步驟:(1) 先升級到 2.7.x (2) 處理 deprecation warnings (3) 遷移 javax 到 jakarta (4) 升級到 3.x。Spring 提供遷移指南和工具。

Q4: Spring Cloud 還需要嗎?用 Kubernetes 就好?

視需求而定。基本的服務發現和配置管理,K8s 原生就夠用。但如果需要進階的熔斷、限流、動態路由,Spring Cloud 元件(如 Resilience4j、Spring Cloud Gateway)還是很有價值。

Q5: Java 21 的 Virtual Threads 對 Cloud Native 有幫助嗎?

有。Virtual Threads 讓高併發 I/O 密集型應用變得更簡單,不需要 Reactive 程式設計就能達到類似的效果。Spring Boot 3.2+ 支援 Virtual Threads。


下一步

Java 在 Cloud Native 時代依然是強大的選擇。建議:

  1. 升級到 Spring Boot 3.x
  2. 了解 GraalVM Native Image 的限制和適用場景
  3. 評估 Spring Cloud Kubernetes 的使用
  4. 導入可觀測性(Micrometer + OpenTelemetry)

延伸閱讀:

想將現有 Java 應用雲原生化?預約架構諮詢,讓有經驗的專家幫你評估現況,規劃遷移策略。


參考資料

需要專業的雲端建議?

無論您正在評估雲平台、優化現有架構,或尋找節費方案,我們都能提供協助

預約免費諮詢

相關文章