
业务流(Business Process)是企业系统的骨架。订单从创建到履约、工单从提交到关闭、审批从发起到归档——每一条业务流背后,都是状态、规则、参与者与异常处理的复杂交织。专业做法不是把逻辑散落在 Service 里,而是把流程抽象为可建模、可执行、可观测的引擎。本文从状态机建模、编排引擎、异常补偿、可观测性四个维度,给出可落地的架构与代码。
业务流的第一性原理是状态机。任何流程都可以拆解为:状态集合、事件集合、转移规则、动作。以订单履约为例:
text
待支付 → 已支付 → 配货中 → 已发货 → 已签收
↓ ↓ ↓ ↓
已取消 已退款 异常待处理 退货中用代码定义状态与转移:
public enum OrderState {
PENDING_PAYMENT, PAID, PICKING, SHIPPED,
DELIVERED, CANCELLED, REFUNDED, EXCEPTION
}
public enum OrderEvent {
PAY, CANCEL, PICK, SHIP, DELIVER, REFUND, EXCEPTION
}
public class OrderStateMachine {
private static final Map<OrderState, Map<OrderEvent, OrderState>> TRANSITIONS =
Map.of(
OrderState.PENDING_PAYMENT, Map.of(
OrderEvent.PAY, OrderState.PAID,
OrderEvent.CANCEL, OrderState.CANCELLED),
OrderState.PAID, Map.of(
OrderEvent.PICK, OrderState.PICKING,
OrderEvent.REFUND, OrderState.REFUNDED),
OrderState.PICKING, Map.of(
OrderEvent.SHIP, OrderState.SHIPPED,
OrderEvent.EXCEPTION, OrderState.EXCEPTION),
OrderState.SHIPPED, Map.of(
OrderEvent.DELIVER, OrderState.DELIVERED)
);
public OrderState next(OrderState current, OrderEvent event) {
var transitions = TRANSITIONS.getOrDefault(current, Map.of());
var next = transitions.get(event);
if (next == null) {
throw new IllegalStateException(
"非法转移: " + current + " + " + event);
}
return next;
}
}关键点:转移规则是数据,不是 if-else 堆砌。这使流程可配置、可测试、可审计。
状态机定义了"能怎么走",编排引擎负责"实际怎么走"。核心要求:事件驱动、状态持久化、幂等执行。
public record OrderContext(
String orderId, OrderState state,
Map<String, Object> data, List<String> audit) {}
public interface OrderRepository {
OrderContext load(String orderId);
void save(OrderContext ctx);
boolean tryLock(String orderId, String token);
}
@Service
public class OrderFlowEngine {
private final OrderStateMachine machine;
private final OrderRepository repo;
private final ApplicationEventPublisher publisher;
public OrderContext fire(String orderId, OrderEvent event) {
String lockToken = UUID.randomUUID().toString();
if (!repo.tryLock(orderId, lockToken)) {
throw new ConcurrentModificationException("流程正在处理中");
}
try {
OrderContext ctx = repo.load(orderId);
OrderState next = machine.next(ctx.state(), event);
OrderContext updated = new OrderContext(
ctx.orderId(), next, ctx.data(),
append(ctx.audit(), ctx.state() + "->" + next)
);
repo.save(updated);
publisher.publishEvent(new StateChangedEvent(orderId, next));
return updated;
} finally {
repo.unlock(orderId, lockToken);
}
}
}这里用乐观锁防止并发重复推进,用事件发布解耦后续动作。订单状态变更后,发货、通知、积分等逻辑通过监听事件异步执行,不阻塞主流程。
长流程必然有中间状态。订单已支付但库存扣减失败怎么办?答案是 Saga 模式——每个正向操作配一个补偿操作,失败时反向执行。
public record FlowStep(
String name,
Runnable action,
Runnable compensate) {}
public class OrderSaga {
private final Deque<FlowStep> executed = new ArrayDeque<>();
private final AuditLogger audit;
public void execute(List<FlowStep> steps) {
try {
for (FlowStep step : steps) {
step.action().run();
executed.push(step);
audit.log(step.name(), "ok");
}
} catch (Exception e) {
audit.log("saga", "rollback triggered: " + e.getMessage());
while (!executed.isEmpty()) {
FlowStep step = executed.pop();
try {
step.compensate().run();
audit.log(step.name(), "compensated");
} catch (Exception ce) {
audit.log(step.name(), "compensate failed: " + ce.getMessage());
// 补偿失败必须告警,转人工
}
}
throw new FlowException("Saga 回滚完成", e);
}
}
}补偿操作必须幂等,补偿失败要记录并转人工,不能静默吞掉。
业务流架构师必须回答三个问题:流程卡在哪?为什么失败?谁在处理?
每个状态变更输出结构化日志,记录 traceId、订单号、原状态、新状态、事件、耗时:
@Component
public class FlowAuditListener {
private final FlowAuditRepository repo;
@EventListener
public void onStateChanged(StateChangedEvent event) {
repo.save(new FlowAudit(
event.orderId(), event.newState().name(),
MDC.get("traceId"), Instant.now()));
}
}配合 Grafana 看板,实时展示各状态的订单数量、平均停留时长、异常率。当某状态积压超过阈值时自动告警。
总结:业务流的核心不是把逻辑写出来,而是把流程建模为可执行、可观测、可恢复的引擎。用状态机约束转移,用编排引擎驱动执行,用 Saga 保障容错,用审计日志实现透明。代码结构清晰,边界明确,业务流才能真正支撑企业级系统的复杂度。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。