Java 微服务架构实战学习文档

第一章 微服务架构基础

1.1 架构演进历程

单体架构 → 垂直拆分 → SOA → 微服务 → 云原生 → 服务网格
架构阶段特点适用场景
单体架构统一部署、简单开发、难以扩展小型项目、初创团队
SOA服务总线、重量级 ESB企业级系统集成
微服务独立部署、轻量通信、去中心化中大型互联网应用
云原生容器化、DevOps、持续交付弹性伸缩、高可用场景
服务网格Sidecar 代理、流量治理大规模微服务集群

1.2 微服务核心特征

九大核心特征

  1. 服务组件化:每个服务独立开发、测试、部署
  2. 按业务能力组织团队:康威定律,团队对齐服务边界
  3. 去中心化治理:技术栈异构、数据独立
  4. 去中心化数据管理:每个服务独立数据库
  5. 基础设施自动化:CI/CD、自动化测试
  6. 容错设计:熔断、降级、限流
  7. 演进式设计:逐步拆分,持续优化
  8. 轻量级通信:HTTP/REST 或 gRPC
  9. 服务发现与注册:动态服务寻址

1.3 服务拆分原则

DDD 领域驱动设计拆分法

// 示例:电商系统领域划分
├── 用户域 (User Domain)
│   ├── 用户服务 (user-service)
│   └── 权限服务 (auth-service)
├── 商品域 (Product Domain)
│   ├── 商品服务 (product-service)
│   └── 类目服务 (category-service)
├── 交易域 (Trade Domain)
│   ├── 订单服务 (order-service)
│   ├── 库存服务 (inventory-service)
│   └── 支付服务 (payment-service)
└── 营销域 (Marketing Domain)
    ├── 优惠券服务 (coupon-service)
    └── 秒杀服务 (seckill-service)

拆分原则 checklist

  •  单一职责原则:一个服务只负责一个业务功能
  •  高内聚低耦合:服务内部紧密相关,服务间依赖最小化
  •  独立部署:每个服务可独立打包、发布、回滚
  •  独立扩展:根据负载单独扩容特定服务
  •  独立数据:每个服务拥有独立的数据存储

1.4 常见设计模式

模式名称解决的问题典型实现
API 网关模式统一入口、认证鉴权Spring Cloud Gateway
服务发现模式动态服务寻址Nacos、Consul
断路器模式防止级联故障Sentinel、Resilience4j
配置中心模式集中配置管理Nacos Config
事件溯源模式审计追踪、状态重建Kafka + Event Store
Saga 模式分布式事务Seata Saga
CQRS 模式读写分离命令端/查询端分离
BFF 模式适配不同客户端Backend for Frontend

第二章 Spring Cloud Alibaba 核心组件

2.1 技术栈全景图

┌─────────────────────────────────────────────────────────────┐
│                        接入层                                │
│              Spring Cloud Gateway (API 网关)                 │
└─────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────┐
│                      服务治理层                               │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │   Nacos     │  │   Sentinel  │  │      Seata          │  │
│  │  注册/配置   │  │  熔断限流     │  │   分布式事务         │  │
│  └─────────────┘  └─────────────┘  └─────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────┐
│                      服务通信层                               │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────────────┐  │
│  │  OpenFeign  │  │    Dubbo    │  │     RocketMQ        │  │
│  │  HTTP 调用  │  │   RPC 调用   │  │    异步消息           │  │
│  └─────────────┘  └─────────────┘  └─────────────────────┘  │
└─────────────────────────────────────────────────────────────┘
                              ↓
┌─────────────────────────────────────────────────────────────┐
│                      数据层                                   │
│  MySQL  │  Redis  │  Elasticsearch  │  MongoDB  │  ShardingSphere │
└─────────────────────────────────────────────────────────────┘

2.2 版本兼容性矩阵(2025 最新)

组件推荐版本Spring Boot 兼容JDK 要求
Spring Cloud Alibaba2025.0.03.4.0+17+
Spring Cloud2025.0.03.4.0+17+
Nacos3.0+-8+
Sentinel1.8.8+-8+
Seata2.2+-8+
RocketMQ5.3+-8+

重要提示:Spring Cloud 2025.0.0 与 Spring Boot 4.0.1+ 存在兼容性问题,请使用 Spring Cloud 2025.1.x 版本

2.3 快速开始:项目脚手架

Maven 父工程配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <groupId>com.company</groupId>
    <artifactId>microservice-parent</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    
    <name>Microservice Parent</name>
    <description>微服务父工程</description>
    
    <properties>
        <java.version>17</java.version>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        
        <!-- Spring 生态版本 -->
        <spring-boot.version>3.4.0</spring-boot.version>
        <spring-cloud.version>2025.0.0</spring-cloud.version>
        <spring-cloud-alibaba.version>2025.0.0</spring-cloud-alibaba.version>
        
        <!-- 工具版本 -->
        <lombok.version>1.18.30</lombok.version>
        <mapstruct.version>1.5.5.Final</mapstruct.version>
    </properties>
    
    <dependencyManagement>
        <dependencies>
            <!-- Spring Boot BOM -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            
            <!-- Spring Cloud BOM -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            
            <!-- Spring Cloud Alibaba BOM -->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                    <configuration>
                        <excludes>
                            <exclude>
                                <groupId>org.projectlombok</groupId>
                                <artifactId>lombok</artifactId>
                            </exclude>
                        </excludes>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

第三章 服务治理与通信

3.1 Nacos 3.0:注册与配置中心

3.1.1 核心架构升级

特性Nacos 2.xNacos 3.0
通信协议HTTP + gRPC纯 gRPC(性能提升 3-5 倍)
一致性协议Raft / DistroDistroConsistency(去中心化)
注册机制客户端主动推送服务端轮询 + 异步注册
健康检查固定心跳智能动态心跳(指数退避)
元数据JSON 传输Protobuf(体积减少 60%)
灰度发布基础权重基于标签的动态路由

3.1.2 服务注册实战

依赖引入

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

配置文件

spring:
  application:
    name: user-service
  cloud:
    nacos:
      discovery:
        server-addr: ${NACOS_SERVER:localhost:8848}
        namespace: ${NACOS_NAMESPACE:prod}
        group: ${NACOS_GROUP:DEFAULT_GROUP}
        metadata:
          version: 1.0.0
          region: beijing
        # 3.0 新增:智能心跳配置
        heart-beat-interval: 3000
        heart-beat-timeout: 9000
        # 3.0 新增:异步注册
        async-register-enabled: true

启动类

@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

3.1.3 配置中心实战

动态配置监听

@Component
@Data
@ConfigurationProperties(prefix = "user")
@NacosConfigurationProperties(dataId = "user-service.yaml", autoRefreshed = true)
public class UserProperties {
    private Integer maxLoginRetry;
    private Long tokenExpireTime;
    private List<String> whitelistIps;
}

// 监听配置变更
@Component
public class ConfigChangeListener {
    
    @NacosConfigListener(dataId = "user-service.yaml")
    public void onMessage(String config) {
        log.info("配置已更新: {}", config);
        // 刷新本地缓存、重置限流阈值等
    }
}

配置分层管理

nacos-config/
├── shared-config/           # 共享配置
│   ├── common-log.yaml      # 日志配置
│   ├── common-redis.yaml    # Redis 配置
│   └── common-db.yaml       # 数据库配置
├── service-config/          # 服务专属配置
│   ├── user-service.yaml
│   ├── order-service.yaml
│   └── pay-service.yaml
└── env-config/              # 环境配置
    ├── application-dev.yaml
    ├── application-test.yaml
    └── application-prod.yaml

3.2 Spring Cloud Gateway 4.3

3.2.1 2025 版本重大变更

旧模块名新模块名说明
spring-cloud-gateway-serverspring-cloud-gateway-server-webfluxWebFlux 网关
spring-cloud-gateway-server-mvcspring-cloud-gateway-server-webmvcWebMVC 网关
spring-cloud-starter-gateway-serverspring-cloud-starter-gateway-server-webfluxWebFlux 启动器

3.2.2 网关核心配置

spring:
  cloud:
    gateway:
      # 全局跨域配置
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods: "*"
            allowedHeaders: "*"
      
      # 路由配置
      routes:
        # 用户服务路由
        - id: user-service-route
          uri: lb://user-service
          predicates:
            - Path=/api/user/**
            - Method=GET,POST
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 100
                redis-rate-limiter.burstCapacity: 200
                key-resolver: "#{@ipKeyResolver}"
            - name: CircuitBreaker
              args:
                name: userServiceCircuitBreaker
                fallbackUri: forward:/fallback/user
        
        # 订单服务路由
        - id: order-service-route
          uri: lb://order-service
          predicates:
            - Path=/api/order/**
          filters:
            - StripPrefix=1
            - AddRequestHeader=X-Request-From, Gateway
      
      # 2025 新增:Bucket4j 限流器
      bucket4j:
        enabled: true
        filters:
          - cache-name: buckets
            url: /api/.*
            rate-limits:
              - bandwidths:
                  - capacity: 1000
                    time: 1
                    unit: minutes
      
      # 安全代理配置(2025 新增)
      server:
        webflux:
          trusted-proxies: "10\\.0\\.0\\..*|192\\.168\\..*"

3.2.3 自定义过滤器

/**
 * 认证过滤器 - 统一鉴权
 */
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
    
    @Autowired
    private JwtTokenProvider tokenProvider;
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        
        // 白名单放行
        if (isWhiteList(path)) {
            return chain.filter(exchange);
        }
        
        // 验证 Token
        String token = extractToken(request);
        if (!tokenProvider.validateToken(token)) {
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
            
            String body = "{\"code\":401,\"message\":\"Unauthorized\"}";
            DataBuffer buffer = response.bufferFactory().wrap(body.getBytes());
            return response.writeWith(Mono.just(buffer));
        }
        
        // 透传用户信息到下游服务
        ServerHttpRequest mutatedRequest = request.mutate()
            .header("X-User-Id", tokenProvider.getUserId(token))
            .header("X-User-Role", tokenProvider.getUserRole(token))
            .build();
        
        return chain.filter(exchange.mutate().request(mutatedRequest).build());
    }
    
    @Override
    public int getOrder() {
        return -100; // 最高优先级
    }
}

3.3 服务间通信

3.3.1 OpenFeign 声明式调用

// 1. 定义 Feign 客户端
@FeignClient(
    name = "order-service",
    fallbackFactory = OrderClientFallbackFactory.class,
    configuration = FeignConfig.class
)
public interface OrderClient {
    
    @GetMapping("/orders/{userId}")
    Result<List<OrderDTO>> getUserOrders(@PathVariable("userId") Long userId);
    
    @PostMapping("/orders")
    Result<Long> createOrder(@RequestBody OrderCreateRequest request);
    
    // 批量查询,减少网络往返
    @PostMapping("/orders/batch")
    Result<Map<Long, List<OrderDTO>>> batchGetOrders(@RequestBody List<Long> userIds);
}

// 2. 降级工厂
@Component
@Slf4j
public class OrderClientFallbackFactory implements FallbackFactory<OrderClient> {
    @Override
    public OrderClient create(Throwable cause) {
        log.error("订单服务调用失败", cause);
        return new OrderClient() {
            @Override
            public Result<List<OrderDTO>> getUserOrders(Long userId) {
                return Result.fail("订单服务暂不可用,请稍后重试");
            }
            
            @Override
            public Result<Long> createOrder(OrderCreateRequest request) {
                // 记录失败日志,后续补偿处理
                return Result.fail("订单创建失败,请稍后重试");
            }
            
            @Override
            public Result<Map<Long, List<OrderDTO>>> batchGetOrders(List<Long> userIds) {
                return Result.success(Collections.emptyMap());
            }
        };
    }
}

// 3. 配置类
public class FeignConfig {
    
    @Bean
    public Request.Options feignOptions() {
        // 连接超时 5s,读取超时 30s
        return new Request.Options(5, TimeUnit.SECONDS, 30, TimeUnit.SECONDS, true);
    }
    
    @Bean
    public Retryer feignRetryer() {
        // 初始间隔 100ms,最大间隔 1s,最多重试 3 次
        return new Retryer.Default(100, TimeUnit.MILLISECONDS, 3);
    }
    
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL; // 开发环境使用,生产建议 BASIC
    }
}

3.3.2 Dubbo RPC 高性能调用

# Dubbo 配置
dubbo:
  application:
    name: ${spring.application.name}
    qos-enable: false
  protocol:
    name: tri  # Triple 协议,兼容 gRPC
    port: -1   # 随机端口
  registry:
    address: nacos://${spring.cloud.nacos.discovery.server-addr}
    group: DUBBO_GROUP
  consumer:
    check: false
    timeout: 3000
    retries: 2
    loadbalance: roundrobin
// 服务提供者
@DubboService(version = "1.0.0", group = "prod", timeout = 3000)
public class UserServiceImpl implements UserService {
    @Override
    public UserDTO getById(Long id) {
        // 业务逻辑
        return userMapper.selectById(id);
    }
}

// 服务消费者
@Service
public class OrderService {
    
    @DubboReference(version = "1.0.0", group = "prod", check = false)
    private UserService userService;
    
    public OrderDTO createOrder(Long userId) {
        UserDTO user = userService.getById(userId);
        // 创建订单逻辑
    }
}

第四章 流量控制与容错

4.1 Sentinel 1.8 流量治理

4.1.1 核心概念

概念说明典型场景
资源被保护的方法或接口Controller 方法、Service 方法
规则限流、降级、系统保护策略QPS 限制、响应时间阈值
流量控制限制并发访问数或 QPS秒杀活动限流
熔断降级失败率达到阈值时快速失败下游服务故障时保护系统
系统保护基于系统负载自适应保护CPU 过高时自动限流
热点参数针对特定参数值限流针对特定用户 ID 限流

4.1.2 流控规则配置

@Configuration
public class SentinelConfig {
    
    @PostConstruct
    public void initRules() {
        List<FlowRule> rules = new ArrayList<>();
        
        // 规则1:用户接口 QPS 限流
        FlowRule userRule = new FlowRule();
        userRule.setResource("GET:/api/user/{id}");
        userRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        userRule.setCount(1000); // 每秒 1000 请求
        userRule.setStrategy(RuleConstant.STRATEGY_DIRECT);
        userRule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_WARM_UP);
        userRule.setWarmUpPeriodSec(10); // 预热 10 秒
        rules.add(userRule);
        
        // 规则2:订单创建并发线程数限流
        FlowRule orderRule = new FlowRule();
        orderRule.setResource("POST:/api/orders");
        orderRule.setGrade(RuleConstant.FLOW_GRADE_THREAD);
        orderRule.setCount(50); // 最多 50 并发线程
        rules.add(orderRule);
        
        // 规则3:热点参数限流(针对用户 ID)
        ParamFlowRule hotRule = new ParamFlowRule();
        hotRule.setResource("getUserOrders");
        hotRule.setParamIdx(0); // 第 0 个参数
        hotRule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        hotRule.setCount(100);
        // 特定用户 ID 单独限制
        hotRule.setParamFlowItemList(Arrays.asList(
            new ParamFlowItem("10086", 10, String.class), // VIP 用户限制更严
            new ParamFlowItem("10010", 5, String.class)
        ));
        ParamFlowRuleManager.loadRules(Collections.singletonList(hotRule));
        
        FlowRuleManager.loadRules(rules);
    }
}

4.1.3 熔断降级规则

// 熔断降级配置
@PostConstruct
public void initDegradeRules() {
    List<DegradeRule> rules = new ArrayList<>();
    
    // 慢调用比例熔断
    DegradeRule slowRule = new DegradeRule();
    slowRule.setResource("orderService");
    slowRule.setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType());
    slowRule.setCount(0.5); // 慢调用比例阈值 50%
    slowRule.setSlowRatioThreshold(0.3); // 慢调用比例超过 30%
    slowRule.setTimeWindow(10); // 熔断时长 10s
    slowRule.setMinRequestAmount(5); // 最小请求数
    slowRule.setStatIntervalMs(1000); // 统计时长 1s
    slowRule.setSlowRequestThreshold(500); // 响应时间超过 500ms 算慢调用
    rules.add(slowRule);
    
    // 异常比例熔断
    DegradeRule errorRule = new DegradeRule();
    errorRule.setResource("paymentService");
    errorRule.setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType());
    errorRule.setCount(0.5); // 异常比例超过 50%
    errorRule.setTimeWindow(30); // 熔断 30s
    rules.add(errorRule);
    
    DegradeRuleManager.loadRules(rules);
}

4.1.4 注解方式定义资源

@Service
public class OrderService {
    
    /**
     * 热点参数限流:value 是资源名,blockHandler 是限流处理方法
     */
    @SentinelResource(
        value = "createOrder",
        blockHandler = "handleBlock",
        fallback = "handleFallback"
    )
    public OrderDTO createOrder(Long userId, OrderCreateRequest request) {
        // 业务逻辑
        return orderMapper.insert(request);
    }
    
    // 限流处理(必须与原方法参数+BlockException 相同)
    public OrderDTO handleBlock(Long userId, OrderCreateRequest request, BlockException ex) {
        log.warn("创建订单被限流: userId={}", userId);
        throw new BizException("系统繁忙,请稍后重试");
    }
    
    // 降级处理(异常时触发)
    public OrderDTO handleFallback(Long userId, OrderCreateRequest request, Throwable ex) {
        log.error("创建订单失败,进入降级: userId={}", userId, ex);
        // 记录失败订单,后续补偿
        saveFailedOrder(userId, request);
        return null;
    }
}

4.2 网关层统一限流

@Component
public class GatewaySentinelConfig {
    
    @PostConstruct
    public void doInit() {
        // 网关流控规则
        GatewayFlowRule rule = new GatewayFlowRule("user-service-route");
        rule.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_ROUTE_ID);
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        rule.setCount(5000); // 路由级别限流
        rule.setIntervalSec(1);
        
        // 参数限流:针对特定用户
        GatewayParamFlowItem paramItem = new GatewayParamFlowItem();
        paramItem.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_HEADER);
        paramItem.setFieldName("X-User-Id");
        rule.setParamItem(paramItem);
        
        GatewayRuleManager.loadRules(Collections.singletonList(rule));
    }
}

第五章 分布式数据一致性

5.1 Seata 2.2 分布式事务

5.1.1 架构组件

┌─────────────────────────────────────────────────────────────┐
│                     TC (Transaction Coordinator)              │
│                     事务协调器(独立部署)                      │
│              维护全局事务状态,协调分支事务提交/回滚              │
└─────────────────────────────────────────────────────────────┘
                              ↓
        ┌─────────────────────┼─────────────────────┐
        ↓                     ↓                     ↓
┌───────────────┐    ┌───────────────┐    ┌───────────────┐
│      TM       │    │      RM       │    │      RM       │
│ 事务管理器     │    │  资源管理器    │    │  资源管理器    │
│ @GlobalTransactional │  │ 订单服务分支   │    │  库存服务分支  │
└───────────────┘    └───────────────┘    └───────────────┘

5.1.2 四种事务模式对比

模式侵入性性能适用场景特点
AT简单 CRUD自动补偿,无业务改造
TCC复杂业务手动实现 Try/Confirm/Cancel
SAGA长事务流程状态机引擎,向前/向后恢复
XA强一致性场景两阶段提交,资源锁定长

5.1.3 AT 模式实战

# Seata 客户端配置
seata:
  enabled: true
  application-id: ${spring.application.name}
  tx-service-group: my_tx_group
  service:
    vgroup-mapping:
      my_tx_group: default
  registry:
    type: nacos
    nacos:
      server-addr: ${spring.cloud.nacos.discovery.server-addr}
      group: SEATA_GROUP
      namespace: ${spring.cloud.nacos.discovery.namespace}
  client:
    rm:
      async-commit-buffer-limit: 10000
    tm:
      default-global-transaction-timeout: 60000
  data-source-proxy-mode: AT
@Service
@Slf4j
public class OrderBizService {
    
    @Autowired
    private OrderMapper orderMapper;
    
    @Autowired
    private InventoryClient inventoryClient;
    
    @Autowired
    private AccountClient accountClient;
    
    /**
     * 创建订单(全局事务)
     * 1. 创建订单(本地事务)
     * 2. 扣减库存(RPC 调用)
     * 3. 扣减账户余额(RPC 调用)
     */
    @GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
    public OrderDTO createOrder(OrderCreateRequest request) {
        log.info("全局事务开始,XID: {}", RootContext.getXID());
        
        // 1. 创建订单
        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setProductId(request.getProductId());
        order.setCount(request.getCount());
        order.setMoney(request.getCount() * request.getPrice());
        order.setStatus(OrderStatus.CREATING);
        orderMapper.insert(order);
        
        // 2. 扣减库存(远程调用)
        Result<Void> inventoryResult = inventoryClient.decrease(
            request.getProductId(), 
            request.getCount()
        );
        if (!inventoryResult.isSuccess()) {
            throw new BizException("库存不足");
        }
        
        // 3. 扣减余额(远程调用)
        Result<Void> accountResult = accountClient.debit(
            request.getUserId(),
            order.getMoney()
        );
        if (!accountResult.isSuccess()) {
            throw new BizException("余额不足");
        }
        
        // 更新订单状态
        order.setStatus(OrderStatus.SUCCESS);
        orderMapper.updateById(order);
        
        log.info("全局事务提交成功");
        return convertToDTO(order);
    }
}

5.1.4 TCC 模式实战(复杂业务场景)

/**
 * TCC 模式:库存服务
 */
@LocalTCC
public interface InventoryTccService {
    
    /**
     * Try 阶段:预留库存
     */
    @TwoPhaseBusinessAction(
        name = "inventoryTccAction",
        commitMethod = "commit",
        rollbackMethod = "rollback",
        useTCCFence = true // 防悬挂
    )
    boolean tryDecrease(@BusinessActionContextParameter(paramName = "productId") Long productId,
                        @BusinessActionContextParameter(paramName = "count") Integer count);
    
    /**
     * Confirm 阶段:确认扣减(实际扣减预留库存)
     */
    boolean commit(BusinessActionContext context);
    
    /**
     * Cancel 阶段:取消预留(释放预留库存)
     */
    boolean rollback(BusinessActionContext context);
}

@Service
@Slf4j
public class InventoryTccServiceImpl implements InventoryTccService {
    
    @Autowired
    private InventoryMapper inventoryMapper;
    
    @Autowired
    private InventoryFenceMapper fenceMapper;
    
    @Override
    public boolean tryDecrease(Long productId, Integer count) {
        // 1. 检查库存是否充足
        Inventory inventory = inventoryMapper.selectById(productId);
        if (inventory.getAvailable() < count) {
            return false;
        }
        
        // 2. 扣减可用库存,增加预留库存
        int affected = inventoryMapper.decreaseAvailable(productId, count);
        if (affected == 0) {
            return false; // 库存不足或并发冲突
        }
        
        inventoryMapper.increaseReserved(productId, count);
        log.info("Try 阶段:预留库存成功,productId={}, count={}", productId, count);
        return true;
    }
    
    @Override
    public boolean commit(BusinessActionContext context) {
        Long productId = Long.parseLong(context.getActionContext("productId").toString());
        Integer count = Integer.parseInt(context.getActionContext("count").toString());
        
        // 将预留库存转为实际扣减
        inventoryMapper.decreaseReserved(productId, count);
        inventoryMapper.increaseSold(productId, count);
        
        log.info("Confirm 阶段:确认扣减成功,productId={}, count={}", productId, count);
        return true;
    }
    
    @Override
    public boolean rollback(BusinessActionContext context) {
        Long productId = Long.parseLong(context.getActionContext("productId").toString());
        Integer count = Integer.parseInt(context.getActionContext("count").toString());
        
        // 释放预留库存
        inventoryMapper.increaseAvailable(productId, count);
        inventoryMapper.decreaseReserved(productId, count);
        
        log.info("Cancel 阶段:释放预留成功,productId={}, count={}", productId, count);
        return true;
    }
}

5.2 最终一致性方案:消息队列

/**
 * 可靠消息最终一致性方案
 */
@Service
public class ReliableMessageService {
    
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    
    @Autowired
    private TransactionRecordMapper transactionRecordMapper;
    
    /**
     * 发送半消息(事务消息)
     */
    public void sendHalfMessage(Order order) {
        Message<Order> message = MessageBuilder
            .withPayload(order)
            .setHeader("KEYS", order.getId().toString())
            .setHeader("TRANSACTION_ID", generateTxId())
            .build();
        
        // 发送事务消息
        TransactionSendResult result = rocketMQTemplate.sendMessageInTransaction(
            "order-topic",
            message,
            order // 本地事务参数
        );
        
        if (!result.getLocalTransactionState().equals(LocalTransactionState.COMMIT_MESSAGE)) {
            throw new BizException("事务消息发送失败");
        }
    }
    
    /**
     * 本地事务执行
     */
    @RocketMQTransactionListener
    class OrderTxListener implements RocketMQLocalTransactionListener {
        
        @Override
        public RocketMQLocalTransactionState executeLocalTransaction(Message msg, Object arg) {
            try {
                Order order = (Order) arg;
                // 执行本地事务:创建订单
                orderService.createOrderLocal(order);
                return RocketMQLocalTransactionState.COMMIT_MESSAGE;
            } catch (Exception e) {
                return RocketMQLocalTransactionState.ROLLBACK_MESSAGE;
            }
        }
        
        @Override
        public RocketMQLocalTransactionState checkLocalTransaction(Message msg) {
            // 回查本地事务状态
            String orderId = msg.getHeaders().get("KEYS", String.class);
            Order order = orderMapper.selectById(orderId);
            if (order != null) {
                return RocketMQLocalTransactionState.COMMIT_MESSAGE;
            }
            return RocketMQLocalTransactionState.ROLLBACK_MESSAGE;
        }
    }
}

第六章 可观测性与监控

6.1 链路追踪:SkyWalking

# SkyWalking Agent 配置
skywalking:
  agent:
    service_name: ${spring.application.name}
    collector:
      backend_service: ${SW_OAP_SERVER:localhost:11800}
  plugin:
    toolkit:
      log:
        transmit_formatted: true
    spring-cloud-gateway:
      enabled: true
/**
 * 自定义链路标签
 */
@Service
public class OrderService {
    
    @Trace(operationName = "createOrder")
    @Tags({
        @Tag(key = "userId", value = "arg[0]"),
        @Tag(key = "orderId", value = "returned.orderId")
    })
    public Order createOrder(Long userId, OrderRequest request) {
        // 业务逻辑
        ActiveSpan.tag("productId", request.getProductId().toString());
        ActiveSpan.info("开始创建订单");
        
        // 关键步骤埋点
        try (TraceScope scope = TracerManager.tracing("validateInventory")) {
            validateInventory(request);
        }
        
        return order;
    }
}

6.2 指标监控:Micrometer + Prometheus

@Configuration
public class MetricsConfig {
    
    @Bean
    MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
        return registry -> registry.config()
            .commonTags("application", "order-service")
            .commonTags("region", "beijing");
    }
    
    /**
     * 自定义业务指标
     */
    @Component
    public class OrderMetrics {
        private final Counter createCounter;
        private final Counter failCounter;
        private final Timer processTimer;
        private final DistributionSummary amountSummary;
        
        public OrderMetrics(MeterRegistry registry) {
            this.createCounter = Counter.builder("orders.created")
                .description("订单创建总数")
                .register(registry);
            
            this.failCounter = Counter.builder("orders.failed")
                .description("订单创建失败数")
                .tag("reason", "inventory")
                .register(registry);
            
            this.processTimer = Timer.builder("orders.process.time")
                .description("订单处理耗时")
                .publishPercentiles(0.5, 0.95, 0.99)
                .register(registry);
            
            this.amountSummary = DistributionSummary.builder("orders.amount")
                .description("订单金额分布")
                .baseUnit("yuan")
                .publishPercentiles(0.5, 0.9, 0.99)
                .register(registry);
        }
        
        public void recordOrderCreated(BigDecimal amount) {
            createCounter.increment();
            amountSummary.record(amount.doubleValue());
        }
        
        public void recordProcessTime(Runnable operation) {
            processTimer.record(operation);
        }
    }
}

6.3 日志聚合:ELK + 结构化日志

<!-- logback-spring.xml -->
<configuration>
    <property name="LOG_PATTERN" 
              value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{X-B3-TraceId:-},%X{X-B3-SpanId:-}] %logger{36} - %msg%n"/>
    
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <includeContext>true</includeContext>
            <includeMdc>true</includeMdc>
            <customFields>{"service":"${spring.application.name}"}</customFields>
        </encoder>
    </appender>
    
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>/var/log/app/application.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>/var/log/app/application.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <maxHistory>30</maxHistory>
            <maxFileSize>100MB</maxFileSize>
        </rollingPolicy>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
    </appender>
    
    <root level="INFO">
        <appender-ref ref="CONSOLE"/>
        <appender-ref ref="FILE"/>
    </root>
</configuration>

第七章 生产环境实践

7.1 容器化部署

Dockerfile 最佳实践

# 多阶段构建,减小镜像体积
FROM eclipse-temurin:17-jdk-alpine AS builder
WORKDIR /app

# 先复制依赖配置,利用缓存层
COPY pom.xml mvnw ./
COPY .mvn .mvn
RUN ./mvnw dependency:go-offline -B

# 复制源码并构建
COPY src src
RUN ./mvnw clean package -DskipTests -B

# 运行阶段使用 JRE 而非 JDK
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app

# 安全:使用非 root 用户
RUN addgroup -g 1001 -S appgroup && \
    adduser -u 1001 -S appuser -G appgroup
USER appuser

# 从构建阶段复制 JAR
COPY --from=builder /app/target/*.jar app.jar

# JVM 参数优化
ENV JAVA_OPTS="-XX:+UseG1GC \
               -XX:MaxRAMPercentage=75.0 \
               -XX:InitialRAMPercentage=50.0 \
               -XX:+UseContainerSupport \
               -Djava.security.egd=file:/dev/./urandom"

EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

Kubernetes 部署配置

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
  labels:
    app: order-service
    version: v1.0.0
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 0
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
        version: v1.0.0
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "8080"
        prometheus.io/path: "/actuator/prometheus"
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                    - key: app
                      operator: In
                      values:
                        - order-service
                topologyKey: kubernetes.io/hostname
      containers:
        - name: order-service
          image: registry.company.com/order-service:1.0.0
          ports:
            - containerPort: 8080
              name: http
            - containerPort: 9090
              name: grpc
          env:
            - name: SPRING_PROFILES_ACTIVE
              value: "prod"
            - name: NACOS_SERVER
              valueFrom:
                configMapKeyRef:
                  name: common-config
                  key: nacos.server
            - name: JVM_OPTS
              value: "-XX:+UseG1GC -XX:MaxRAMPercentage=75.0"
          resources:
            requests:
              memory: "512Mi"
              cpu: "250m"
            limits:
              memory: "2Gi"
              cpu: "1000m"
          livenessProbe:
            httpGet:
              path: /actuator/health/liveness
              port: 8080
            initialDelaySeconds: 60
            periodSeconds: 10
          readinessProbe:
            httpGet:
              path: /actuator/health/readiness
              port: 8080
            initialDelaySeconds: 30
            periodSeconds: 5
          lifecycle:
            preStop:
              exec:
                command: ["/bin/sh", "-c", "sleep 15"] # 优雅停机等待
---
apiVersion: v1
kind: Service
metadata:
  name: order-service
spec:
  selector:
    app: order-service
  ports:
    - port: 80
      targetPort: 8080
      name: http
    - port: 9090
      targetPort: 9090
      name: grpc
  type: ClusterIP
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: order-service-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: order-service
  minReplicas: 3
  maxReplicas: 20
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Pods
      pods:
        metric:
          name: http_requests_per_second
        target:
          type: AverageValue
          averageValue: "1000"
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 60
      policies:
        - type: Percent
          value: 100
          periodSeconds: 15
    scaleDown:
      stabilizationWindowSeconds: 300
      policies:
        - type: Percent
          value: 10
          periodSeconds: 60

7.2 CI/CD 流水线

// Jenkinsfile
pipeline {
    agent any
    
    environment {
        DOCKER_REGISTRY = 'registry.company.com'
        SERVICE_NAME = 'order-service'
    }
    
    stages {
        stage('Build & Test') {
            steps {
                sh './mvnw clean verify -DskipITs=false'
            }
            post {
                always {
                    junit 'target/surefire-reports/*.xml'
                    jacoco execPattern: 'target/jacoco.exec'
                }
            }
        }
        
        stage('SonarQube Analysis') {
            steps {
                withSonarQubeEnv('SonarQube') {
                    sh './mvnw sonar:sonar'
                }
            }
        }
        
        stage('Build Docker Image') {
            steps {
                script {
                    def image = docker.build("${DOCKER_REGISTRY}/${SERVICE_NAME}:${BUILD_NUMBER}")
                    image.push()
                    image.push('latest')
                }
            }
        }
        
        stage('Deploy to Dev') {
            steps {
                sh """
                    kubectl set image deployment/${SERVICE_NAME} \
                        ${SERVICE_NAME}=${DOCKER_REGISTRY}/${SERVICE_NAME}:${BUILD_NUMBER} \
                        -n dev
                    kubectl rollout status deployment/${SERVICE_NAME} -n dev --timeout=300s
                """
            }
        }
        
        stage('Integration Test') {
            steps {
                sh './mvnw verify -P integration-test -Denv=dev'
            }
        }
        
        stage('Deploy to Production') {
            when {
                branch 'main'
            }
            steps {
                input message: 'Deploy to Production?', ok: 'Deploy'
                sh """
                    kubectl set image deployment/${SERVICE_NAME} \
                        ${SERVICE_NAME}=${DOCKER_REGISTRY}/${SERVICE_NAME}:${BUILD_NUMBER} \
                        -n prod
                    kubectl rollout status deployment/${SERVICE_NAME} -n prod --timeout=600s
                """
            }
        }
    }
    
    post {
        failure {
            slackSend(color: 'danger', message: "Build Failed: ${env.JOB_NAME} #${env.BUILD_NUMBER}")
        }
        success {
            slackSend(color: 'good', message: "Build Success: ${env.JOB_NAME} #${env.BUILD_NUMBER}")
        }
    }
}

7.3 灰度发布方案

/**
 * 基于 Nacos 元数据的灰度发布
 */
@Component
public class GrayReleaseFilter implements GlobalFilter, Ordered {
    
    @Autowired
    private NacosDiscoveryProperties nacosProperties;
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        
        // 从 Header 获取灰度标识
        String grayTag = request.getHeaders().getFirst("X-Gray-Tag");
        String userId = request.getHeaders().getFirst("X-User-Id");
        
        // 根据规则判断是否需要灰度
        boolean isGray = checkGrayRule(grayTag, userId);
        
        // 设置元数据,影响负载均衡
        if (isGray) {
            ServerHttpRequest mutatedRequest = request.mutate()
                .header("nacos.service.metadata.version", "v2.0.0-gray")
                .build();
            return chain.filter(exchange.mutate().request(mutatedRequest).build());
        }
        
        return chain.filter(exchange);
    }
    
    private boolean checkGrayRule(String grayTag, String userId) {
        // 1. 特定标签强制灰度
        if ("gray".equals(grayTag)) {
            return true;
        }
        
        // 2. 用户 ID 取模灰度(5% 流量)
        if (userId != null) {
            long userIdHash = Math.abs(userId.hashCode());
            return userIdHash % 100 < 5;
        }
        
        return false;
    }
    
    @Override
    public int getOrder() {
        return -50;
    }
}

第八章 性能优化与调优

8.1 JVM 调优指南

场景推荐配置说明
通用 Web 应用-XX:+UseG1GC -XX:MaxRAMPercentage=75.0G1 收集器,自适应内存
低延迟要求-XX:+UseZGC -XX:+ZGenerationalZGC,停顿时间 < 10ms
大内存堆(>16G)-XX:+UseShenandoahGCShenandoah,低延迟
容器环境-XX:+UseContainerSupport识别容器内存限制
# 生产环境推荐 JVM 参数
JAVA_OPTS="
  -XX:+UseG1GC
  -XX:MaxGCPauseMillis=200
  -XX:G1HeapRegionSize=16m
  -XX:InitiatingHeapOccupancyPercent=45
  -XX:MaxRAMPercentage=75.0
  -XX:InitialRAMPercentage=50.0
  -XX:+UseContainerSupport
  -XX:+UseStringDeduplication
  -XX:+OptimizeStringConcat
  -Djava.security.egd=file:/dev/./urandom
  -Dspring.backgroundpreinitializer.ignore=true
"

8.2 数据库优化

/**
 * 连接池配置(HikariCP)
 */
@Configuration
public class DataSourceConfig {
    
    @Bean
    @ConfigurationProperties("spring.datasource.hikari")
    public HikariConfig hikariConfig() {
        HikariConfig config = new HikariConfig();
        // 核心配置
        config.setMaximumPoolSize(20);
        config.setMinimumIdle(5);
        config.setConnectionTimeout(30000);
        config.setIdleTimeout(600000);
        config.setMaxLifetime(1800000);
        
        // 性能优化
        config.setAutoCommit(false);
        config.setCachePrepStmts(true);
        config.setPrepStmtCacheSize(250);
        config.setPrepStmtCacheSqlLimit(2048);
        config.setUseServerPrepStmts(true);
        config.setUseLocalSessionState(true);
        config.setRewriteBatchedStatements(true);
        config.setCacheResultSetMetadata(true);
        config.setCacheServerConfiguration(true);
        config.setElideSetAutoCommits(true);
        config.setMaintainTimeStats(false);
        
        return config;
    }
}

8.3 缓存策略

/**
 * 多级缓存架构:Caffeine(本地)+ Redis(远程)
 */
@Configuration
@EnableCaching
public class CacheConfig {
    
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        // Redis 缓存配置
        RedisCacheConfiguration redisConfig = RedisCacheConfiguration.defaultCacheConfig()
            .entryTtl(Duration.ofMinutes(10))
            .serializeKeysWith(RedisSerializationContext.SerializationPair
                .fromSerializer(new StringRedisSerializer()))
            .serializeValuesWith(RedisSerializationContext.SerializationPair
                .fromSerializer(new GenericJackson2JsonRedisSerializer()));
        
        // Caffeine 本地缓存配置
        CaffeineCacheManager caffeineManager = new CaffeineCacheManager();
        caffeineManager.setCaffeine(Caffeine.newBuilder()
            .maximumSize(10000)
            .expireAfterWrite(Duration.ofMinutes(5))
            .recordStats());
        
        // 组合缓存管理器
        CompositeCacheManager compositeManager = new CompositeCacheManager();
        compositeManager.setCacheManagers(Arrays.asList(caffeineManager, 
            new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(factory), redisConfig)));
        compositeManager.setFallbackToNoOpCache(false);
        
        return compositeManager;
    }
}

@Service
public class ProductService {
    
    @Cacheable(value = "product", key = "#id", cacheManager = "cacheManager")
    public ProductDTO getById(Long id) {
        return productMapper.selectById(id);
    }
    
    @CacheEvict(value = "product", key = "#product.id")
    public void update(Product product) {
        productMapper.updateById(product);
    }
}

第九章 面试与常见问题

9.1 高频面试题

Q1: Nacos 的 CP 和 AP 模式有什么区别?如何选择?

答案

  • AP 模式(默认):使用 Distro 协议,优先保证可用性,注册中心宕机不影响已注册服务间调用。适用于大多数互联网场景
  • CP 模式:使用 Raft 协议,保证强一致性,但牺牲一定可用性。适用于对数据一致性要求极高的金融场景
  • 选择建议:默认使用 AP 模式,除非有强一致性要求

Q2: Sentinel 与 Hystrix 的熔断策略有何差异?

表格

特性SentinelHystrix
熔断策略慢调用比例、异常比例、异常数异常比例、异常数
限流能力丰富(QPS、线程数、热点参数)有限
自适应保护支持(系统负载保护)不支持
实时监控完善 Dashboard需要额外集成
维护状态活跃维护已停止维护

Q3: Seata AT 模式的 undo_log 是如何实现的?

答案

  1. 一阶段:业务 SQL 执行前,解析 SQL 生成前镜像(查询原数据);执行业务 SQL;生成后镜像(查询新数据);插入 undo_log(包含前后镜像)
  2. 二阶段提交:异步删除 undo_log
  3. 二阶段回滚:根据 undo_log 的前镜像生成回滚 SQL,执行回滚

9.2 生产环境问题排查

java

复制

/**
 * 健康检查端点扩展
 */
@Component
public class CustomHealthIndicator implements HealthIndicator {
    
    @Autowired
    private DataSource dataSource;
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    @Override
    public Health health() {
        Map<String, Object> details = new HashMap<>();
        
        // 数据库检查
        try (Connection conn = dataSource.getConnection()) {
            details.put("database", "UP");
            details.put("databaseLatency", checkDbLatency());
        } catch (Exception e) {
            return Health.down()
                .withDetail("database", "DOWN: " + e.getMessage())
                .build();
        }
        
        // Redis 检查
        try {
            redisTemplate.opsForValue().get("health:check");
            details.put("redis", "UP");
        } catch (Exception e) {
            return Health.down()
                .withDetail("redis", "DOWN: " + e.getMessage())
                .build();
        }
        
        // Nacos 连接检查
        details.put("nacos", checkNacosConnection());
        
        return Health.up()
            .withDetails(details)
            .build();
    }
}

9.3 学习路径建议

plain

复制

第一阶段(2-3 周):基础夯实
├── Spring Boot 3.x 核心原理
├── Spring Cloud Gateway 基础路由
├── Nacos 服务注册与配置管理
└── OpenFeign 声明式调用

第二阶段(3-4 周):微服务进阶
├── Sentinel 流量控制与熔断
├── Seata 分布式事务(AT/TCC 模式)
├── RocketMQ 消息队列实战
└── SkyWalking 链路追踪

第三阶段(2-3 周):生产实践
├── Docker + Kubernetes 容器化部署
├── CI/CD 流水线搭建
├── 性能调优与监控告警
└── 灰度发布与故障演练

附录

A. 推荐版本组合(2025 年)

表格

组件版本备注
JDK17 或 21LTS 版本,推荐 21(虚拟线程)
Spring Boot3.4.0+最低 3.4.0
Spring Cloud2025.0.0+或 2025.1.x(兼容 Boot 4.0.1+)
Spring Cloud Alibaba2025.0.0+适配最新 Spring Cloud
Nacos3.0+支持 gRPC、智能心跳
Sentinel1.8.8+包含最新安全修复
Seata2.2+支持控制台、更多存储模式
RocketMQ5.3+支持 Proxy 模式