微服务架构

难度等级:⭐⭐⭐⭐ 前置知识:Web 后端开发、数据存储 后续衔接:架构设计、DevOps

学习路径


一、微服务基础

1.1 什么是微服务

微服务架构(Microservices Architecture)是一种将单一应用程序拆分为一组小型服务的方法,每个服务运行在独立的进程中,服务之间通过轻量级通信机制(通常是 HTTP/REST 或 gRPC)进行协作。每个服务围绕业务能力构建,可以独立部署、独立扩展、独立技术栈。

单体架构的痛点

微服务的优势

微服务的挑战

何时选择微服务

微服务不是银弹。当团队规模较小(<10人)、业务简单、快速验证阶段,单体架构更合适。当系统复杂度上升、团队规模扩大、需要独立扩展和快速迭代时,才考虑向微服务演进。Martin Fowler 提出的”单体优先”(MonolithFirst)策略建议:先从单体开始,随着业务增长逐步拆分。

1.2 服务拆分原则

服务拆分是微服务架构中最关键的决策之一。拆分过粗,退化为分布式单体;拆分过细,带来不必要的网络开销和运维负担。

单一职责原则(SRP)

每个服务应该只有一个变更的理由,围绕一个明确的业务能力(Business Capability)构建。例如,电商系统中的订单服务只负责订单的创建、查询、状态流转,不处理库存扣减或支付逻辑。

领域驱动设计(DDD)指导拆分

DDD 提供了系统化的拆分方法论:

拆分步骤

  1. 识别业务领域:梳理核心域、支撑域、通用域
  2. 划定限界上下文:根据业务边界而非技术边界拆分
  3. 定义服务契约:明确服务间的 API 接口和数据格式
  4. 设计数据边界:每个服务拥有独立数据库,避免共享表
  5. 渐进式拆分:从单体中逐步剥离服务,而非一次性重写

常见拆分误区

服务粒度参考

服务类型 方法数量 团队规模 数据库
过细 < 50 1-2人 独立
合理 50-200 2-5人(Two-Pizza Team) 独立
过粗 > 200 5-10人 可能共享

1.3 服务通信

微服务之间的通信是架构的核心环节,主要分为同步和异步两种模式。

同步通信

同步通信中,调用方等待被调用方返回结果,行为类似本地函数调用。

// .NET HttpClient 调用示例
var client = _httpClientFactory.CreateClient("OrderService");
var response = await client.GetAsync($"/api/orders/{orderId}");
var order = await response.Content.ReadFromJsonAsync<Order>();
// Spring Boot RestTemplate 调用示例
ResponseEntity<Order> response = restTemplate.getForEntity(
    "http://order-service/api/orders/{id}",
    Order.class, orderId
);
// gRPC 服务定义
service OrderService {
  rpc GetOrder (OrderRequest) returns (OrderResponse);
  rpc StreamOrders (StreamRequest) returns (stream Order);
}

异步通信

异步通信中,调用方发送消息后不等待立即返回,通过消息中间件解耦服务。

// CAP 发布事件示例
await _capPublisher.PublishAsync("order.created", new OrderCreatedEvent {
    OrderId = orderId,
    Amount = amount
});

通信方式选型

场景 推荐方式 原因
需要即时响应 REST/gRPC 同步获取结果
高性能内部调用 gRPC 二进制协议,低延迟
事件通知 消息队列 解耦,异步处理
削峰填谷 Kafka/RocketMQ 高吞吐,持久化
多消费者 发布/订阅 扇出,独立处理

通信最佳实践


二、.NET 微服务

2.1 Ocelot API Gateway

Ocelot 是 .NET 生态中最流行的开源 API 网关,负责将客户端请求路由到后端微服务,并提供限流、认证、日志聚合等横切关注点的统一处理。

核心功能

配置示例

{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/orders/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        { "Host": "localhost", "Port": 5001 }
      ],
      "UpstreamPathTemplate": "/orders/{everything}",
      "UpstreamHttpMethod": [ "GET", "POST" ],
      "RateLimitOptions": {
        "ClientWhitelist": [],
        "EnableRateLimiting": true,
        "Period": "1s",
        "PeriodTimespan": 1,
        "Limit": 10
      },
      "AuthenticationOptions": {
        "AuthenticationProviderKey": "Bearer",
        "AllowedScopes": [ "orders.read" ]
      }
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:5000",
    "ServiceDiscoveryProvider": {
      "Host": "localhost",
      "Port": 8500,
      "Type": "Consul"
    }
  }
}

Program.cs 注册

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOcelot();

var app = builder.Build();
await app.UseOcelot();
app.Run();

网关部署模式

Ocelot 的局限

Ocelot 基于 .NET,性能在高并发场景下不如 Envoy、Nginx 等原生网关。对于超高吞吐场景,可考虑 YARP(Yet Another Reverse Proxy),这是微软官方推出的新一代反向代理,性能更优且与 .NET 生态深度集成。

2.2 Polly 弹性处理

Polly 是 .NET 的弹性与瞬态故障处理库,提供重试、熔断、超时、舱壁隔离、缓存等策略,是构建健壮微服务的基础组件。

重试策略(Retry)

处理瞬态故障(网络抖动、服务短暂不可用),通过重试提高成功率。

var retryPolicy = Policy
    .Handle<HttpRequestException>()
    .OrResult<HttpResponseMessage>(r => !r.IsSuccessStatusCode)
    .WaitAndRetryAsync(
        retryCount: 3,
        sleepDurationProvider: attempt => TimeSpan.FromSeconds(Math.Pow(2, attempt)),
        onRetry: (outcome, timespan, attempt, context) =>
        {
            _logger.LogWarning("第 {Attempt} 次重试,等待 {Timespan}ms",
                attempt, timespan.TotalMilliseconds);
        });

var response = await retryPolicy.ExecuteAsync(() => _httpClient.GetAsync(url));

熔断策略(Circuit Breaker)

当失败率达到阈值时,快速失败(Fail Fast),避免持续调用注定失败的服务,给下游服务恢复时间。

var circuitBreakerPolicy = Policy
    .Handle<Exception>()
    .CircuitBreakerAsync(
        exceptionsAllowedBeforeBreaking: 5,      // 连续 5 次失败后熔断
        durationOfBreak: TimeSpan.FromSeconds(30), // 熔断 30 秒
        onBreak: (ex, duration) => _logger.LogWarning("熔断开启 {Duration}s", duration.TotalSeconds),
        onReset: () => _logger.LogInformation("熔断关闭,恢复正常"),
        onHalfOpen: () => _logger.LogInformation("熔断半开,尝试放行一次")
    );

熔断器三态:

超时策略(Timeout)

var timeoutPolicy = Policy.TimeoutAsync<HttpResponseMessage>(
    TimeSpan.FromSeconds(5),
    TimeoutStrategy.Pessimistic
);

舱壁隔离(Bulkhead)

限制并发调用数量,防止某个服务的故障耗尽所有线程池资源。

var bulkheadPolicy = Policy.BulkheadAsync<HttpResponseMessage>(
    maxParallelization: 10,    // 最大并发 10 个
    maxQueuingActions: 5,      // 排队队列长度 5
    onBulkheadRejected: async context =>
    {
        _logger.LogError("舱壁已满,请求被拒绝");
    });

策略包装(PolicyWrap)

将多个策略组合使用,形成完整的弹性处理链。

var policyWrap = Policy.WrapAsync(
    bulkheadPolicy,      // 最外层:舱壁隔离
    circuitBreakerPolicy, // 第二层:熔断
    retryPolicy,         // 第三层:重试
    timeoutPolicy        // 最内层:超时
);

var result = await policyWrap.ExecuteAsync(async () =>
    await _httpClient.GetAsync(url));

与 HttpClientFactory 集成

builder.Services.AddHttpClient("OrderService")
    .AddPolicyHandler(retryPolicy)
    .AddPolicyHandler(circuitBreakerPolicy)
    .AddPolicyHandler(timeoutPolicy);

2.3 服务注册发现

服务注册发现是微服务架构的基础设施,解决”服务在哪里”的问题。服务启动时向注册中心注册自己的地址,调用方通过注册中心查询目标服务的地址列表。

Consul 集成

Consul 是 HashiCorp 推出的服务网格解决方案,提供服务注册发现、健康检查、KV 存储、多数据中心等功能。

// 服务注册
var consulClient = new ConsulClient(config => config.Address = new Uri("http://localhost:8500"));

var registration = new AgentServiceRegistration
{
    ID = $"order-service-{Guid.NewGuid():N}",
    Name = "order-service",
    Address = "localhost",
    Port = 5001,
    Tags = new[] { "v1", "production" },
    Check = new AgentServiceCheck
    {
        HTTP = "http://localhost:5001/health",
        Interval = TimeSpan.FromSeconds(10),
        Timeout = TimeSpan.FromSeconds(5),
        DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(30)
    }
};

await consulClient.Agent.ServiceRegister(registration);

Nacos 集成

Nacos 是阿里巴巴开源的服务发现与配置管理平台,在 .NET 中可通过 nacos-sdk-csharp 集成。

builder.Services.AddNacosAspNet(c =>
{
    c.ServerAddresses = new[] { "http://localhost:8848" };
    c.Namespace = "production";
    c.ServiceName = "order-service";
    c.GroupName = "DEFAULT_GROUP";
    c.Weight = 1.0;
});

注册中心对比

特性 Consul Nacos Eureka
CAP 理论 CP(强一致) AP/CP 可切换 AP(高可用)
健康检查 HTTP/TCP/Script HTTP/TCP 心跳
配置中心 KV 存储 内置支持 不支持
多数据中心 原生支持 支持 不支持
语言生态 多语言 Java/.NET Java
运维复杂度 中等 较低

服务发现的两种模式

服务下线与优雅关闭

服务关闭时应主动从注册中心注销,避免流量继续路由到已下线实例。

// 优雅关闭
app.Lifetime.ApplicationStopping.Register(async () =>
{
    await consulClient.Agent.ServiceDeregister(registration.ID);
    _logger.LogInformation("服务已从 Consul 注销");
});

2.4 CAP 事件总线

CAP 是 .NET 平台下的分布式事务解决方案,基于本地消息表模式实现服务间的最终一致性,同时支持事件总线的发布/订阅功能。

本地消息表模式

本地消息表是保证业务操作与消息发送原子性的经典方案。核心思路:将消息发送与业务数据保存在同一个本地事务中,然后通过后台任务轮询发送未确认的消息。

// 订单创建时使用 CAP
[Route("api/orders")]
public class OrderController : ControllerBase
{
    private readonly ICapPublisher _capPublisher;
    private readonly AppDbContext _dbContext;

    [HttpPost]
    public async Task<IActionResult> CreateOrder([FromBody] CreateOrderRequest request)
    {
        using var transaction = _dbContext.Database.BeginTransaction(_capPublisher, autoCommit: false);
        try
        {
            // 1. 创建订单(本地事务)
            var order = new Order { /* ... */ };
            _dbContext.Orders.Add(order);
            await _dbContext.SaveChangesAsync();

            // 2. 发布事件(与订单在同一事务中)
            await _capPublisher.PublishAsync("order.created", new OrderCreatedEvent
            {
                OrderId = order.Id,
                UserId = order.UserId,
                Amount = order.TotalAmount
            });

            // 3. 提交事务(订单和消息同时提交)
            await transaction.CommitAsync();
            return Ok(order.Id);
        }
        catch
        {
            await transaction.RollbackAsync();
            throw;
        }
    }
}

消息订阅

public class OrderEventHandler : ICapSubscribe
{
    private readonly InventoryService _inventoryService;

    [CapSubscribe("order.created")]
    public async Task HandleOrderCreated(OrderCreatedEvent @event)
    {
        // 扣减库存
        await _inventoryService.DeductStock(@event.OrderId, @event.Items);
    }
}

消息可靠性保证

CAP 支持的消息中间件

CAP Dashboard

CAP 内置 Web Dashboard,可查看消息发布/订阅状态、重试失败消息、手动重发消息。

builder.Services.AddCap(x =>
{
    x.UseEntityFramework<AppDbContext>();
    x.UseRabbitMQ("localhost");
    x.UseDashboard(); // 启用 Dashboard,默认路径 /cap
});

2.5 Dapr 分布式运行时

Dapr(Distributed Application Runtime)是微软开源的可移植、事件驱动的运行时,通过 Sidecar 模式为应用提供分布式构建块,使开发者专注于业务逻辑而非分布式系统复杂性。

核心构建块

Sidecar 模式

Dapr 通过 Sidecar 模式运行,每个应用实例旁边运行一个 Dapr Sidecar 进程,应用通过 HTTP 或 gRPC 与 Sidecar 通信,Sidecar 负责处理所有分布式系统复杂性。

┌─────────────┐     HTTP/gRPC     ┌──────────────┐
│   应用程序    │ ◄──────────────► │  Dapr Sidecar │
│  (你的代码)   │     本地调用      │   (基础设施)   │
└─────────────┘                   └──────────────┘
                                           │
                                  ┌────────▼────────┐
                                  │  外部基础设施     │
                                  │  Redis/K8s/MQ   │
                                  └─────────────────┘

服务调用示例

// 使用 Dapr SDK 调用其他服务
var daprClient = new DaprClientBuilder().Build();

// 同步调用
var order = await daprClient.InvokeMethodAsync<Order>(
    HttpMethod.Get,
    "order-service",
    $"api/orders/{orderId}");

状态管理示例

// 保存状态
await daprClient.SaveStateAsync("redis-store", "order-123", order);

// 读取状态
var order = await daprClient.GetStateAsync<Order>("redis-store", "order-123");

// 带 ETag 的乐观并发控制
var (state, etag) = await daprClient.GetStateAndETagAsync<Order>("redis-store", "order-123");
await daprClient.TrySaveStateAsync("redis-store", "order-123", order, etag);

Dapr 的优势

Dapr 的局限


三、Spring Cloud 微服务

3.1 Spring Cloud Gateway

Spring Cloud Gateway 是 Spring 官方推出的基于 Spring Boot 2.x、Spring WebFlux 和 Project Reactor 构建的响应式 API 网关,取代了已停止维护的 Zuul 1.x。

核心概念

路由配置示例

spring:
  cloud:
    gateway:
      routes:
        - id: order-service
          uri: lb://order-service  # lb 表示负载均衡
          predicates:
            - Path=/api/orders/**
            - Method=GET,POST
            - Header=X-Request-Source, (web|mobile)
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
            - name: CircuitBreaker
              args:
                name: orderCircuitBreaker
                fallbackUri: forward:/fallback/order

自定义全局过滤器

@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        if (StringUtils.isBlank(token) || !token.startsWith("Bearer ")) {
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        // 验证 JWT 并传递用户信息给下游
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -100; // 值越小优先级越高
    }
}

动态路由

配合 Nacos 或 Consul 实现路由配置的动态刷新,无需重启网关。

@RestController
@RequestMapping("/routes")
public class DynamicRouteController {

    private final RouteDefinitionWriter routeDefinitionWriter;
    private final ApplicationEventPublisher publisher;

    @PostMapping("/add")
    public String addRoute(@RequestBody RouteDefinition definition) {
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        publisher.publishEvent(new RefreshRoutesEvent(this));
        return "Route added successfully";
    }
}

网关高可用

生产环境通常部署多个网关实例,前端通过 Nginx 或云负载均衡器分发流量。网关本身无状态,可水平扩展。

3.2 注册中心

注册中心是微服务架构的”电话簿”,存储服务实例的网络地址信息,供服务发现使用。

Nacos

Nacos 是阿里巴巴开源的动态服务发现、配置管理和服务管理平台,目前已成为 Spring Cloud Alibaba 生态的核心组件。

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
        namespace: production
        group: DEFAULT_GROUP
        metadata:
          version: 1.0.0
          region: cn-shanghai

Nacos 的核心优势:

Eureka

Eureka 是 Netflix 开源的服务注册发现组件,Spring Cloud Netflix 的核心部分。

# Eureka Server 配置
server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
# Eureka Client 配置
spring:
  application:
    name: order-service
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka

Eureka 的设计哲学是 AP 优先(可用性 > 一致性):

Eureka 2.x 已停止开源维护,新项目不建议使用。

Consul

Consul 在 Java 生态中通过 Spring Cloud Consul 集成,特性与 .NET 生态类似。

注册中心选型对比

维度 Nacos Eureka Consul
一致性协议 Raft(CP)/ Distro(AP) 最终一致(AP) Raft(CP)
健康检查 TCP/HTTP/MySQL/Script 心跳 TCP/HTTP/Script/gRPC
配置管理 内置支持 不支持 KV 存储
多数据中心 支持 不支持 原生支持
社区活跃度 高(阿里维护) 低(已停止维护) 高(HashiCorp 维护)
部署运维 简单 简单 中等
适用场景 Spring Cloud 项目 遗留系统 多语言/多云环境

服务下线与优雅关闭

Spring Cloud 2020+ 支持 Actuator 优雅关闭端点,服务关闭时先注销注册信息,等待已有请求完成后再停止。

management:
  endpoint:
    shutdown:
      enabled: true
  endpoints:
    web:
      exposure:
        include: shutdown

3.3 OpenFeign 服务调用

OpenFeign 是声明式 HTTP 客户端,通过接口注解定义服务调用,底层自动处理序列化、负载均衡、重试等逻辑。

基本使用

// 定义 Feign 客户端接口
@FeignClient(name = "order-service", path = "/api/orders")
public interface OrderServiceClient {

    @GetMapping("/{orderId}")
    Order getOrder(@PathVariable("orderId") Long orderId);

    @PostMapping
    Order createOrder(@RequestBody CreateOrderRequest request);

    @GetMapping("/user/{userId}")
    List<Order> getOrdersByUser(@PathVariable("userId") Long userId);
}

// 使用 Feign 客户端
@Service
public class UserService {

    @Autowired
    private OrderServiceClient orderClient;

    public UserDTO getUserWithOrders(Long userId) {
        User user = userRepository.findById(userId).orElseThrow();
        List<Order> orders = orderClient.getOrdersByUser(userId);
        return new UserDTO(user, orders);
    }
}

负载均衡

OpenFeign 默认集成 Spring Cloud LoadBalancer(替代了已停止维护的 Ribbon)。

spring:
  cloud:
    loadbalancer:
      retry:
        enabled: true  # 启用重试

超时与重试配置

spring:
  cloud:
    openfeign:
      client:
        config:
          order-service:  # 针对特定服务
            connect-timeout: 3000
            read-timeout: 5000
            logger-level: basic
          default:  # 全局默认
            connect-timeout: 2000
            read-timeout: 3000

自定义配置类

@Configuration
public class FeignConfig {

    @Bean
    public RequestInterceptor authRequestInterceptor() {
        return template -> {
            // 在每个请求中添加认证 Header
            String token = SecurityContextHolder.getToken();
            template.header("Authorization", "Bearer " + token);
        };
    }

    @Bean
    public Retryer feignRetryer() {
        return new Retryer.Default(100, 1000, 3); // 初始间隔、最大间隔、最大次数
    }
}

Feign + Sentinel 集成

通过 fallback 实现服务降级。

@FeignClient(
    name = "order-service",
    path = "/api/orders",
    fallbackFactory = OrderServiceFallbackFactory.class
)
public interface OrderServiceClient {
    @GetMapping("/{orderId}")
    Order getOrder(@PathVariable("orderId") Long orderId);
}

@Component
public class OrderServiceFallbackFactory implements FallbackFactory<OrderServiceClient> {

    @Override
    public OrderServiceClient create(Throwable cause) {
        return new OrderServiceClient() {
            @Override
            public Order getOrder(Long orderId) {
                // 降级逻辑:返回缓存或默认值
                return Order.empty(orderId);
            }
        };
    }
}

OpenFeign 最佳实践

3.4 Sentinel 限流熔断

Sentinel 是阿里巴巴开源的流量治理组件,提供流量控制、熔断降级、系统自适应保护等功能,是 Hystrix 的替代方案。

流量控制

基于 QPS 或并发线程数限制流量,支持直接拒绝或 Warm Up(预热)模式。

// 定义资源
@SentinelResource(value = "getOrder", blockHandler = "handleBlock")
public Order getOrder(Long orderId) {
    return orderRepository.findById(orderId).orElse(null);
}

// 流控处理
public Order handleBlock(Long orderId, BlockException ex) {
    log.warn("请求被限流: {}", ex.getClass().getSimpleName());
    return Order.empty(orderId);
}

流控规则配置

List<FlowRule> rules = new ArrayList<>();
FlowRule rule = new FlowRule("getOrder");
rule.setGrade(RuleConstant.FLOW_GRADE_QPS);  // 按 QPS 限流
rule.setCount(100);                          // 阈值 100 QPS
rule.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_RATE_LIMITER); // 匀速排队
rule.setMaxQueueingTimeMs(500);              // 最大排队时间 500ms
rules.add(rule);
FlowRuleManager.loadRules(rules);

熔断降级

基于异常比例、异常数或慢调用比例触发熔断。

// 慢调用比例熔断
DegradeRule rule = new DegradeRule("getOrder")
    .setGrade(CircuitBreakerStrategy.SLOW_REQUEST_RATIO.getType())
    .setCount(0.5)           // 慢调用比例超过 50%
    .setTimeWindow(10)       // 熔断时长 10 秒
    .setSlowRatioThreshold(3); // 响应时间超过 3 秒视为慢调用

系统自适应保护

根据系统负载(CPU 使用率、系统 Load、入口 QPS 等)自动调整流量,防止系统被打垮。

SystemRule rule = new SystemRule();
rule.setHighestSystemLoad(10.0);   // 系统 Load 超过 10 时触发保护
rule.setHighestCpuUsage(0.8);      // CPU 使用率超过 80%
rule.setQps(5000);                 // 总入口 QPS 限制
SystemRuleManager.loadRules(Collections.singletonList(rule));

Sentinel Dashboard

Sentinel 提供可视化的管理控制台,支持实时监控、规则配置、簇点链路查看。

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080  # Dashboard 地址
        port: 8719                 # 与 Dashboard 通信的端口
      eager: true                  # 应用启动时立即连接 Dashboard

Sentinel vs Hystrix

特性 Sentinel Hystrix
隔离策略 信号量(轻量) 线程池/信号量
熔断策略 慢调用/异常比例/异常数 异常比例
实时监控 支持(Dashboard) 支持(Hystrix Dashboard)
规则配置 动态配置,实时生效 静态配置为主
系统保护 自适应保护 不支持
热点限流 支持(参数级) 不支持

3.5 Spring Cloud Stream

Spring Cloud Stream 是构建消息驱动微服务的框架,通过统一的编程模型屏蔽底层消息中间件的差异。

核心概念

基本使用

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

    @StreamListener(Processor.INPUT)
    public void handleMessage(String message) {
        log.info("Received: {}", message);
    }
}
spring:
  cloud:
    stream:
      bindings:
        input:
          destination: order-events
          group: order-service-group
        output:
          destination: order-events
      binders:
        defaultRabbit:
          type: rabbit
          environment:
            spring:
              rabbitmq:
                host: localhost
                port: 5672

函数式编程模型(推荐)

Spring Cloud Stream 3.x 推荐使用函数式编程模型。

@Bean
public Function<OrderEvent, OrderResult> processOrder() {
    return event -> {
        log.info("Processing order: {}", event.getOrderId());
        return new OrderResult(event.getOrderId(), "SUCCESS");
    };
}

消息分区配置

spring:
  cloud:
    stream:
      bindings:
        input:
          destination: orders
          group: order-service
          consumer:
            partitioned: true
            instanceCount: 3
            instanceIndex: 0
      producer:
        partition-key-expression: headers.userId
        partition-count: 3

3.6 配置中心

微服务架构中,配置管理是核心需求。Nacos Config 提供集中化、动态刷新的配置管理。

基本集成

# bootstrap.yml
spring:
  application:
    name: order-service
  cloud:
    nacos:
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        namespace: production
        group: DEFAULT_GROUP

动态刷新

使用 @RefreshScope 注解使 Bean 支持配置刷新。

@RestController
@RefreshScope
public class ConfigController {

    @Value("${order.timeout:5000}")
    private Integer orderTimeout;

    @GetMapping("/timeout")
    public Integer getTimeout() {
        return orderTimeout;
    }
}

配置共享

Nacos 支持共享配置,多个服务可以共用同一份配置。

spring:
  cloud:
    nacos:
      config:
        shared-configs:
          - data-id: common-config.yaml
            group: SHARED_GROUP
            refresh: true

配置中心最佳实践

3.7 链路追踪

分布式系统中,一个请求可能跨越多个服务,链路追踪帮助定位性能瓶颈和故障根因。

Sleuth + Zipkin

Spring Cloud Sleuth 自动为请求添加 TraceId 和 SpanId,Zipkin 收集并可视化追踪数据。

spring:
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      probability: 1.0  # 采样率 100%

TraceId 传递

Sleuth 自动在 HTTP Header 和消息队列中传递 TraceId,确保链路连续。

客户端请求
  │ TraceId: abc123
  ▼
[Gateway] ──SpanId: span1──►
  │
  ▼
[OrderService] ──SpanId: span2──►
  │
  ▼
[PaymentService] ──SpanId: span3

日志集成

在日志中输出 TraceId,便于问题排查。

logging:
  pattern:
    level: "%5p [${spring.application.name:},%X{traceId:-},%X{spanId:-}]"

日志输出示例

INFO [order-service,abc123def456,abc123def789] Processing order 12345

SkyWalking(替代方案)

对于 Java 生态,SkyWalking 是另一个流行的 APM 工具,支持无侵入式探针注入。

# JVM 参数添加 SkyWalking 探针
-javaagent:/path/to/skywalking-agent.jar
-Dskywalking.agent.service_name=order-service
-Dskywalking.collector.backend_service=localhost:11800

四、微服务通用概念

4.1 API 设计风格

RESTful API

REST(Representational State Transfer)是最主流的 API 设计风格,基于 HTTP 方法和资源路径。

核心原则:

GET    /api/orders          # 获取订单列表
GET    /api/orders/123      # 获取单个订单
POST   /api/orders          # 创建订单
PUT    /api/orders/123      # 更新订单
DELETE /api/orders/123      # 删除订单

GraphQL

GraphQL 允许客户端精确指定需要的字段,避免过度获取或不足。

适用场景:

query {
  user(id: "123") {
    name
    orders(status: "ACTIVE") {
      id
      totalAmount
      items {
        productName
        quantity
      }
    }
  }
}

gRPC

gRPC 基于 Protocol Buffers,适合高性能内部服务通信。

优势:

syntax = "proto3";

message OrderRequest {
  int64 order_id = 1;
}

message OrderResponse {
  int64 order_id = 1;
  string status = 2;
  double total_amount = 3;
}

service OrderService {
  rpc GetOrder (OrderRequest) returns (OrderResponse);
}

选型建议

场景 推荐风格 原因
面向外部开发者/公众 RESTful 通用标准,易理解
前端灵活数据查询 GraphQL 按需获取,减少请求次数
服务间内部通信 gRPC 高性能,强类型
移动端弱网环境 GraphQL/gRPC 减少数据量

4.2 分布式事务

微服务拆分后,原本在同一数据库的事务现在跨多个服务,需要新的解决方案。

Saga 模式

Saga 将长事务拆分为多个本地事务,每个本地事务有对应的补偿操作。

订单创建 Saga 流程:
1. 订单服务:创建订单(补偿:取消订单)
2. 库存服务:扣减库存(补偿:恢复库存)
3. 支付服务:扣款(补偿:退款)
4. 物流服务:创建配送单(补偿:取消配送)

TCC 模式

TCC(Try-Confirm-Cancel)三阶段提交:

@LocalTCC
public interface PaymentTCCService {

    @TwoPhaseBusinessAction(name = "paymentTry", commitMethod = "paymentConfirm", rollbackMethod = "paymentCancel")
    boolean paymentTry(@BusinessActionContextParameter(paramName = "orderId") String orderId,
                       @BusinessActionContextParameter(paramName = "amount") BigDecimal amount);

    boolean paymentConfirm(BusinessActionContext context);

    boolean paymentCancel(BusinessActionContext context);
}

Seata 框架

Seata 是阿里巴巴开源的分布式事务解决方案,支持 AT、TCC、SAGA、XA 四种模式。

分布式事务选型

模式 一致性 性能 侵入性 适用场景
2PC/XA 强一致 同构数据库
TCC 最终一致 高性能要求
Saga 最终一致 长事务
本地消息表 最终一致 简单场景

4.3 Service Mesh

Service Mesh(服务网格)是基础设施层,处理服务间通信,将流量管理、安全、可观测性从业务代码中剥离。

核心概念

Istio

Istio 是最成熟的开源 Service Mesh 实现,基于 Envoy 代理。

核心能力:

# Istio VirtualService 示例:灰度发布
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: order-service
spec:
  hosts:
  - order-service
  http:
  - match:
    - headers:
        x-version:
          exact: v2
    route:
    - destination:
        host: order-service
        subset: v2
    - destination:
        host: order-service
        subset: v1
      weight: 10

Sidecar 模式的优势

Service Mesh 的代价


五、微服务实战考量

5.1 监控与可观测性

可观测性包含三大支柱:指标(Metrics)、日志(Logs)、链路(Traces)。

指标(Metrics)

# Prometheus 配置示例
scrape_configs:
  - job_name: 'spring-boot-app'
    metrics_path: '/actuator/prometheus'
    scrape_interval: 15s
    static_configs:
      - targets: ['order-service:8080']

日志(Logs)

{
  "timestamp": "2026-04-24T10:30:00Z",
  "level": "INFO",
  "service": "order-service",
  "traceId": "abc123def456",
  "spanId": "abc123def789",
  "message": "Order created successfully",
  "orderId": "12345"
}

链路(Traces)

告警策略

5.2 灰度发布与蓝绿部署

蓝绿部署

同时运行两个完全相同的生产环境(蓝色和绿色),一个处理生产流量,另一个部署新版本后切换。

优势:

缺点:

金丝雀发布(Canary)

逐步将流量从旧版本迁移到新版本,观察指标后再决定是否继续。

流量切换步骤:
1. 新版本部署 1% 流量
2. 观察 10 分钟,无异常则提升到 10%
3. 继续观察,提升到 50%
4. 最终全量 100%

Istio 灰度发布

# 按权重分配流量
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: order-service-canary
spec:
  hosts:
  - order-service
  http:
  - route:
    - destination:
        host: order-service
        subset: v1
      weight: 90
    - destination:
        host: order-service
        subset: v2
      weight: 10

基于 Header 的灰度

# 特定用户群体访问新版本
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: order-service-header
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

六、学习资源推荐

书籍

在线课程

开源项目参考

实践建议