Chapter 08

微服务基础

Spring Cloud 核心组件全景,服务注册发现,OpenFeign 声明式调用,Resilience4j 熔断器,API 网关。

单体架构 vs 微服务的取舍

微服务不是银弹,也不是"更先进"的必然选择。在决定采用微服务架构前,需要认真评估成本与收益。

单体架构的优势

  • 开发简单,本地调试方便
  • 事务边界清晰(单一 DB)
  • 部署运维成本低
  • 性能好(无网络调用开销)
  • 适合小团队(< 5 人)

微服务的适用场景

  • 不同模块需要独立扩缩容
  • 大型团队需要并行开发
  • 技术异构(不同语言/框架)
  • 部分模块需要高可用隔离
  • 业务复杂度已超过单体边界

核心概念名词解释

服务注册与发现
服务启动时向注册中心(Eureka/Nacos/Consul)上报自己的地址和元数据;调用方从注册中心查询目标服务的实例列表,通过负载均衡选择一个实例发起调用。无需硬编码 IP:Port。
OpenFeign
Spring Cloud 提供的声明式 HTTP 客户端。通过定义接口 + 注解,无需手写 RestTemplate 代码,自动集成负载均衡、熔断、日志等功能。调用远程服务像调用本地方法一样简单。
LoadBalancer(负载均衡)
Spring Cloud LoadBalancer(替代旧版 Ribbon)在客户端侧实现负载均衡,从注册中心获取实例列表,按轮询(Round-Robin)或随机(Random)策略选择实例。
熔断器(Circuit Breaker)
防止级联故障的保护机制。当某个服务持续失败时,熔断器"断开"——后续请求直接返回降级响应,不再等待超时。一段时间后进入半开状态,尝试少量请求,若成功则"闭合"恢复正常。
Resilience4j
轻量级容错库,Spring Cloud 推荐的 Hystrix 替代品。提供熔断器(CircuitBreaker)、限流(RateLimiter)、重试(Retry)、舱壁隔离(Bulkhead)、超时(TimeLimiter)等模式。
服务网格(Service Mesh)
将服务间通信的横切关注点(负载均衡、熔断、认证、链路追踪)从应用代码中剥离,下沉到基础设施层(Sidecar Proxy,如 Envoy)。Istio 是最流行的服务网格实现。

Spring Cloud 核心组件全景

┌─────────────────────────────────────────────────────────────────┐ │ Spring Cloud 生态全景 │ └─────────────────────────────────────────────────────────────────┘ 客户端请求 │ ▼ ┌──────────────────────────────────────┐ │ Spring Cloud Gateway(API 网关) │ ← 路由、鉴权、限流、日志 │ 路由规则:/user-service/** → user-svc │ │ 路由规则:/order-service/** → ord-svc │ └──────────────────────────────────────┘ │ │ ▼ ▼ ┌──────────────┐ ┌──────────────────┐ │ User │ │ Order Service │ │ Service │ │ │ │ │ │ @FeignClient │ ─── 调用 → Product Service │ │ │ Resilience4j │ ─── 熔断降级 └──────────────┘ └──────────────────┘ │ │ └─────────┬───────┘ │ 所有服务注册/发现 ▼ ┌─────────────────────┐ │ Nacos / Eureka │ ← 服务注册中心 + 配置中心 │ 注册表: │ │ user-service → [...] │ │ order-service → [...]│ └─────────────────────┘ 分布式链路追踪:Micrometer + Zipkin / Jaeger 配置管理:Spring Cloud Config / Nacos Config

OpenFeign 声明式客户端

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
// 主启动类开启 Feign
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication { ... }

// 定义 Feign 客户端接口
@FeignClient(
    name = "product-service",      // 注册中心的服务名
    fallback = ProductClientFallback.class  // 降级实现
)
public interface ProductClient {

    @GetMapping("/products/{id}")
    ProductDTO getProduct(@PathVariable Long id);

    @PostMapping("/products/{id}/decrease-stock")
    void decreaseStock(@PathVariable Long id,
                       @RequestBody StockDecreaseRequest req);
}

// 降级实现(熔断后返回默认数据)
@Component
public class ProductClientFallback implements ProductClient {

    @Override
    public ProductDTO getProduct(Long id) {
        // 降级:返回默认商品信息
        return ProductDTO.builder().id(id).name("商品暂时不可用").build();
    }

    @Override
    public void decreaseStock(Long id, StockDecreaseRequest req) {
        throw new ServiceUnavailableException("库存服务暂时不可用");
    }
}

Resilience4j 熔断器配置

resilience4j:
  circuitbreaker:
    instances:
      product-service:           # 针对 product-service 的熔断配置
        sliding-window-size: 10  # 滑动窗口大小(10次请求)
        failure-rate-threshold: 50  # 失败率 ≥ 50% 时熔断
        wait-duration-in-open-state: 10s  # 断开状态等待 10s
        permitted-number-of-calls-in-half-open-state: 3
        automatic-transition-from-open-to-half-open-enabled: true
  retry:
    instances:
      product-service:
        max-attempts: 3
        wait-duration: 500ms
        retry-exceptions:
          - java.net.ConnectException  # 只重试连接异常

Spring Cloud Gateway 路由配置

spring:
  cloud:
    gateway:
      routes:
        - id: user-service
          uri: lb://user-service   # lb:// 使用负载均衡
          predicates:
            - Path=/api/users/**
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter  # 限流过滤器
              args:
                redis-rate-limiter.replenishRate: 100   # 每秒 100 个令牌
                redis-rate-limiter.burstCapacity: 200

        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          filters:
            - name: CircuitBreaker
              args:
                name: order-service-cb
                fallbackUri: forward:/fallback/orders
Tip 微服务不是银弹。团队少于 5 人、业务处于探索期、服务间边界不清晰时,强行拆分微服务往往弊大于利。建议先用良好的模块化单体(Modular Monolith)积累业务理解,当某个模块真的需要独立扩缩容时再拆分。
Warning 微服务中的分布式事务是最大挑战。避免使用两阶段提交(2PC),优先考虑业务可接受的最终一致性方案:Saga 模式(将分布式事务拆解为一系列本地事务)或者借助 Seata AT 模式自动管理。