Skip to content
第 217 / 250 章架构⏱ 14 分钟阅读

第 217 章:微服务入门

学习目标

  • 理解微服务与单体的差异
  • 掌握服务拆分原则
  • 学会服务通信方式
  • 了解微服务治理基础

一、单体 vs 微服务

1.1 单体架构

所有功能打包成一个应用,共享一个数据库。

优点:简单、调试容易、部署简单

缺点:

  • 团队耦合,代码冲突多
  • 扩展必须整体扩(浪费资源)
  • 一个 bug 让整个系统挂
  • 技术栈绑定

1.2 微服务架构

按业务拆分为独立服务,各自部署。

优点:

  • 独立部署、独立扩缩
  • 故障隔离
  • 技术异构(每个服务可用不同语言)
  • 团队自治

缺点:

  • 分布式复杂性(网络、事务、监控)
  • 运维成本高
  • 数据一致性难

二、服务拆分

2.1 拆分原则

原则说明
单一职责一个服务只做一件事
业务边界按 DDD 限界上下文
高内聚低耦合服务内部紧,服务之间松
可独立部署不影响其他服务
团队规模"两个披萨原则"(< 8 人)

2.2 拆分方式

方式一:按业务能力

电商系统
├── 用户中心
├── 商品中心
├── 订单中心
├── 支付中心
└── 库存中心

方式二:按 DDD 限界上下文

├── 销售上下文(下单)
├── 商品上下文(SPU/SKU)
├── 库存上下文(扣减/锁定)
└── 支付上下文(交易/退款)

2.3 反例:拆错的微服务

拆得过细(纳米服务 / 分布式单体):

订单服务拆为:
├── 创建订单
├── 修改订单
├── 查询订单
├── 取消订单
└── 订单状态

→ 简单 CRUD 拆成 5 个服务,纯运维灾难

合理粒度:按业务价值切分,服务数 = 子域数

三、服务通信

3.1 同步 vs 异步

维度同步异步
一致性弱(最终一致)
性能受限于最慢高吞吐
耦合高(知道对方地址)低(只发事件)
失败处理即时失败重试 / DLQ
适用关键路径副作用、通知

3.2 RESTful

最常见的同步通信方式。

java
@RestController
@RequestMapping("/api/orders")
public class OrderController {

    @PostMapping
    public Result<Order> create(@RequestBody OrderRequest req) {
        return orderService.create(req);
    }
}

调用方:

java
@Service
public class OrderApplicationService {

    @Autowired
    @LoadBalanced
    private RestTemplate restTemplate;

    public Order create(OrderRequest req) {
        // 调用库存服务同步扣减
        String stockUrl = "http://inventory-service/api/inventory/deduct";
        InventoryResponse resp = restTemplate.postForObject(stockUrl, req, InventoryResponse.class);
        // ...
    }
}

3.3 OpenFeign

声明式 HTTP 客户端,Spring Cloud 标配。

java
@FeignClient(name = "inventory-service")
public interface InventoryClient {

    @PostMapping("/api/inventory/deduct")
    Result<InventoryResponse> deduct(@RequestBody DeductRequest req);

    @GetMapping("/api/inventory/check/{skuId}")
    Result<Boolean> checkStock(@PathVariable String skuId);
}
java
@Service
@RequiredArgsConstructor
public class OrderService {
    private final InventoryClient inventoryClient;

    public void createOrder() {
        Result<InventoryResponse> result = inventoryClient.deduct(...);
        if (!result.isSuccess()) {
            throw new BizException("库存不足");
        }
    }
}

3.4 gRPC

高性能 RPC,基于 HTTP/2 + Protobuf。

inventory.proto:

protobuf
syntax = "proto3";

service InventoryService {
  rpc Deduct(DeductRequest) returns (DeductResponse);
  rpc CheckStock(CheckRequest) returns (CheckResponse);
}

message DeductRequest {
  string sku_id = 1;
  int32 quantity = 2;
}

message DeductResponse {
  bool success = 1;
  string message = 2;
}
java
// Stub 调用
@GrpcClient("inventory-service")
private InventoryServiceGrpc.InventoryServiceBlockingStub stub;

public void deduct(String skuId, int qty) {
    DeductResponse resp = stub.deduct(
        DeductRequest.newBuilder()
            .setSkuId(skuId)
            .setQuantity(qty)
            .build()
    );
}

3.5 消息队列异步

java
// 发布者:订单服务
@Service
public class OrderService {
    @Autowired
    private KafkaTemplate<String, OrderEvent> kafka;

    public void createOrder() {
        Order order = ...;
        orderRepo.save(order);

        // 异步通知库存
        kafka.send("order-events", new OrderCreatedEvent(order));
    }
}

// 消费者:库存服务
@KafkaListener(topics = "order-events")
public void onOrderCreated(OrderCreatedEvent event) {
    inventoryService.lockStock(event.orderId(), event.items());
}

四、服务注册与发现

4.1 原理

4.2 Nacos

yaml
# application.yml
spring:
  application:
    name: order-service
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.1.10:8848

注册后:

bash
curl http://192.168.1.10:8848/nacos/v1/ns/catalog/instances?serviceName=order-service

调用方:

java
@FeignClient(name = "inventory-service")
public interface InventoryClient { ... }

五、API 网关

所有外部请求经网关统一入口。

5.1 Spring Cloud Gateway

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

        - id: payment-service
          uri: lb://payment-service
          predicates:
            - Path=/api/payments/**

5.2 Kong / APISIX

生产级网关,支持:

  • 路由、鉴权
  • 限流、熔断
  • 日志、监控
  • 插件生态

六、配置中心

集中管理配置,支持动态刷新。

yaml
# Nacos / Apollo / Consul
spring:
  cloud:
    nacos:
      config:
        server-addr: 192.168.1.10:8848
        file-extension: yaml
        refresh-enabled: true
java
@RefreshScope
@RestController
public class ConfigController {

    @Value("${order.timeout:3000}")
    private int timeout;
}

七、容错与熔断

7.1 服务雪崩

A 调用 B,B 调用 C,C 挂 → B 累积线程 → A 也挂

7.2 熔断器模式

状态行为
Closed正常调用,统计失败率
Open直接拒绝,降级
HalfOpen放行少量请求试探

7.3 Resilience4j

java
@Service
public class OrderService {

    @CircuitBreaker(name = "inventory", fallbackMethod = "fallback")
    public InventoryResponse checkStock(String skuId) {
        return inventoryClient.check(skuId);
    }

    // 降级方法
    public InventoryResponse fallback(String skuId, Throwable t) {
        log.warn("库存服务不可用,降级处理", t);
        return InventoryResponse.okWithCache(skuId);
    }
}

7.4 Sentinel(阿里)

java
@SentinelResource(value = "checkStock", blockHandler = "blockHandler")
public InventoryResponse checkStock(String skuId) {
    return inventoryClient.check(skuId);
}

public InventoryResponse blockHandler(String skuId, BlockException ex) {
    return InventoryResponse.busy();
}

八、分布式事务

8.1 问题

订单 + 库存 + 支付三个服务,无法用本地事务保证一致。

8.2 CAP 理论

分布式系统 P 必选,只能在 C 和 A 之间权衡。

8.3 BASE 理论

放弃强一致,追求基本可用 + 最终一致

原则含义
BA(Basically Available)基本可用,允许降级
S(Soft State)软状态,允许中间态
E(Eventually Consistent)最终一致

8.4 Saga 模式

长事务拆成多个本地事务 + 补偿动作。

实现:

  • Seata(阿里,Saga + AT + TCC)
  • Apache ServiceComb Saga

九、链路追踪

9.1 概念

用户请求
   ├─ 网关 (10ms)
   ├─ 订单 (20ms)
   │   ├─ 库存 RPC (15ms) ← 慢!
   │   └─ 支付 RPC (5ms)
   └─ 响应 (30ms)

9.2 Trace + Span

  • Trace:一次完整调用链
  • Span:每个调用节点
  • 通过 traceId 串联所有服务

9.3 Sleuth + Zipkin

xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
yaml
spring:
  zipkin:
    base-url: http://zipkin:9411
  sleuth:
    sampler:
      probability: 1.0

十、微服务架构图

十一、本章小结

组件作用
服务注册中心服务发现
API 网关统一入口、鉴权、限流
配置中心配置统一管理
熔断器容错、降级
消息队列异步解耦
链路追踪调用链可视化
监控指标采集与告警

动手练习

  1. 用 Spring Boot 实现 2 个简单微服务(用户、商品),用 RestTemplate 通信
  2. 用 Nacos 做服务注册与发现
  3. 用 OpenFeign 替换 RestTemplate,体验声明式调用
  4. 配置 Sentinel 熔断,模拟下游故障,观察降级行为

推荐阅读


下一章:第 218 章:微服务设计原则

本站基于 VitePress 构建 · 由 Codebook 团队维护