DDD与微服务
DDD与微服务
限界上下文作为服务边界
DDD 的限界上下文是划分微服务的最佳指导。每个微服务对应一个限界上下文,拥有独立的领域模型和数据存储。
电商系统微服务划分:
┌─────────────────────────────────────────────────────────────────┐
│ 电商平台 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 订单服务 │ │ 商品服务 │ │ 库存服务 │ │
│ │ (Order) │ │ (Product) │ │ (Inventory) │ │
│ │ │ │ │ │ │ │
│ │ - Order │ │ - Product │ │ - Stock │ │
│ │ - OrderItem │ │ - Category │ │ - Warehouse │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ └────────────────┼────────────────┘ │
│ │ │
│ 事件驱动通信 │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 支付服务 │ │ 用户服务 │ │ 物流服务 │ │
│ │ (Payment) │ │ (User) │ │ (Shipping) │ │
│ │ │ │ │ │ │ │
│ │ - Payment │ │ - Customer │ │ - Shipment │ │
│ │ - Refund │ │ - Address │ │ - Tracking │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
服务间通信
微服务间通信主要有同步调用和异步事件两种方式。
// 同步调用:使用 Feign Client
@FeignClient(name = "inventory-service")
public interface InventoryClient {
@PostMapping("/api/inventory/check")
CheckResult checkAvailability(@RequestBody CheckRequest request);
@PostMapping("/api/inventory/reserve")
void reserve(@RequestBody ReserveRequest request);
}
// 异步事件:使用消息队列
@Component
public class OrderEventPublisher {
private final KafkaTemplate<String, Object> kafkaTemplate;
public void publishOrderCreated(Order order) {
OrderCreatedEvent event = new OrderCreatedEvent(
order.getId().getValue(),
order.getCustomerId().getValue(),
order.getItems().stream()
.map(item -> new OrderItemDto(
item.getProductId().getValue(),
item.getQuantity()
))
.collect(Collectors.toList())
);
kafkaTemplate.send("order-events", event);
}
}
// 事件消费者
@Component
public class InventoryEventConsumer {
@KafkaListener(topics = "order-events")
public void handleOrderCreated(OrderCreatedEvent event) {
// 检查库存
for (OrderItemDto item : event.getItems()) {
if (!inventoryService.checkAvailability(
item.getProductId(), item.getQuantity())) {
throw new InsufficientInventoryException();
}
}
// 预留库存
inventoryService.reserve(event.getOrderId(), event.getItems());
}
}
数据一致性
微服务间的数据一致性通常采用最终一致性模式。
// Saga 模式:分布式事务
@Component
public class OrderSaga {
private final OrderService orderService;
private final InventoryClient inventoryClient;
private final PaymentClient paymentClient;
@SagaStep(order = 1, compensation = "cancelOrder")
public void createOrder(CreateOrderCommand command) {
orderService.createOrder(command);
}
@SagaStep(order = 2, compensation = "releaseInventory")
public void reserveInventory(String orderId) {
Order order = orderService.findById(orderId);
inventoryClient.reserve(orderId, order.getItems());
}
@SagaStep(order = 3, compensation = "cancelPayment")
public void processPayment(String orderId) {
Order order = orderService.findById(orderId);
paymentClient.charge(orderId, order.calculateTotal());
}
// 补偿操作
public void cancelOrder(String orderId) {
orderService.cancel(orderId);
}
public void releaseInventory(String orderId) {
inventoryClient.release(orderId);
}
public void cancelPayment(String orderId) {
paymentClient.refund(orderId);
}
}
服务划分原则
- 单一职责:每个服务只负责一个业务能力
- 高内聚:相关的功能放在同一个服务
- 松耦合:服务间通过明确的接口通信
- 数据自治:每个服务拥有自己的数据存储
DDD 的限界上下文为微服务划分提供了清晰的指导原则。