微服务架构设计原则
大约 9 分钟约 2796 字
微服务架构设计原则
简介
微服务架构将单体应用拆分为独立部署、独立演化的服务。理解服务拆分策略、通信模式、数据一致性和治理策略,有助于构建可扩展、可维护的分布式系统。
特点
服务拆分策略
按业务能力拆分
// 按业务能力(Business Capability)拆分
// 每个服务对应一个业务功能领域
// 电商系统拆分示例:
// ┌─────────────────────────────────────────┐
// │ API Gateway (BFF) │
// └──────────┬──────┬──────┬──────┬─────────┘
// │ │ │ │
// ┌──────┴──┐ ┌─┴───┐ ┌┴────┐ ┌┴────────┐
// │用户服务 │ │订单 │ │商品 │ │支付服务 │
// │Identity │ │Order│ │Prod │ │Payment │
// └─────────┘ └─────┘ └─────┘ └─────────┘
// ┌─────────┐ ┌─────┐ ┌─────┐
// │库存服务 │ │物流 │ │通知 │
// │Inventory│ │Ship │ │Notif│
// └─────────┘ └─────┘ └─────┘
// 每个服务的项目结构
// src/
// ├── UserService/
// │ ├── UserService.API/ — 控制器、中间件
// │ ├── UserService.Application/ — 用例、DTO
// │ ├── UserService.Domain/ — 实体、值对象、领域服务
// │ ├── UserService.Infrastructure/ — 仓储、外部服务
// │ └── UserService.Tests/
// ├── OrderService/
// │ └── ...
// 每个服务独立的 EF Core DbContext
public class UserDbContext : DbContext
{
public DbSet<User> Users => Set<User>();
public DbSet<UserProfile> Profiles => Set<UserProfile>();
public UserDbContext(DbContextOptions<UserDbContext> options) : base(options) { }
}
public class OrderDbContext : DbContext
{
public DbSet<Order> Orders => Set<Order>();
public DbSet<OrderItem> OrderItems => Set<OrderItem>();
public OrderDbContext(DbContextOptions<OrderDbContext> options) : base(options) { }
}
// 服务间不共享数据库,通过 API 或事件通信
// 用户服务只有 UserDbContext
// 订单服务只有 OrderDbContext按子域拆分(DDD)
// 按限界上下文(Bounded Context)拆分
// 每个子域有独立的领域模型
// 订单子域
public class Order // 订单上下文中的 Order
{
public Guid Id { get; private set; }
public OrderStatus Status { get; private set; }
public List<OrderItem> Items { get; private set; } = new();
public Address ShippingAddress { get; private set; }
// 订单上下文不关心用户密码、角色等信息
// 只保留 UserId 作为引用
public Guid UserId { get; private set; }
public void AddItem(ProductItem item, int quantity)
{
var existing = Items.FirstOrDefault(i => i.ProductId == item.ProductId);
if (existing != null)
{
existing.IncreaseQuantity(quantity);
}
else
{
Items.Add(new OrderItem(item.ProductId, item.ProductName, item.Price, quantity));
}
}
public void Submit()
{
if (!Items.Any()) throw new DomainException("订单不能为空");
Status = OrderStatus.Submitted;
// 发布领域事件
AddDomainEvent(new OrderSubmittedEvent(Id, UserId, Items.Select(i => i.ProductId).ToList()));
}
}
// 用户子域
public class User // 用户上下文中的 User
{
public Guid Id { get; private set; }
public string Email { get; private set; }
public string PasswordHash { get; private set; }
public UserProfile Profile { get; private set; }
// 用户上下文不关心订单信息
// 订单信息通过服务间调用获取
}
// 上下文映射(Context Map)
// 订单上下文 → 用户上下文:通过 UserId 引用(Customer-Supplier)
// 订单上下文 → 商品上下文:通过 ProductId 引用(Conformist)
// 订单上下文 → 库存上下文:通过事件驱动(Anti-Corruption Layer)服务间通信
同步通信(HTTP/gRPC)
// 服务间 HTTP 调用(使用 HttpClientFactory)
public class UserServiceClient
{
private readonly HttpClient _httpClient;
private readonly ILogger<UserServiceClient> _logger;
private readonly IAsyncPolicy<HttpResponseMessage> _retryPolicy;
public UserServiceClient(
HttpClient httpClient,
ILogger<UserServiceClient> logger)
{
_httpClient = httpClient;
_logger = logger;
// 重试策略
_retryPolicy = Policy<HttpResponseMessage>
.Handle<HttpRequestException>()
.OrResult(r => !r.IsSuccessStatusCode)
.WaitAndRetryAsync(3, attempt =>
TimeSpan.FromMilliseconds(Math.Pow(2, attempt) * 200));
}
public async Task<UserDto?> GetUserAsync(Guid userId, CancellationToken ct = default)
{
try
{
var response = await _retryPolicy.ExecuteAsync(async () =>
await _httpClient.GetAsync($"/api/users/{userId}", ct));
if (response.StatusCode == HttpStatusCode.NotFound)
return null;
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<UserDto>(ct);
}
catch (Exception ex)
{
_logger.LogError(ex, "获取用户 {UserId} 失败", userId);
throw;
}
}
public async Task<bool> ValidateUserAsync(Guid userId, CancellationToken ct = default)
{
try
{
var response = await _httpClient.GetAsync($"/api/users/{userId}/validate", ct);
return response.IsSuccessStatusCode;
}
catch
{
return false; // 降级:用户验证失败
}
}
}
// 注册
builder.Services.AddHttpClient<UserServiceClient>(client =>
{
client.BaseAddress = new Uri("https://user-service:8080");
client.Timeout = TimeSpan.FromSeconds(10);
});
// gRPC 服务间通信
// Protos/user.proto
// syntax = "proto3";
// service UserGrpcService {
// rpc GetUser (GetUserRequest) returns (UserResponse);
// rpc ValidateUser (ValidateUserRequest) returns (ValidateUserResponse);
// }
// gRPC 客户端
builder.Services.AddGrpcClient<UserGrpcService.UserGrpcServiceClient>(options =>
{
options.Address = new Uri("https://user-service:8080");
});
// 使用
public class OrderService
{
private readonly UserGrpcService.UserGrpcServiceClient _userClient;
public OrderService(UserGrpcService.UserGrpcServiceClient userClient)
{
_userClient = userClient;
}
public async Task<OrderDto> CreateOrderAsync(CreateOrderRequest request)
{
// gRPC 调用验证用户
var userResponse = await _userClient.GetUserAsync(new GetUserRequest { UserId = request.UserId });
// ...
}
}异步通信(事件驱动)
// 事件驱动架构 — 使用 RabbitMQ 或 Kafka
// 1. 定义事件
public record IntegrationEvent(
Guid EventId,
DateTime OccurredAt,
string EventType)
{
public Guid EventId { get; } = EventId == Guid.Empty ? Guid.NewGuid() : EventId;
public DateTime OccurredAt { get; } = OccurredAt == default ? DateTime.UtcNow : OccurredAt;
}
public record OrderCreatedEvent(
Guid OrderId,
Guid UserId,
List<OrderItemData> Items,
decimal TotalAmount) : IntegrationEvent(Guid.NewGuid(), DateTime.UtcNow, nameof(OrderCreatedEvent));
public record OrderPaidEvent(
Guid OrderId,
string TransactionId,
decimal Amount) : IntegrationEvent(Guid.NewGuid(), DateTime.UtcNow, nameof(OrderPaidEvent));
// 2. 事件发布器
public interface IEventBus
{
Task PublishAsync<TEvent>(TEvent @event, CancellationToken ct = default) where TEvent : IntegrationEvent;
}
// 3. RabbitMQ 实现
public class RabbitMQEventBus : IEventBus, IDisposable
{
private readonly IConnection _connection;
private readonly IModel _channel;
private readonly ILogger<RabbitMQEventBus> _logger;
private readonly JsonSerializerOptions _jsonOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
public RabbitMQEventBus(IConnectionFactory connectionFactory, ILogger<RabbitMQEventBus> logger)
{
_logger = logger;
_connection = connectionFactory.CreateConnection();
_channel = _connection.CreateModel();
}
public Task PublishAsync<TEvent>(TEvent @event, CancellationToken ct = default) where TEvent : IntegrationEvent
{
var exchangeName = typeof(TEvent).Name;
var routingKey = typeof(TEvent).Name;
_channel.ExchangeDeclare(exchangeName, ExchangeType.Fanout, durable: true);
var body = JsonSerializer.SerializeToUtf8Bytes(@event, _jsonOptions);
var properties = _channel.CreateBasicProperties();
properties.MessageId = @event.EventId.ToString();
properties.ContentType = "application/json";
properties.DeliveryMode = 2; // 持久化
_channel.BasicPublish(exchangeName, routingKey, properties, body);
_logger.LogInformation("发布事件: {EventType} ({EventId})", typeof(TEvent).Name, @event.EventId);
return Task.CompletedTask;
}
public void Dispose()
{
_channel?.Dispose();
_connection?.Dispose();
}
}
// 4. 事件消费
public class OrderCreatedConsumer : BackgroundService
{
private readonly IConnection _connection;
private readonly IServiceProvider _sp;
private readonly ILogger<OrderCreatedConsumer> _logger;
public OrderCreatedConsumer(
IConnectionFactory connectionFactory,
IServiceProvider sp,
ILogger<OrderCreatedConsumer> logger)
{
_sp = sp;
_logger = logger;
_connection = connectionFactory.CreateConnection();
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
var channel = _connection.CreateModel();
channel.ExchangeDeclare("OrderCreatedEvent", ExchangeType.Fanout, durable: true);
var queueName = channel.QueueDeclare("inventory-order-created", durable: true).QueueName;
channel.QueueBind(queueName, "OrderCreatedEvent", "");
var consumer = new EventingBasicConsumer(channel);
consumer.Received += async (model, ea) =>
{
try
{
var body = ea.Body.ToArray();
var evt = JsonSerializer.Deserialize<OrderCreatedEvent>(body);
using var scope = _sp.CreateScope();
var inventory = scope.ServiceProvider.GetRequiredService<IInventoryService>();
await inventory.ReserveStockAsync(evt.OrderId, evt.Items, stoppingToken);
channel.BasicAck(ea.DeliveryTag, false);
}
catch (Exception ex)
{
_logger.LogError(ex, "处理 OrderCreatedEvent 失败");
channel.BasicNack(ea.DeliveryTag, false, true); // 重试
}
};
channel.BasicConsume(queueName, autoAck: false, consumer);
return Task.CompletedTask;
}
}数据一致性
Saga 模式
// Saga 模式 — 分布式事务协调
// 编排式 Saga(Orchestration)
public class CreateOrderSaga
{
private readonly IEventBus _eventBus;
private readonly ILogger<CreateOrderSaga> _logger;
private readonly IOrderRepository _orderRepo;
private readonly IInventoryService _inventoryService;
private readonly IPaymentService _paymentService;
public CreateOrderSaga(
IEventBus eventBus,
ILogger<CreateOrderSaga> logger,
IOrderRepository orderRepo,
IInventoryService inventoryService,
IPaymentService paymentService)
{
_eventBus = eventBus;
_logger = logger;
_orderRepo = orderRepo;
_inventoryService = inventoryService;
_paymentService = paymentService;
}
public async Task ExecuteAsync(CreateOrderCommand command, CancellationToken ct)
{
var orderId = Guid.NewGuid();
try
{
// Step 1: 创建订单(Pending 状态)
var order = new Order(orderId, command.UserId, command.Items);
order.SetStatus(OrderStatus.Pending);
await _orderRepo.SaveAsync(order, ct);
// Step 2: 预留库存
await _inventoryService.ReserveStockAsync(orderId, command.Items, ct);
// Step 3: 扣款
var payment = await _paymentService.ChargeAsync(
command.UserId, order.TotalAmount, orderId, ct);
// Step 4: 确认订单
order.SetStatus(OrderStatus.Confirmed);
order.SetPaymentId(payment.TransactionId);
await _orderRepo.SaveAsync(order, ct);
// 发布事件
await _eventBus.PublishAsync(new OrderCreatedEvent(orderId, command.UserId,
command.Items, order.TotalAmount), ct);
_logger.LogInformation("订单 {OrderId} 创建成功", orderId);
}
catch (Exception ex)
{
_logger.LogError(ex, "订单 {OrderId} 创建失败,开始补偿", orderId);
// 补偿操作
await CompensateAsync(orderId, ct);
throw;
}
}
private async Task CompensateAsync(Guid orderId, CancellationToken ct)
{
try
{
// 回滚库存
await _inventoryService.ReleaseStockAsync(orderId, ct);
}
catch (Exception ex)
{
_logger.LogError(ex, "库存回滚失败: {OrderId}", orderId);
}
try
{
// 取消支付
await _paymentService.RefundAsync(orderId, ct);
}
catch (Exception ex)
{
_logger.LogError(ex, "退款失败: {OrderId}", orderId);
}
try
{
// 取消订单
var order = await _orderRepo.GetByIdAsync(orderId, ct);
if (order != null)
{
order.SetStatus(OrderStatus.Cancelled);
await _orderRepo.SaveAsync(order, ct);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "订单取消失败: {OrderId}", orderId);
}
}
}API Gateway
YARP 反向代理
// YARP (Yet Another Reverse Proxy) — 微服务网关
// 安装:dotnet add package Yarp.ReverseProxy
// appsettings.json 配置
// {
// "ReverseProxy": {
// "Routes": {
// "user-route": {
// "ClusterId": "user-cluster",
// "Match": { "Path": "/api/users/{**catch-all}" }
// },
// "order-route": {
// "ClusterId": "order-cluster",
// "Match": { "Path": "/api/orders/{**catch-all}" }
// }
// },
// "Clusters": {
// "user-cluster": {
// "Destinations": {
// "destination1": { "Address": "https://user-service:8080" }
// }
// },
// "order-cluster": {
// "Destinations": {
// "destination1": { "Address": "https://order-service:8080" }
// }
// }
// }
// }
// }
// Program.cs
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
app.MapReverseProxy();
// 自定义转换(添加请求头)
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
.AddTransforms(transformBuilderContext =>
{
transformBuilderContext.AddRequestTransform(async transformContext =>
{
// 添加关联 ID
var correlationId = transformContext.HttpContext.TraceIdentifier;
transformContext.ProxyRequest.Headers.Add("X-Correlation-Id", correlationId);
// 转发用户信息
var user = transformContext.HttpContext.User;
if (user.Identity?.IsAuthenticated == true)
{
var userId = user.FindFirst("sub")?.Value;
transformContext.ProxyRequest.Headers.Add("X-User-Id", userId ?? "");
}
});
});优点
缺点
总结
微服务拆分策略分为按业务能力和按子域(DDD)两种方式,核心原则是高内聚、低耦合。服务间通信:同步方式使用 HTTP/gRPC(适合实时查询),异步方式使用消息队列(适合解耦和最终一致性)。分布式事务使用 Saga 模式(编排式或协调式)实现补偿机制。API Gateway 使用 YARP 反向代理统一入口。关键设计原则:每服务独立数据库、服务间通过 API 或事件通信、每个服务拥有独立的领域模型。
关键知识点
- 先分清这个主题位于请求链路、后台任务链路还是基础设施链路。
- 服务端主题通常不只关心功能正确,还关心稳定性、性能和可观测性。
- 任何框架能力都要结合配置、生命周期、异常传播和外部依赖一起看。
- Kubernetes 主题必须同时看资源对象、调度行为、网络暴露和配置分发。
项目落地视角
- 画清请求进入、业务执行、外部调用、日志记录和错误返回的完整路径。
- 为关键链路补齐超时、重试、熔断、追踪和结构化日志。
- 把配置与敏感信息分离,并明确不同环境的差异来源。
- 上线前检查镜像、命名空间、探针、资源限制、Service/Ingress 和配置来源。
常见误区
- 只会堆中间件或组件,不知道它们在链路中的执行顺序。
- 忽略生命周期和线程池、连接池等运行时资源约束。
- 没有监控和测试就对性能或可靠性下结论。
- 只会 apply YAML,不理解对象之间的依赖关系。
进阶路线
- 继续向运行时行为、可观测性、发布治理和微服务协同深入。
- 把主题和数据库、缓存、消息队列、认证授权联动起来理解。
- 沉淀团队级模板,包括统一异常处理、配置约定和基础设施封装。
- 继续补齐调度、网络策略、存储、GitOps 和平台工程能力。
适用场景
- 当你准备把《微服务架构设计原则》真正落到项目里时,最适合先在一个独立模块或最小样例里验证关键路径。
- 适合 API 服务、后台任务、实时通信、认证授权和微服务协作场景。
- 当需求开始涉及稳定性、性能、可观测性和发布流程时,这类主题会成为基础设施能力。
落地建议
- 先定义请求链路与失败路径,再决定中间件、过滤器、服务边界和依赖方式。
- 为关键链路补日志、指标、追踪、超时与重试策略。
- 环境配置与敏感信息分离,避免把生产参数写死在代码或镜像里。
排错清单
- 先确认问题发生在路由、模型绑定、中间件、业务层还是基础设施层。
- 检查 DI 生命周期、配置来源、序列化规则和认证上下文。
- 查看线程池、连接池、缓存命中率和外部依赖超时。
复盘问题
- 如果把《微服务架构设计原则》放进你的当前项目,最先要验证的输入、输出和失败路径分别是什么?
- 《微服务架构设计原则》最容易在什么规模、什么边界条件下暴露问题?你会用什么指标或日志去确认?
- 相比默认实现或替代方案,采用《微服务架构设计原则》最大的收益和代价分别是什么?
