4. 服务边界定义:微服务架构下的服务边界原则,如何将业务能力映射为Temporal Workflow与Activity

在微服务架构中,服务边界的合理划分是系统稳定性和演进能力的基础。Temporal Workflow 与 Activity 的映射并非简单的代码拆分,而是需要遵循领域驱动设计(DDD)的限界上下文原则,将业务能力与分布式协调逻辑解耦。

4.1 服务边界划分的核心原则

微服务边界的定义应遵循以下原则,以确保每个服务具备高内聚、低耦合的特性:

原则 说明 反例
限界上下文 每个服务对应一个明确的业务领域边界,内部模型自治 订单服务直接操作库存数据库表
数据主权 服务拥有其数据的唯一写权限,其他服务通过API访问 多个服务共享同一张数据库表
业务能力 服务边界由业务能力而非技术分层决定 将“用户验证”拆成独立的HTTP服务
变更频率 将变更速率不同的逻辑隔离到不同服务 核心交易逻辑与报表逻辑混在一起
故障隔离 一个服务的故障不应级联扩散到其他服务 同步调用链路过深,无熔断机制
实践建议: 在划分服务边界时,优先使用事件风暴(Event Storming)识别聚合根与限界上下文。每个聚合根通常对应一个Temporal Workflow,而聚合根内部的操作对应Activity。

4.2 业务能力到Temporal Workflow与Activity的映射模型

将业务能力映射到Temporal原语时,需要遵循以下对应关系:

  • Workflow:对应一个完整的业务用例或流程编排。它负责定义步骤顺序、补偿逻辑、超时策略,以及跨服务的协调。Workflow 本身不应包含业务计算逻辑,只做编排。
  • Activity:对应一个不可分割的业务操作或外部调用。Activity 是幂等的、可重试的,并且通常在一个微服务内部执行。Activity 可以访问数据库、调用外部API或执行本地计算。

下图展示了从业务能力到Temporal原语的映射关系:

业务能力到Temporal Workflow与Activity映射 业务能力 → Temporal Workflow / Activity 映射 业务能力层 订单创建 支付处理 库存预留 物流调度 通知发送 ... Temporal 原语层 OrderWorkflow CreateOrderActivity ProcessPaymentActivity ReserveInventoryActivity ScheduleDeliveryActivity Workflow 编排多个 Activity,Activity 执行具体业务逻辑

4.3 映射策略:从业务事件到Workflow定义

将业务能力映射为Temporal Workflow时,推荐采用以下步骤:

  1. 识别业务事件:列出所有触发业务流程的事件(如“订单已提交”、“支付已确认”)。
  2. 定义Workflow接口:每个业务事件对应一个Workflow类型,Workflow名称应体现业务意图(如 OrderFulfillmentWorkflow)。
  3. 分解Activity:将Workflow内的每个步骤拆分为Activity,确保每个Activity只做一件事,且具备幂等性。
  4. 确定Activity归属服务:根据限界上下文,将Activity分配到对应的微服务中。Activity的实现类可以位于不同服务的代码库中。
  5. 定义重试与超时策略:为每个Activity设置合理的重试间隔和超时时间,避免Workflow因临时故障而失败。
关键原则: Workflow 代码应保持轻量,不包含任何 I/O 操作或线程阻塞调用。所有与外部系统的交互都必须封装在 Activity 中。这保证了 Workflow 的执行历史可以被完整持久化,并且 Worker 可以安全地重放。

4.4 跨服务Activity的通信机制

当Activity需要调用其他微服务时,Temporal提供了多种通信模式:

模式 适用场景 实现方式
同步请求-响应 需要立即获取结果的查询操作 Activity 内部使用 HTTP/gRPC 调用下游服务
异步消息 不需要立即响应的操作,如发送通知 Activity 将消息写入消息队列,由下游服务消费
子Workflow 跨服务的复杂编排,需要独立的生命周期管理 父Workflow通过 ChildWorkflowStub 启动子Workflow
信号(Signal) 等待外部事件或用户输入 Workflow 调用 Workflow.await 等待特定信号

下图展示了Activity跨服务调用的典型架构:

Activity跨服务通信架构 Activity 跨服务通信架构 Temporal Server Order Worker OrderWorkflow Payment Worker ProcessPaymentActivity 订单服务 支付服务 库存服务 Worker 执行 Activity 时,通过内部 RPC 或消息队列调用对应的微服务

4.5 代码示例:订单履约Workflow

以下示例展示如何将订单履约的业务能力映射为Temporal Workflow与Activity:

// 1. 定义 Workflow 接口
public interface OrderFulfillmentWorkflow {
    @WorkflowMethod
    OrderResult fulfillOrder(OrderInput input);
}

// 2. 实现 Workflow 编排
public class OrderFulfillmentWorkflowImpl implements OrderFulfillmentWorkflow {
    
    private final PaymentActivity paymentActivity = 
        Workflow.newActivityStub(PaymentActivity.class, 
            ActivityOptions.newBuilder()
                .setStartToCloseTimeout(Duration.ofSeconds(10))
                .setRetryOptions(RetryOptions.newBuilder()
                    .setMaximumAttempts(3)
                    .build())
                .build());
    
    private final InventoryActivity inventoryActivity = 
        Workflow.newActivityStub(InventoryActivity.class,
            ActivityOptions.newBuilder()
                .setStartToCloseTimeout(Duration.ofSeconds(5))
                .build());
    
    private final NotificationActivity notificationActivity = 
        Workflow.newActivityStub(NotificationActivity.class,
            ActivityOptions.newBuilder()
                .setStartToCloseTimeout(Duration.ofSeconds(3))
                .build());

    @Override
    public OrderResult fulfillOrder(OrderInput input) {
        // Step 1: 预留库存
        boolean reserved = inventoryActivity.reserve(input.getItems());
        if (!reserved) {
            throw new ApplicationFailureException("库存不足");
        }
        
        // Step 2: 处理支付
        PaymentResult payment = paymentActivity.process(input.getPaymentInfo());
        
        // Step 3: 发送通知
        notificationActivity.sendOrderConfirmation(input.getUserId());
        
        return new OrderResult(payment.getTransactionId());
    }
}

// 3. 定义 Activity 接口(位于不同微服务中)
public interface PaymentActivity {
    @ActivityMethod
    PaymentResult process(PaymentInfo info);
}

public interface InventoryActivity {
    @ActivityMethod
    boolean reserve(List<Item> items);
}

public interface NotificationActivity {
    @ActivityMethod
    void sendOrderConfirmation(String userId);
}
常见误区: 不要将多个业务步骤合并到一个 Activity 中。例如,将“支付处理”和“库存预留”放在同一个 Activity 里,会导致重试时重复执行已完成的操作,破坏幂等性。每个 Activity 应只封装一个不可分割的业务操作。

4.6 服务边界映射检查清单

在完成映射后,使用以下清单进行验证:

  • 单一职责:每个 Activity 是否只做一件事?
  • 幂等性:Activity 重复执行是否会产生副作用?
  • 数据隔离:Activity 是否只访问所属服务的数据?
  • 超时覆盖:每个 Activity 是否设置了合理的超时时间?
  • 错误处理:Workflow 是否定义了明确的补偿逻辑(如 Saga 模式)?
  • 版本兼容:Activity 签名变更时,是否考虑了 Workflow 历史重放的兼容性?

遵循以上原则和映射策略,可以确保微服务架构下的Temporal Workflow具备清晰的边界、良好的可维护性和高可用性。