轩辕李的博客 轩辕李的博客
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • JavaScript
  • TypeScript
  • Node.js
  • 前端框架
  • 前端工程化
  • 浏览器与Web API
  • 架构设计与模式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

轩辕李

勇猛精进,星辰大海
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • JavaScript
  • TypeScript
  • Node.js
  • 前端框架
  • 前端工程化
  • 浏览器与Web API
  • 架构设计与模式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 架构设计与模式

    • 高可用-分布式基础之CAP理论
    • 高可用-服务容错与降级策略
    • 高可用-故障检测与自动恢复
    • 高可用-混沌工程实践
    • 高可用-分布式事务实战
    • 高可用-多活与容灾架构设计
    • 高性能-缓存架构设计
    • 高性能-性能优化方法论
    • 高性能-异步处理与消息队列
    • 高性能-数据库性能优化
    • 高性能-负载均衡策略详解
    • 高性能-CDN与静态资源优化
    • 高扩展-水平扩展vs垂直扩展
    • 高扩展-无状态服务设计
    • 高扩展-微服务架构演进
      • 一、架构演进的必然性
        • 1、单体架构的局限
        • 2、架构演进的典型路径
        • 3、何时考虑微服务
      • 二、微服务架构的核心特征
        • 1、服务自治
        • 2、按业务能力拆分
        • 3、去中心化治理
        • 4、自动化部署
        • 5、故障隔离
      • 三、服务拆分原则
        • 1、单一职责原则
        • 2、高内聚低耦合
        • 3、业务边界清晰
        • 4、数据独立性
        • 5、团队自治
        • 6、拆分粒度适中
      • 四、服务拆分实战
        • 1、识别服务边界
        • 2、单体应用拆分示例
        • 3、数据库拆分
        • 4、共享代码处理
      • 五、微服务通信模式
        • 1、同步通信
        • 2、异步通信
        • 3、服务发现
        • 4、API 网关
      • 六、数据一致性解决方案
        • 1、分布式事务问题
        • 2、Saga 模式
        • 3、最终一致性
        • 4、TCC 模式
      • 七、微服务治理
        • 1、服务限流
        • 2、服务熔断
        • 3、链路追踪
        • 4、日志聚合
        • 5、配置中心
      • 八、部署与运维
        • 1、容器化
        • 2、Kubernetes 部署
        • 3、CI/CD 流水线
        • 4、灰度发布
      • 九、监控告警
        • 1、监控体系
        • 2、告警规则
      • 十、常见问题与解决方案
        • 1、服务雪崩
        • 2、链路过长
        • 3、数据一致性
        • 4、服务数量爆炸
        • 5、测试复杂度
      • 十一、总结
        • 微服务的核心价值
        • 架构演进建议
        • 最佳实践
        • 微服务不是银弹
    • 高扩展-弹性伸缩设计
  • 代码质量管理

  • 基础

  • 操作系统

  • 计算机网络

  • AI

  • 编程范式

  • 安全

  • 中间件

  • 心得

  • 架构
  • 架构设计与模式
轩辕李
2025-05-29
目录

高扩展-微服务架构演进

从单体应用到微服务架构,是现代软件系统扩展性演进的必经之路。微服务架构通过将复杂系统拆分为多个独立的小服务,实现了更好的扩展性、灵活性和团队协作效率。

然而,微服务并非银弹,盲目拆分反而会带来更大的复杂度。本文将深入探讨微服务架构的演进路径、拆分原则和实践经验,帮助你做出正确的架构决策。

# 一、架构演进的必然性

# 1、单体架构的局限

单体应用(Monolithic Application)是指所有功能模块都在一个应用中的架构模式。

┌─────────────────────────────────────┐
│         单体应用 (WAR/JAR)           │
│                                     │
│  ┌─────────┐  ┌─────────┐         │
│  │用户模块  │  │订单模块  │         │
│  └─────────┘  └─────────┘         │
│  ┌─────────┐  ┌─────────┐         │
│  │商品模块  │  │支付模块  │         │
│  └─────────┘  └─────────┘         │
│                                     │
│         共享数据库                   │
└─────────────────────────────────────┘

单体架构的问题:

① 扩展性差:

  • 只能整体扩展,无法针对性扩展高负载模块
  • 一个模块需要扩展,整个应用都要复制

② 部署风险高:

  • 修改一行代码,整个应用都要重新部署
  • 部署周期长,发布窗口大

③ 技术栈固化:

  • 所有模块必须使用同一技术栈
  • 升级框架版本影响整个系统

④ 团队协作困难:

  • 多个团队修改同一代码库,冲突频繁
  • 代码耦合严重,改动影响面大

⑤ 故障隔离差:

  • 一个模块出问题,整个应用不可用
  • 内存泄漏会拖垮整个系统

# 2、架构演进的典型路径

阶段1: 单体应用
   ↓ (业务增长,团队扩大)
阶段2: 单体应用 + 垂直拆分
   ↓ (用户量暴增,性能瓶颈)
阶段3: SOA 服务化
   ↓ (业务复杂度提升)
阶段4: 微服务架构
   ↓ (云原生转型)
阶段5: Service Mesh

# 3、何时考虑微服务

需要微服务的信号:

问题 描述 影响
部署频率低 每月只能发布1-2次 业务迭代缓慢
团队规模大 10人以上在同一代码库协作 冲突频繁,效率低
启动时间长 应用启动超过5分钟 开发调试效率低
扩展粒度粗 只有少数模块高负载,却要整体扩展 资源浪费
技术债务重 代码耦合严重,改动风险大 维护成本高
故障影响大 局部问题导致整体不可用 可用性差

不需要微服务的场景:

  • ❌ 团队规模小于10人
  • ❌ 业务逻辑简单,CRUD为主
  • ❌ 用户量不大(DAU < 10万)
  • ❌ 团队缺乏分布式系统经验
  • ❌ 基础设施不完善(监控、日志、链路追踪)

# 二、微服务架构的核心特征

# 1、服务自治

每个微服务都是一个独立的业务单元:

  • 独立的代码库
  • 独立的数据库
  • 独立的部署周期
  • 独立的技术选型
┌──────────────┐  ┌──────────────┐  ┌──────────────┐
│  用户服务     │  │  订单服务     │  │  商品服务     │
│              │  │              │  │              │
│ Spring Boot  │  │  Go + Gin    │  │  Node.js     │
│   MySQL      │  │  PostgreSQL  │  │  MongoDB     │
└──────────────┘  └──────────────┘  └──────────────┘

# 2、按业务能力拆分

基于领域驱动设计(DDD)思想,按业务边界拆分:

电商系统拆分:
┌─────────────────────────────────────────┐
│  用户中心  │  商品中心  │  订单中心      │
│  账户服务  │  商品服务  │  订单服务      │
│  认证服务  │  库存服务  │  支付服务      │
│  权限服务  │  分类服务  │  物流服务      │
└─────────────────────────────────────────┘

# 3、去中心化治理

数据去中心化:

  • 每个服务管理自己的数据
  • 避免共享数据库
  • 通过 API 访问其他服务的数据
❌ 共享数据库:
[用户服务] ─┐
           ├─→ [共享数据库]
[订单服务] ─┘

✅ 独立数据库:
[用户服务] → [用户DB]
[订单服务] → [订单DB]
     │
     └─ RPC ─→ [用户服务] (获取用户信息)

技术去中心化:

  • 各团队自主选择技术栈
  • 使用统一的通信协议(HTTP/gRPC)
  • 遵守统一的 API 规范

# 4、自动化部署

微服务数量多,必须实现自动化:

  • CI/CD 流水线
  • 容器化部署(Docker)
  • 容器编排(Kubernetes)
  • 基础设施即代码(Terraform)

# 5、故障隔离

舱壁模式(Bulkhead Pattern):

// 为不同的服务配置独立的线程池
@Bean
public ThreadPoolTaskExecutor userServiceExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(10);
    executor.setMaxPoolSize(20);
    executor.setQueueCapacity(100);
    executor.setThreadNamePrefix("user-service-");
    return executor;
}

@Bean
public ThreadPoolTaskExecutor orderServiceExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(20);
    executor.setMaxPoolSize(50);
    executor.setQueueCapacity(200);
    executor.setThreadNamePrefix("order-service-");
    return executor;
}

熔断降级:

@Service
public class OrderService {
    
    @Autowired
    private UserServiceClient userServiceClient;
    
    // 用户服务故障时,使用降级逻辑
    @HystrixCommand(fallbackMethod = "getUserFallback")
    public User getUser(Long userId) {
        return userServiceClient.getById(userId);
    }
    
    public User getUserFallback(Long userId) {
        // 返回默认用户信息
        User user = new User();
        user.setId(userId);
        user.setUsername("用户" + userId);
        return user;
    }
}

# 三、服务拆分原则

# 1、单一职责原则

每个服务只负责一个业务领域:

❌ 职责不清晰:

用户服务:
- 用户注册
- 用户登录
- 订单管理  ← 不属于用户领域
- 商品收藏  ← 不属于用户领域

✅ 职责明确:

用户服务:
- 用户注册
- 用户登录
- 用户信息管理

订单服务:
- 订单创建
- 订单管理

收藏服务:
- 商品收藏
- 收藏管理

# 2、高内聚低耦合

高内聚: 相关功能放在同一服务。

✅ 商品服务(高内聚):
- 商品CRUD
- 商品详情
- 商品搜索
- 商品分类

低耦合: 服务间依赖尽可能少。

❌ 强耦合:
订单服务 → 用户服务 → 权限服务 → 角色服务
         ↓
       商品服务 → 库存服务 → 仓库服务

✅ 低耦合:
订单服务 → 用户服务(只获取基本信息)
         → 商品服务(只获取基本信息)

# 3、业务边界清晰

基于 DDD 的限界上下文(Bounded Context)拆分:

电商系统的限界上下文:

┌─────────────────────────────────────────────┐
│                 电商系统                     │
│                                             │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐ │
│  │用户上下文│  │商品上下文│  │交易上下文│ │
│  │          │  │          │  │          │ │
│  │ 用户     │  │ 商品     │  │ 订单     │ │
│  │ 账户     │  │ 分类     │  │ 支付     │ │
│  │ 认证     │  │ 库存     │  │ 物流     │ │
│  └──────────┘  └──────────┘  └──────────┘ │
└─────────────────────────────────────────────┘

聚合根识别:

// 订单聚合根
@Entity
public class Order {
    @Id
    private Long id;
    
    private Long userId;  // 不直接关联 User 实体
    
    @OneToMany(cascade = CascadeType.ALL)
    private List<OrderItem> items;  // 订单项是订单的一部分
    
    private OrderStatus status;
}

// 订单项(值对象)
@Embeddable
public class OrderItem {
    private Long productId;  // 不直接关联 Product 实体
    private String productName;
    private Integer quantity;
    private BigDecimal price;
}

# 4、数据独立性

每个服务拥有独立的数据库:

-- 用户服务数据库
CREATE DATABASE user_service;
USE user_service;
CREATE TABLE users (...);
CREATE TABLE accounts (...);

-- 订单服务数据库
CREATE DATABASE order_service;
USE order_service;
CREATE TABLE orders (...);
CREATE TABLE order_items (...);

-- 商品服务数据库
CREATE DATABASE product_service;
USE product_service;
CREATE TABLE products (...);
CREATE TABLE categories (...);

数据冗余:

为了避免跨服务查询,适当冗余数据:

// 订单服务保存商品快照
@Entity
public class OrderItem {
    private Long productId;
    
    // 冗余商品信息(下单时的快照)
    private String productName;
    private String productImage;
    private BigDecimal productPrice;
}

# 5、团队自治

康威定律: 系统架构反映组织的沟通结构。

组织结构:
┌──────────┐  ┌──────────┐  ┌──────────┐
│ 用户团队  │  │ 商品团队  │  │ 订单团队  │
│ (5人)    │  │ (8人)    │  │ (10人)   │
└──────────┘  └──────────┘  └──────────┘

对应的服务:
┌──────────┐  ┌──────────┐  ┌──────────┐
│ 用户服务  │  │ 商品服务  │  │ 订单服务  │
│          │  │          │  │          │
└──────────┘  └──────────┘  └──────────┘

# 6、拆分粒度适中

过度拆分的问题:

  • 服务数量爆炸,运维成本高
  • 服务间调用链过长,性能下降
  • 分布式事务难以处理

粒度建议:

  • 单个服务代码量: 1万-5万行
  • 服务团队规模: 2-10人(两个披萨团队)
  • 服务启动时间: < 1分钟
  • 服务数据库表数: 5-20张

# 四、服务拆分实战

# 1、识别服务边界

步骤 1: 领域建模

使用事件风暴(Event Storming)识别领域:

电商系统事件流:
用户注册 → 浏览商品 → 加入购物车 → 下单 → 支付 → 发货 → 收货 → 评价

领域识别:
- 用户域: 用户注册、用户登录
- 商品域: 浏览商品、商品详情
- 购物车域: 加入购物车、购物车管理
- 订单域: 下单、订单管理
- 支付域: 支付、退款
- 物流域: 发货、收货、物流查询
- 评价域: 商品评价

步骤 2: 分析依赖关系

依赖关系图:
┌──────────┐
│ 用户服务  │ ← 认证基础服务
└──────────┘
      ↑
      │
┌──────────┐     ┌──────────┐
│ 订单服务  │ ←─→ │ 商品服务  │
└──────────┘     └──────────┘
      │               ↑
      ↓               │
┌──────────┐     ┌──────────┐
│ 支付服务  │     │ 库存服务  │
└──────────┘     └──────────┘
      │
      ↓
┌──────────┐
│ 物流服务  │
└──────────┘

步骤 3: 确定拆分顺序

优先拆分:

  1. ✅ 变更频繁的模块
  2. ✅ 性能瓶颈模块
  3. ✅ 依赖少的模块
  4. ✅ 边界清晰的模块

延后拆分:

  1. ❌ 核心复杂业务模块
  2. ❌ 依赖关系复杂的模块
  3. ❌ 变更不频繁的模块

# 2、单体应用拆分示例

原单体应用结构:

e-commerce-monolith/
├── src/main/java/com/example/
│   ├── user/
│   │   ├── controller/
│   │   ├── service/
│   │   └── repository/
│   ├── product/
│   │   ├── controller/
│   │   ├── service/
│   │   └── repository/
│   ├── order/
│   │   ├── controller/
│   │   ├── service/
│   │   └── repository/
│   └── payment/
│       ├── controller/
│       ├── service/
│       └── repository/
└── application.yml (共享配置)

拆分后的微服务结构:

microservices/
├── user-service/
│   ├── src/main/java/com/example/user/
│   ├── application.yml
│   └── Dockerfile
├── product-service/
│   ├── src/main/java/com/example/product/
│   ├── application.yml
│   └── Dockerfile
├── order-service/
│   ├── src/main/java/com/example/order/
│   ├── application.yml
│   └── Dockerfile
└── payment-service/
    ├── src/main/java/com/example/payment/
    ├── application.yml
    └── Dockerfile

# 3、数据库拆分

阶段 1: 逻辑拆分(Schema 隔离)

-- 同一数据库实例,不同 Schema
CREATE SCHEMA user_schema;
CREATE SCHEMA product_schema;
CREATE SCHEMA order_schema;

-- 应用连接不同 Schema
user-service:
  datasource:
    url: jdbc:mysql://localhost:3306/user_schema

product-service:
  datasource:
    url: jdbc:mysql://localhost:3306/product_schema

阶段 2: 物理拆分(独立数据库)

# 不同的数据库实例
user-service:
  datasource:
    url: jdbc:mysql://user-db:3306/user_service

product-service:
  datasource:
    url: jdbc:mysql://product-db:3306/product_service

order-service:
  datasource:
    url: jdbc:mysql://order-db:3306/order_service

# 4、共享代码处理

抽取公共库:

common-lib/
├── common-core/          # 核心工具类
│   ├── Result.java
│   ├── PageResult.java
│   └── Constants.java
├── common-redis/         # Redis 封装
│   └── RedisService.java
├── common-security/      # 安全组件
│   ├── JwtTokenProvider.java
│   └── SecurityConfig.java
└── common-api/           # API 定义
    ├── UserDTO.java
    └── ProductDTO.java

服务引用公共库:

<!-- user-service pom.xml -->
<dependencies>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>common-core</artifactId>
    </dependency>
    <dependency>
        <groupId>com.example</groupId>
        <artifactId>common-security</artifactId>
    </dependency>
</dependencies>

# 五、微服务通信模式

# 1、同步通信

RESTful API:

// 商品服务提供 API
@RestController
@RequestMapping("/api/products")
public class ProductController {
    
    @GetMapping("/{id}")
    public Result<ProductDTO> getProduct(@PathVariable Long id) {
        Product product = productService.getById(id);
        return Result.success(ProductMapper.toDTO(product));
    }
}

// 订单服务调用商品服务
@Service
public class OrderService {
    
    @Autowired
    private RestTemplate restTemplate;
    
    public Order createOrder(CreateOrderRequest request) {
        // 调用商品服务获取商品信息
        String url = "http://product-service/api/products/" + request.getProductId();
        ProductDTO product = restTemplate.getForObject(url, ProductDTO.class);
        
        // 创建订单
        Order order = new Order();
        order.setProductId(product.getId());
        order.setProductName(product.getName());
        order.setPrice(product.getPrice());
        
        return orderRepository.save(order);
    }
}

gRPC:

// product.proto
syntax = "proto3";

service ProductService {
  rpc GetProduct(GetProductRequest) returns (ProductResponse);
}

message GetProductRequest {
  int64 id = 1;
}

message ProductResponse {
  int64 id = 1;
  string name = 2;
  double price = 3;
}
// 订单服务调用商品服务(gRPC)
@Service
public class OrderService {
    
    @Autowired
    private ProductServiceGrpc.ProductServiceBlockingStub productStub;
    
    public Order createOrder(CreateOrderRequest request) {
        // gRPC 调用
        ProductResponse product = productStub.getProduct(
            GetProductRequest.newBuilder()
                .setId(request.getProductId())
                .build()
        );
        
        Order order = new Order();
        order.setProductId(product.getId());
        order.setProductName(product.getName());
        order.setPrice(product.getPrice());
        
        return orderRepository.save(order);
    }
}

# 2、异步通信

基于消息队列:

// 订单服务发送订单创建事件
@Service
public class OrderService {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    public Order createOrder(CreateOrderRequest request) {
        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setProductId(request.getProductId());
        order.setStatus(OrderStatus.PENDING);
        
        orderRepository.save(order);
        
        // 发送订单创建事件
        OrderCreatedEvent event = new OrderCreatedEvent();
        event.setOrderId(order.getId());
        event.setUserId(order.getUserId());
        event.setProductId(order.getProductId());
        
        rabbitTemplate.convertAndSend("order.exchange", "order.created", event);
        
        return order;
    }
}

// 库存服务监听订单创建事件
@Component
public class OrderEventListener {
    
    @Autowired
    private InventoryService inventoryService;
    
    @RabbitListener(queues = "inventory.order.created")
    public void handleOrderCreated(OrderCreatedEvent event) {
        // 扣减库存
        inventoryService.decreaseStock(event.getProductId(), event.getQuantity());
    }
}

// 物流服务监听订单创建事件
@Component
public class OrderEventListener {
    
    @Autowired
    private ShippingService shippingService;
    
    @RabbitListener(queues = "shipping.order.created")
    public void handleOrderCreated(OrderCreatedEvent event) {
        // 创建物流单
        shippingService.createShippingOrder(event.getOrderId());
    }
}

# 3、服务发现

使用 Nacos:

# 商品服务注册到 Nacos
spring:
  application:
    name: product-service
  cloud:
    nacos:
      discovery:
        server-addr: nacos-server:8848
        namespace: production
        group: DEFAULT_GROUP
// 订单服务通过服务名调用商品服务
@Service
public class OrderService {
    
    @Autowired
    private RestTemplate restTemplate;  // 已配置 @LoadBalanced
    
    public Order createOrder(CreateOrderRequest request) {
        // 使用服务名(自动负载均衡)
        String url = "http://product-service/api/products/" + request.getProductId();
        ProductDTO product = restTemplate.getForObject(url, ProductDTO.class);
        
        // ...
    }
}

# 4、API 网关

统一入口:

客户端
  │
  ↓
┌──────────────┐
│  API Gateway │ (Spring Cloud Gateway / Kong)
└──────────────┘
  │
  ├─→ [用户服务]
  ├─→ [商品服务]
  ├─→ [订单服务]
  └─→ [支付服务]

Spring Cloud Gateway 配置:

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

网关功能:

  • ✅ 路由转发
  • ✅ 负载均衡
  • ✅ 认证鉴权
  • ✅ 限流熔断
  • ✅ 日志监控
  • ✅ 协议转换

# 六、数据一致性解决方案

# 1、分布式事务问题

场景: 下单需要同时操作订单服务和库存服务。

下单流程:
1. 订单服务: 创建订单
2. 库存服务: 扣减库存
3. 支付服务: 创建支付单

问题: 如何保证这3个操作要么全部成功,要么全部失败?

# 2、Saga 模式

编排式 Saga:

// 订单服务(Saga 编排器)
@Service
public class OrderSagaOrchestrator {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private InventoryServiceClient inventoryClient;
    
    @Autowired
    private PaymentServiceClient paymentClient;
    
    @Transactional
    public Order createOrder(CreateOrderRequest request) {
        // 1. 创建订单(本地事务)
        Order order = new Order();
        order.setStatus(OrderStatus.PENDING);
        orderRepository.save(order);
        
        try {
            // 2. 调用库存服务扣减库存
            inventoryClient.decreaseStock(request.getProductId(), request.getQuantity());
            
            // 3. 调用支付服务创建支付单
            paymentClient.createPayment(order.getId(), order.getAmount());
            
            // 4. 全部成功,更新订单状态
            order.setStatus(OrderStatus.CONFIRMED);
            orderRepository.save(order);
            
            return order;
            
        } catch (Exception e) {
            // 补偿操作
            try {
                inventoryClient.increaseStock(request.getProductId(), request.getQuantity());
            } catch (Exception ex) {
                log.error("库存回滚失败", ex);
            }
            
            order.setStatus(OrderStatus.FAILED);
            orderRepository.save(order);
            
            throw new OrderCreateException("订单创建失败", e);
        }
    }
}

事件驱动式 Saga:

// 1. 订单服务: 创建订单并发送事件
@Service
public class OrderService {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Transactional
    public Order createOrder(CreateOrderRequest request) {
        Order order = new Order();
        order.setStatus(OrderStatus.PENDING);
        orderRepository.save(order);
        
        // 发送订单创建事件
        OrderCreatedEvent event = new OrderCreatedEvent(order.getId(), request);
        rabbitTemplate.convertAndSend("saga.exchange", "order.created", event);
        
        return order;
    }
}

// 2. 库存服务: 监听事件并扣减库存
@Component
public class InventorySagaListener {
    
    @RabbitListener(queues = "saga.inventory.order.created")
    @Transactional
    public void handleOrderCreated(OrderCreatedEvent event) {
        try {
            inventoryService.decreaseStock(event.getProductId(), event.getQuantity());
            
            // 发送库存扣减成功事件
            InventoryDecreasedEvent successEvent = new InventoryDecreasedEvent(event.getOrderId());
            rabbitTemplate.convertAndSend("saga.exchange", "inventory.decreased", successEvent);
            
        } catch (Exception e) {
            // 发送库存扣减失败事件
            InventoryDecreaseFailedEvent failEvent = new InventoryDecreaseFailedEvent(event.getOrderId());
            rabbitTemplate.convertAndSend("saga.exchange", "inventory.decrease.failed", failEvent);
        }
    }
}

// 3. 订单服务: 监听库存扣减结果
@Component
public class OrderSagaListener {
    
    @RabbitListener(queues = "saga.order.inventory.decreased")
    @Transactional
    public void handleInventoryDecreased(InventoryDecreasedEvent event) {
        // 库存扣减成功,继续下一步(调用支付服务)
        PaymentCreateEvent paymentEvent = new PaymentCreateEvent(event.getOrderId());
        rabbitTemplate.convertAndSend("saga.exchange", "payment.create", paymentEvent);
    }
    
    @RabbitListener(queues = "saga.order.inventory.failed")
    @Transactional
    public void handleInventoryFailed(InventoryDecreaseFailedEvent event) {
        // 库存扣减失败,订单标记为失败
        Order order = orderRepository.findById(event.getOrderId()).orElseThrow();
        order.setStatus(OrderStatus.FAILED);
        orderRepository.save(order);
    }
}

# 3、最终一致性

本地消息表:

@Service
public class OrderService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private OutboxEventRepository outboxRepository;
    
    @Transactional
    public Order createOrder(CreateOrderRequest request) {
        // 1. 创建订单
        Order order = new Order();
        order.setStatus(OrderStatus.PENDING);
        orderRepository.save(order);
        
        // 2. 保存待发送事件到本地消息表(同一事务)
        OutboxEvent event = new OutboxEvent();
        event.setEventType("ORDER_CREATED");
        event.setPayload(JSON.toJSONString(order));
        event.setStatus(EventStatus.PENDING);
        outboxRepository.save(event);
        
        return order;
    }
}

// 定时任务:扫描本地消息表并发送事件
@Component
public class OutboxEventPublisher {
    
    @Autowired
    private OutboxEventRepository outboxRepository;
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    @Scheduled(fixedDelay = 5000)
    @Transactional
    public void publishPendingEvents() {
        List<OutboxEvent> pendingEvents = outboxRepository.findByStatus(EventStatus.PENDING);
        
        for (OutboxEvent event : pendingEvents) {
            try {
                rabbitTemplate.convertAndSend("order.exchange", event.getEventType(), event.getPayload());
                
                event.setStatus(EventStatus.PUBLISHED);
                outboxRepository.save(event);
                
            } catch (Exception e) {
                log.error("发送事件失败: {}", event.getId(), e);
            }
        }
    }
}

# 4、TCC 模式

// Try-Confirm-Cancel 模式
public interface InventoryTccService {
    
    /**
     * Try: 预留库存
     */
    @Tcc(confirmMethod = "confirmDecrease", cancelMethod = "cancelDecrease")
    boolean tryDecrease(Long productId, Integer quantity);
    
    /**
     * Confirm: 确认扣减库存
     */
    boolean confirmDecrease(Long productId, Integer quantity);
    
    /**
     * Cancel: 释放预留库存
     */
    boolean cancelDecrease(Long productId, Integer quantity);
}

@Service
public class InventoryTccServiceImpl implements InventoryTccService {
    
    @Override
    public boolean tryDecrease(Long productId, Integer quantity) {
        // 冻结库存
        Inventory inventory = inventoryRepository.findByProductId(productId);
        inventory.setFrozen(inventory.getFrozen() + quantity);
        inventory.setAvailable(inventory.getAvailable() - quantity);
        inventoryRepository.save(inventory);
        return true;
    }
    
    @Override
    public boolean confirmDecrease(Long productId, Integer quantity) {
        // 确认扣减
        Inventory inventory = inventoryRepository.findByProductId(productId);
        inventory.setFrozen(inventory.getFrozen() - quantity);
        inventoryRepository.save(inventory);
        return true;
    }
    
    @Override
    public boolean cancelDecrease(Long productId, Integer quantity) {
        // 释放冻结库存
        Inventory inventory = inventoryRepository.findByProductId(productId);
        inventory.setFrozen(inventory.getFrozen() - quantity);
        inventory.setAvailable(inventory.getAvailable() + quantity);
        inventoryRepository.save(inventory);
        return true;
    }
}

# 七、微服务治理

# 1、服务限流

令牌桶算法:

@Configuration
public class RateLimitConfig {
    
    @Bean
    public RateLimiter orderRateLimiter() {
        // 每秒允许100个请求
        return RateLimiter.create(100);
    }
}

@RestController
public class OrderController {
    
    @Autowired
    private RateLimiter rateLimiter;
    
    @PostMapping("/orders")
    public Result createOrder(@RequestBody CreateOrderRequest request) {
        // 尝试获取令牌
        if (!rateLimiter.tryAcquire(1, 100, TimeUnit.MILLISECONDS)) {
            return Result.error("系统繁忙,请稍后重试");
        }
        
        Order order = orderService.createOrder(request);
        return Result.success(order);
    }
}

基于 Redis 的分布式限流:

@Component
public class DistributedRateLimiter {
    
    @Autowired
    private RedisTemplate<String, Long> redisTemplate;
    
    /**
     * 限流检查
     * @param key 限流key
     * @param limit 限流阈值
     * @param window 时间窗口(秒)
     */
    public boolean isAllowed(String key, int limit, int window) {
        String redisKey = "rate_limit:" + key + ":" + (System.currentTimeMillis() / (window * 1000));
        
        Long count = redisTemplate.opsForValue().increment(redisKey);
        
        if (count == 1) {
            redisTemplate.expire(redisKey, window, TimeUnit.SECONDS);
        }
        
        return count <= limit;
    }
}

# 2、服务熔断

使用 Resilience4j:

@Service
public class OrderService {
    
    @Autowired
    private ProductServiceClient productClient;
    
    @CircuitBreaker(name = "productService", fallbackMethod = "getProductFallback")
    @Retry(name = "productService")
    @TimeLimiter(name = "productService")
    public ProductDTO getProduct(Long productId) {
        return productClient.getById(productId);
    }
    
    public ProductDTO getProductFallback(Long productId, Exception e) {
        log.warn("商品服务调用失败,使用降级数据, productId={}", productId, e);
        
        // 返回默认商品信息
        ProductDTO product = new ProductDTO();
        product.setId(productId);
        product.setName("商品" + productId);
        product.setPrice(BigDecimal.ZERO);
        return product;
    }
}

配置:

resilience4j:
  circuitbreaker:
    instances:
      productService:
        registerHealthIndicator: true
        slidingWindowSize: 10              # 滑动窗口大小
        minimumNumberOfCalls: 5            # 最小调用次数
        failureRateThreshold: 50           # 失败率阈值50%
        waitDurationInOpenState: 10s       # 熔断后等待10秒
        permittedNumberOfCallsInHalfOpenState: 3
  
  retry:
    instances:
      productService:
        maxAttempts: 3                     # 最大重试3次
        waitDuration: 1s                   # 重试间隔1秒
  
  timelimiter:
    instances:
      productService:
        timeoutDuration: 3s                # 超时时间3秒

# 3、链路追踪

使用 SkyWalking:

# application.yml
skywalking:
  agent:
    service_name: ${spring.application.name}
    collector:
      backend_service: skywalking-oap:11800

自定义 Span:

@Service
public class OrderService {
    
    @Autowired
    private Tracer tracer;
    
    public Order createOrder(CreateOrderRequest request) {
        Span span = tracer.createEntrySpan("createOrder", null);
        
        try {
            span.tag("user_id", request.getUserId().toString());
            span.tag("product_id", request.getProductId().toString());
            
            // 业务逻辑
            Order order = doCreateOrder(request);
            
            span.tag("order_id", order.getId().toString());
            return order;
            
        } catch (Exception e) {
            span.errorOccurred();
            span.log(e);
            throw e;
        } finally {
            tracer.stopSpan();
        }
    }
}

# 4、日志聚合

ELK Stack:

应用服务 → Filebeat → Logstash → Elasticsearch → Kibana

Logback 配置:

<configuration>
    <appender name="JSON" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <customFields>{"service":"${spring.application.name}"}</customFields>
        </encoder>
    </appender>
    
    <root level="INFO">
        <appender-ref ref="JSON" />
    </root>
</configuration>

结构化日志:

@Slf4j
@Service
public class OrderService {
    
    public Order createOrder(CreateOrderRequest request) {
        String traceId = MDC.get("traceId");
        
        log.info("创建订单开始, traceId={}, userId={}, productId={}", 
                 traceId, request.getUserId(), request.getProductId());
        
        try {
            Order order = doCreateOrder(request);
            
            log.info("创建订单成功, traceId={}, orderId={}", traceId, order.getId());
            return order;
            
        } catch (Exception e) {
            log.error("创建订单失败, traceId={}, userId={}", traceId, request.getUserId(), e);
            throw e;
        }
    }
}

# 5、配置中心

使用 Nacos Config:

# bootstrap.yml
spring:
  application:
    name: order-service
  cloud:
    nacos:
      config:
        server-addr: nacos-server:8848
        namespace: production
        group: DEFAULT_GROUP
        file-extension: yaml
        shared-configs:
          - data-id: common-config.yaml
            refresh: true

动态刷新配置:

@RefreshScope
@RestController
public class ConfigController {
    
    @Value("${business.max-order-amount}")
    private BigDecimal maxOrderAmount;
    
    @Value("${business.discount-rate}")
    private BigDecimal discountRate;
    
    @GetMapping("/config")
    public Map<String, Object> getConfig() {
        Map<String, Object> config = new HashMap<>();
        config.put("maxOrderAmount", maxOrderAmount);
        config.put("discountRate", discountRate);
        return config;
    }
}

# 八、部署与运维

# 1、容器化

Dockerfile:

FROM openjdk:17-jdk-alpine

WORKDIR /app

COPY target/order-service-1.0.0.jar app.jar

ENV JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC"

EXPOSE 8080

ENTRYPOINT java $JAVA_OPTS -jar app.jar

Docker Compose(本地开发):

version: '3.8'

services:
  user-service:
    build: ./user-service
    ports:
      - "8081:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=dev
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/user_service
    depends_on:
      - mysql
      - redis
  
  product-service:
    build: ./product-service
    ports:
      - "8082:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=dev
    depends_on:
      - mysql
      - redis
  
  order-service:
    build: ./order-service
    ports:
      - "8083:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=dev
    depends_on:
      - mysql
      - redis
  
  mysql:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=root123
    volumes:
      - mysql-data:/var/lib/mysql
  
  redis:
    image: redis:7-alpine
    volumes:
      - redis-data:/data

volumes:
  mysql-data:
  redis-data:

# 2、Kubernetes 部署

Deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
  labels:
    app: order-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
      - name: order-service
        image: myregistry/order-service:1.0.0
        ports:
        - containerPort: 8080
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "production"
        - name: SPRING_CLOUD_NACOS_DISCOVERY_SERVER_ADDR
          value: "nacos-server:8848"
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "1Gi"
            cpu: "1000m"
        livenessProbe:
          httpGet:
            path: /actuator/health/liveness
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10

Service:

apiVersion: v1
kind: Service
metadata:
  name: order-service
spec:
  selector:
    app: order-service
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: ClusterIP

HPA(自动扩缩容):

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: order-service-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: order-service
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

# 3、CI/CD 流水线

GitLab CI:

# .gitlab-ci.yml
stages:
  - build
  - test
  - package
  - deploy

variables:
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

build:
  stage: build
  image: maven:3.8-openjdk-17
  script:
    - mvn clean compile
  cache:
    paths:
      - .m2/repository

test:
  stage: test
  image: maven:3.8-openjdk-17
  script:
    - mvn test
  coverage: '/Total.*?([0-9]{1,3})%/'

package:
  stage: package
  image: maven:3.8-openjdk-17
  script:
    - mvn package -DskipTests
    - docker build -t myregistry/order-service:$CI_COMMIT_SHA .
    - docker push myregistry/order-service:$CI_COMMIT_SHA
  only:
    - master

deploy-production:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl set image deployment/order-service order-service=myregistry/order-service:$CI_COMMIT_SHA
    - kubectl rollout status deployment/order-service
  only:
    - master
  when: manual

# 4、灰度发布

基于 Istio 的金丝雀发布:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: order-service
spec:
  hosts:
  - order-service
  http:
  - match:
    - headers:
        x-canary:
          exact: "true"
    route:
    - destination:
        host: order-service
        subset: v2
  - route:
    - destination:
        host: order-service
        subset: v1
      weight: 90
    - destination:
        host: order-service
        subset: v2
      weight: 10
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: order-service
spec:
  host: order-service
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

# 九、监控告警

# 1、监控体系

四个黄金指标:

指标 说明 阈值
延迟(Latency) 请求响应时间 P99 < 200ms
流量(Traffic) 每秒请求数(QPS) 根据容量规划
错误(Errors) 错误率 < 0.1%
饱和度(Saturation) 资源使用率 CPU < 70%, Memory < 80%

Prometheus + Grafana:

# application.yml
management:
  endpoints:
    web:
      exposure:
        include: "*"
  metrics:
    export:
      prometheus:
        enabled: true
    tags:
      application: ${spring.application.name}

自定义指标:

@Component
public class OrderMetrics {
    
    private final Counter orderCreatedCounter;
    private final Timer orderCreateTimer;
    private final Gauge orderPendingGauge;
    
    public OrderMetrics(MeterRegistry registry) {
        this.orderCreatedCounter = Counter.builder("orders.created")
                .description("订单创建总数")
                .tag("service", "order-service")
                .register(registry);
        
        this.orderCreateTimer = Timer.builder("orders.create.time")
                .description("订单创建耗时")
                .tag("service", "order-service")
                .register(registry);
        
        this.orderPendingGauge = Gauge.builder("orders.pending", this, OrderMetrics::getPendingCount)
                .description("待处理订单数")
                .register(registry);
    }
    
    public void recordOrderCreated() {
        orderCreatedCounter.increment();
    }
    
    public void recordOrderCreateTime(Runnable task) {
        orderCreateTimer.record(task);
    }
    
    private double getPendingCount() {
        // 查询待处理订单数
        return orderRepository.countByStatus(OrderStatus.PENDING);
    }
}

# 2、告警规则

Prometheus AlertManager:

groups:
- name: order-service-alerts
  interval: 30s
  rules:
  # 错误率告警
  - alert: HighErrorRate
    expr: rate(http_server_requests_seconds_count{status=~"5.."}[5m]) > 0.01
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "服务错误率过高"
      description: "{{ $labels.application }} 错误率超过1%, 当前值: {{ $value }}"
  
  # 响应时间告警
  - alert: HighLatency
    expr: histogram_quantile(0.99, rate(http_server_requests_seconds_bucket[5m])) > 0.2
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "服务响应时间过长"
      description: "{{ $labels.application }} P99延迟超过200ms, 当前值: {{ $value }}"
  
  # CPU 使用率告警
  - alert: HighCPUUsage
    expr: process_cpu_usage > 0.8
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: "CPU使用率过高"
      description: "{{ $labels.application }} CPU使用率超过80%, 当前值: {{ $value }}"
  
  # 内存使用率告警
  - alert: HighMemoryUsage
    expr: jvm_memory_used_bytes / jvm_memory_max_bytes > 0.9
    for: 10m
    labels:
      severity: critical
    annotations:
      summary: "内存使用率过高"
      description: "{{ $labels.application }} 内存使用率超过90%, 当前值: {{ $value }}"

# 十、常见问题与解决方案

# 1、服务雪崩

问题: 一个服务故障导致级联失败。

解决方案:

  • ✅ 熔断降级(Hystrix/Resilience4j)
  • ✅ 超时控制
  • ✅ 限流保护
  • ✅ 舱壁隔离

# 2、链路过长

问题: A → B → C → D → E,调用链过长导致延迟累加。

解决方案:

  • ✅ 异步化:使用消息队列解耦
  • ✅ 服务聚合:在网关层聚合多个服务
  • ✅ 数据冗余:减少跨服务调用

# 3、数据一致性

问题: 分布式事务难以保证。

解决方案:

  • ✅ 最终一致性(本地消息表、事务消息)
  • ✅ Saga 模式
  • ✅ TCC 模式
  • ✅ 业务补偿

# 4、服务数量爆炸

问题: 微服务拆分过细,服务数量过多。

解决方案:

  • ✅ 合理的拆分粒度(单个服务1-5万行代码)
  • ✅ 服务合并:将相关服务合并
  • ✅ 服务分层:核心服务 + 聚合服务

# 5、测试复杂度

问题: 微服务环境下集成测试困难。

解决方案:

  • ✅ 契约测试(Pact)
  • ✅ 服务虚拟化(WireMock)
  • ✅ 完善的单元测试
  • ✅ 自动化测试流水线

# 十一、总结

# 微服务的核心价值

  1. 独立部署: 每个服务独立发布,互不影响
  2. 技术异构: 不同服务可以使用不同技术栈
  3. 故障隔离: 单个服务故障不影响整体
  4. 按需扩展: 根据负载情况独立扩展
  5. 团队自治: 小团队独立开发和维护

# 架构演进建议

阶段 建议
初创期 单体应用,快速迭代
成长期 垂直拆分,模块化
扩张期 核心服务微服务化
成熟期 全面微服务,云原生

# 最佳实践

  1. 渐进式演进: 不要一次性全部拆分
  2. 业务优先: 先拆分变更频繁的业务
  3. 监控先行: 完善的监控体系是基础
  4. 自动化: CI/CD、测试、部署全自动化
  5. 团队能力: 团队必须具备分布式系统经验

# 微服务不是银弹

适合微服务:

  • ✅ 大型复杂系统
  • ✅ 高并发高流量
  • ✅ 团队规模大
  • ✅ 快速迭代需求

不适合微服务:

  • ❌ 小型简单系统
  • ❌ 团队规模小
  • ❌ 缺乏运维能力
  • ❌ 业务不稳定

微服务架构是现代软件系统扩展性的最佳实践,但也带来了复杂度的提升。只有在正确的场景下,采用正确的方式实施,才能真正发挥微服务的价值。

祝你变得更强!

编辑 (opens new window)
#微服务#架构演进#服务拆分#分布式系统
上次更新: 2025/12/18
高扩展-无状态服务设计
高扩展-弹性伸缩设计

← 高扩展-无状态服务设计 高扩展-弹性伸缩设计→

最近更新
01
AI编程时代的一些心得
09-11
02
Claude Code 最佳实践(个人版)
08-01
03
高扩展-弹性伸缩设计
06-05
更多文章>
Theme by Vdoing | Copyright © 2018-2025 京ICP备2021021832号-2 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式