【架构实战】编排vs协同:微服务通信架构选型

一、微服务通信概述

微服务架构中,服务间通信是核心问题:

通信模式:

  • 同步通信(REST、gRPC)
  • 异步通信(消息队列、事件驱动)
  • 编排模式(Orchestration)
  • 协同模式(Choreography)

选型考虑因素:

  • 业务复杂度
  • 性能要求
  • 一致性需求
  • 可维护性

二、编排模式(Orchestration)

1. 核心概念

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                       编排模式                                   │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│              ┌───────────────────────┐                         │
│              │     编排器(Orchestrator)│                         │
│              │     中心化控制          │                         │
│              └───────────┬───────────┘                         │
│                          │                                       │
│            ┌─────────────┼─────────────┐                       │
│            │             │             │                       │
│            ▼             ▼             ▼                       │
│      ┌─────────┐   ┌─────────┐   ┌─────────┐              │
│      │ 服务A   │   │ 服务B   │   │ 服务C   │              │
│      └─────────┘   └─────────┘   └─────────┘              │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

2. 同步编排实现

java 复制代码
// 订单编排器
@Service
public class OrderOrchestrator {
    
    @Autowired
    private ProductService productService;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private LogisticsService logisticsService;
    
    @Transactional
    public OrderResult createOrder(OrderRequest request) {
        // 1. 验证商品
        List<Product> products = productService.validateProducts(request.getItems());
        
        // 2. 扣减库存
        inventoryService.deductStock(request.getItems());
        
        // 3. 创建订单
        Order order = orderService.createOrder(request);
        
        // 4. 处理支付
        PaymentResult payment = paymentService.processPayment(order);
        
        if (!payment.isSuccess()) {
            // 支付失败,回滚库存
            inventoryService.rollbackStock(request.getItems());
            throw new PaymentException("支付失败");
        }
        
        // 5. 触发配送
        logisticsService.createDelivery(order);
        
        // 6. 返回结果
        return OrderResult.builder()
            .orderId(order.getId())
            .paymentId(payment.getPaymentId())
            .build();
    }
}

3. 异步编排实现

java 复制代码
// Saga编排器
@Service
public class OrderSagaOrchestrator {
    
    @Autowired
    private KafkaTemplate kafkaTemplate;
    
    public String startOrderSaga(OrderRequest request) {
        String sagaId = UUID.randomUUID().toString();
        
        // 启动Saga
        SagaState state = SagaState.builder()
            .sagaId(sagaId)
            .currentStep(0)
            .status(SagaStatus.STARTED)
            .request(request)
            .build();
        
        // 保存Saga状态
        sagaStateStore.save(state);
        
        // 发送第一个步骤
        kafkaTemplate.send("saga-order", sagaId, new CreateOrderStep(sagaId, request));
        
        return sagaId;
    }
    
    // 处理Saga步骤结果
    public void handleStepResult(SagaStepResult result) {
        SagaState state = sagaStateStore.findById(result.getSagaId());
        
        if (result.isSuccess()) {
            // 步骤成功,执行下一步
            executeNextStep(state);
        } else {
            // 步骤失败,执行补偿
            compensate(state, result.getStep());
        }
    }
    
    private void executeNextStep(SagaState state) {
        SagaStep nextStep = getNextStep(state);
        
        if (nextStep == null) {
            // Saga完成
            state.setStatus(SagaStatus.COMPLETED);
            sagaStateStore.save(state);
            return;
        }
        
        state.setCurrentStep(nextStep.getStepNumber());
        state.setStatus(SagaStatus.PROCESSING);
        sagaStateStore.save(state);
        
        // 发送步骤消息
        kafkaTemplate.send("saga-order", state.getSagaId(), nextStep);
    }
    
    private void compensate(SagaState state, int failedStep) {
        state.setStatus(SagaStatus.COMPENSATING);
        sagaStateStore.save(state);
        
        // 逆向执行已完成步骤的补偿操作
        for (int i = failedStep - 1; i >= 0; i--) {
            SagaStep step = getStep(i);
            kafkaTemplate.send("saga-order-compensate", 
                state.getSagaId(), new CompensateCommand(step));
        }
    }
}

三、协同模式(Choreography)

1. 核心概念

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                       协同模式                                   │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   ┌─────────┐    事件    ┌─────────┐    事件    ┌─────────┐   │
│   │ 服务A   │ ────────▶ │ 服务B   │ ────────▶ │ 服务C   │   │
│   │         │ ◀──────── │         │ ◀──────── │         │   │
│   └─────────┘   命令    └─────────┘   命令    └─────────┘   │
│                                                                  │
│   服务自主决策,通过事件驱动协作                                  │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

2. 事件驱动实现

java 复制代码
// 订单服务 - 发布事件
@Service
public class OrderService {
    
    @Autowired
    private KafkaTemplate kafkaTemplate;
    
    public Order createOrder(OrderRequest request) {
        // 创建订单
        Order order = orderRepository.save(createOrder(request));
        
        // 发布订单创建事件
        kafkaTemplate.send("order-events", order.getId().toString(), 
            new OrderCreatedEvent(order));
        
        return order;
    }
}

// 库存服务 - 订阅事件
@Service
public class InventoryService {
    
    @KafkaListener(topics = "order-events", groupId = "inventory-group")
    public void handleOrderCreated(OrderCreatedEvent event) {
        // 扣减库存
        for (OrderItem item : event.getOrder().getItems()) {
            deductStock(item.getProductId(), item.getQuantity());
        }
        
        // 发布库存扣减成功事件
        kafkaTemplate.send("inventory-events", 
            event.getOrder().getId().toString(),
            new InventoryReservedEvent(event.getOrder()));
    }
}

// 支付服务 - 订阅事件
@Service
public class PaymentService {
    
    @KafkaListener(topics = "inventory-events", groupId = "payment-group")
    public void handleInventoryReserved(InventoryReservedEvent event) {
        // 检查库存是否充足
        if (event.isSuccess()) {
            // 处理支付
            PaymentResult result = processPayment(event.getOrder());
            
            if (result.isSuccess()) {
                // 发布支付成功事件
                kafkaTemplate.send("payment-events",
                    event.getOrder().getId().toString(),
                    new PaymentSucceededEvent(event.getOrder(), result));
            } else {
                // 发布支付失败事件(触发库存回滚)
                kafkaTemplate.send("payment-events",
                    event.getOrder().getId().toString(),
                    new PaymentFailedEvent(event.getOrder(), result.getReason()));
            }
        }
    }
}

// 物流服务 - 订阅事件
@Service
public class LogisticsService {
    
    @KafkaListener(topics = "payment-events", groupId = "logistics-group")
    public void handlePaymentSucceeded(PaymentSucceededEvent event) {
        // 创建物流
        Delivery delivery = createDelivery(event.getOrder());
        
        // 发布发货事件
        kafkaTemplate.send("logistics-events",
            event.getOrder().getId().toString(),
            new OrderShippedEvent(event.getOrder(), delivery));
    }
}

3. 协同模式的优势

java 复制代码
// 服务自治
@Service
public class OrderService {
    
    // 订单服务只需要关注订单相关的业务
    // 不需要知道支付、库存、物流的具体实现
    
    @KafkaListener(topics = "payment-events")
    public void handlePaymentResult(PaymentEvent event) {
        Order order = orderRepository.findById(event.getOrderId());
        
        if (event.isSuccess()) {
            order.setStatus(OrderStatus.PAID);
        } else {
            order.setStatus(OrderStatus.PAYMENT_FAILED);
            order.setFailureReason(event.getReason());
        }
        
        orderRepository.save(order);
        
        // 发布订单状态变更事件
        kafkaTemplate.send("order-events", order.getId().toString(),
            new OrderStatusChangedEvent(order));
    }
}

四、编排vs协同对比

1. 对比表

维度 编排模式 协同模式
中心化 强中心化 去中心化
复杂度 编排器复杂 各服务简单
耦合度 编排器与服务耦合 服务间松耦合
可追踪性 好(编排器控制) 差(需日志聚合)
性能 好(同步调用) 一般(异步消息)
故障处理 编排器统一处理 各服务自行处理
适用场景 复杂业务流程 简单事件流

2. 选择决策

复制代码
选择编排模式:
- 业务流程复杂,需要中心控制
- 需要强一致性
- 需要详细的执行追踪
- 团队习惯面向过程开发

选择协同模式:
- 业务流程简单,事件驱动
- 需要高可用和松耦合
- 团队习惯事件驱动开发
- 已有成熟的消息基础设施

五、混合架构

1. 组合使用

java 复制代码
// 主流程编排,子流程协同
@Service
public class HybridOrderService {
    
    @Autowired
    private KafkaTemplate kafkaTemplate;
    
    // 主流程:编排
    public String createOrder(OrderRequest request) {
        // 1. 编排器验证商品
        List<Product> products = productService.validateProducts(request.getItems());
        
        // 2. 编排器创建订单
        Order order = createOrder(request);
        
        // 3. 子流程:库存扣减(协同)
        kafkaTemplate.send("inventory-commands", 
            order.getId().toString(),
            new ReserveInventoryCommand(order.getItems()));
        
        return order.getId().toString();
    }
}

// 库存子流程:协同
@Service
public class InventoryService {
    
    @KafkaListener(topics = "inventory-commands")
    public void handleReserveCommand(ReserveInventoryCommand command) {
        // 扣减库存
        reserveStock(command.getItems());
        
        // 发布库存预留事件
        kafkaTemplate.send("inventory-events",
            command.getOrderId(),
            new InventoryReservedEvent(command.getOrderId(), true));
    }
}

2. 事件溯源+协同

java 复制代码
// 基于事件的Saga
public class OrderSaga {
    
    @SagaStart
    public void start(OrderRequest request) {
        // 发送创建订单命令
        send("order-service", new CreateOrderCommand(request));
    }
    
    @SagaEvent(topic = "order-created")
    public void onOrderCreated(OrderCreatedEvent event) {
        // 发送扣减库存命令
        send("inventory-service", new ReserveStockCommand(event.getOrder()));
    }
    
    @SagaEvent(topic = "stock-reserved")
    public void onStockReserved(StockReservedEvent event) {
        // 发送支付命令
        send("payment-service", new ProcessPaymentCommand(event.getOrder()));
    }
    
    @SagaEvent(topic = "payment-succeeded")
    public void onPaymentSucceeded(PaymentSucceededEvent event) {
        // 发送发货命令
        send("logistics-service", new CreateDeliveryCommand(event.getOrder()));
        // Saga完成
    }
    
    @SagaEvent(topic = "payment-failed")
    public void onPaymentFailed(PaymentFailedEvent event) {
        // 发送库存回滚命令
        send("inventory-service", new ReleaseStockCommand(event.getOrder()));
        // Saga补偿完成
    }
}

六、异常处理

1. 编排模式异常处理

java 复制代码
@Service
public class OrderOrchestratorWithCompensation {
    
    @Transactional
    public OrderResult createOrder(OrderRequest request) {
        try {
            // 1. 验证商品
            List<Product> products = productService.validateProducts(request.getItems());
            
            // 2. 扣减库存
            inventoryService.deductStock(request.getItems());
            
            // 3. 创建订单
            Order order = orderService.createOrder(request);
            
            // 4. 处理支付
            PaymentResult payment = paymentService.processPayment(order);
            
            if (!payment.isSuccess()) {
                throw new PaymentException("支付失败");
            }
            
            return OrderResult.success(order);
            
        } catch (PaymentException e) {
            // 补偿:回滚库存
            inventoryService.rollbackStock(request.getItems());
            throw e;
            
        } catch (Exception e) {
            // 通用补偿逻辑
            compensate(request);
            throw e;
        }
    }
}

2. 协同模式异常处理

java 复制代码
// 库存服务补偿逻辑
@Service
public class InventoryService {
    
    @KafkaListener(topics = "payment-failed")
    public void handlePaymentFailed(PaymentFailedEvent event) {
        // 回滚库存
        rollbackStock(event.getOrder().getItems());
        
        // 发布库存已回滚事件
        kafkaTemplate.send("inventory-events",
            event.getOrder().getId().toString(),
            new StockRolledBackEvent(event.getOrder()));
    }
    
    @KafkaListener(topics = "order-cancelled")
    public void handleOrderCancelled(OrderCancelledEvent event) {
        // 回滚库存
        rollbackStock(event.getOrder().getItems());
    }
}

七、最佳实践

1. 通信协议选择

java 复制代码
// 同步通信:REST/gRPC
@RestController
public class ProductController {
    
    @GetMapping("/products/{id}")
    public Product getProduct(@PathVariable Long id) {
        return productService.getProduct(id);
    }
}

// 异步通信:消息队列
@Service
public class OrderEventPublisher {
    
    @Autowired
    private KafkaTemplate kafkaTemplate;
    
    public void publishOrderCreated(Order order) {
        kafkaTemplate.send("order-events", order.getId().toString(), 
            new OrderCreatedEvent(order));
    }
}

2. 服务间契约

java 复制代码
// 定义契约
@Contract
public interface OrderServiceContract {
    
    @Endpoint("http://order-service/api")
    interface OrderApi {
        
        @Post("/orders")
        @RequestBody(OrderRequest.class)
        @ResponseBody(OrderResponse.class)
        OrderResponse createOrder(OrderRequest request);
        
        @Get("/orders/{id}")
        @ResponseBody(Order.class)
        Order getOrder(@PathVariable Long id);
    }
}

3. 监控和追踪

java 复制代码
// 分布式追踪
@Component
public class TracingInterceptor {
    
    @Around("@annotation(org.springframework.web.bind.annotation.*)")
    public Object trace(ProceedingJoinPoint point) throws Throwable {
        String traceId = getTraceId();
        String spanId = generateSpanId();
        
        try {
            Object result = point.proceed();
            
            // 记录追踪信息
            tracingService.record(traceId, spanId, 
                point.getSignature().getName(), true, null);
            
            return result;
        } catch (Exception e) {
            tracingService.record(traceId, spanId,
                point.getSignature().getName(), false, e.getMessage());
            throw e;
        }
    }
}

八、总结

微服务通信架构选择:

  • 编排模式:适合复杂业务流程,强中心控制
  • 协同模式:适合简单事件流,去中心化
  • 混合模式:主流程编排,子流程协同
  • Saga:长流程事务处理

最佳实践:

  1. 根据业务复杂度选择模式
  2. 设计好服务间契约
  3. 做好异常处理和补偿
  4. 实现完善的监控追踪

个人观点,仅供参考

相关推荐
Java后端的Ai之路1 小时前
Kubernetes是什么?(小白入门版)
云原生·容器·kubernetes·教程
空中海2 小时前
第二篇:注册中心篇 — Nacos 与 Eureka 服务注册发现
spring boot·云原生·eureka
ai产品老杨2 小时前
深度解析:基于国产化异构计算的 AI 视频管理平台架构——从 GB28181 接入到 NPU 边缘推流的解耦实践
人工智能·架构·音视频
梦想CAD控件2 小时前
网页CAD协同设计平台-生产级在线实时协同CAD引擎
前端·javascript·架构
SamDeepThinking3 小时前
第1篇-开篇词:几亿用户规模下,我们是怎么做C端高并发商品系统的
java·后端·架构
隔窗听雨眠3 小时前
从ZLibrary入口看数字资源分发架构
架构
霍小毛3 小时前
颠覆数据架构!基于Paimon的轻量智慧湖仓平台,开启数据价值新范式
架构
007张三丰3 小时前
系统架构设计师范文4:论微服务架构及其应用
微服务·云原生·架构·软考·系统架构设计师
moonsims3 小时前
NavCore惯性测量导航-轻量级安全惯导 / UAV 安全触发 IMU 模块-异构双IMU架构-低噪声稳定感知+高动态异常检测
安全·架构