云计算百科
云计算领域专业知识百科平台

微服务架构落地:业务域全景与 DDD 落地 —— 如何避免把微服务写成“分布式单体”?

大宗商品销采运储系统・六层架构连载(业务服务层)

前面我们用大量篇幅,完成了基础服务层、公共中间件层、数据持久层这三大底层硬核模块的搭建。

地基打好了,接下来我们将正式进入整个六层架构的最核心、也是直接产生商业价值的一层:【业务服务层】。

大宗商品(钢铁、煤炭、化工、农产品等)的业务非常复杂:涉及多式联运、货权转移、期现结合、批次质检、智能过磅等特有逻辑。很多团队一上来就开始画表、建接口,结果系统越写越乱,最终变成了几十个微服务互相疯狂调用、牵一发而动全身的“分布式单体”。

一句话定调:

业务服务层不是写 CRUD,而是画业务边界。用 DDD(领域驱动设计)约束微服务的膨胀,用防腐层隔离外部生态的污染,才是大宗商品交易的架构底座。


一、痛点:微服务拆分,为什么总是拆成“分布式单体”?

很多架构师在业务层落地时,容易踩进四个致命误区:

  • 按部门拆分(组织架构绑架技术架构):采购部一个系统、销售部一个系统。结果一搞集中开盘,销售要查采购的实时库存,只能跨系统调接口,接口一挂全盘崩溃。

  • 按表拆分(伪 DDD):有订单表就建订单服务,有明细表就建明细服务。导致一个“查询订单详情”的请求,要跨 5 个微服务做 Join,响应慢如老狗。

  • 按技术分层拆分(极端的过度设计):建了 Controller 微服务、Service 微服务、DAO 微服务。一次请求要在网络里流转三次,网络开销直接把性能拖垮。

  • 纳米级微服务(粒度太细):把客户、客户联系人、客户银行账户拆成三个独立服务。导致业务逻辑被切碎,分布式事务满天飞。

  • 大宗商品平台是一条强耦合的物理与资金链条:期现套保 → 采购长协 → 物理仓储 → 过磅质检 → 运输履约 → 销售变现 → 财务结算。如果边界切错了,后续的分布式一致性和长链路追踪会让你痛不欲生。

    图片


    二、大宗商品平台全景图:我们到底在管什么?

    在看代码之前,先看业务。大宗商品平台绝不仅仅是“买进卖出”,它涵盖了复杂的金融属性、物理属性与生态协同。

    ┌────────────────────────────────────────────────────────────────────────┐│ 【外部生态与协同层】 供应商门户 | 客户自助终端 | 司机小程序 | 第三方物流对接    │└────────────────────────────────────────────────────────────────────────┘       │       ▼┌────────────────────────────────────────────────────────────────────────┐│ 【交易与商务域】                                                         ││ 询价报价 | 长协框架 | 现货挂牌 | 集中竞价 | 期现结合(套保) | 电子合同签署    │└────────────────────────────────────────────────────────────────────────┘       │       ▼┌────────────────────────────────────────────────────────────────────────┐│ 【履约与物流域】                                                         ││ 提货单流转 | 派车调度 | 多式联运 | 场站门禁 | 智能过磅 | 电子围栏 | 轨迹追踪 │└────────────────────────────────────────────────────────────────────────┘       │       ▼┌────────────────────────────────────────────────────────────────────────┐│ 【仓储与物权域】                                                         ││ 多货主隔离 | 库位管理 | 批次/炉号管理 | 质量化验(质检) | 货权转移 | 仓单质押 │└────────────────────────────────────────────────────────────────────────┘       │       ▼┌────────────────────────────────────────────────────────────────────────┐│ 【风控与金融域】                                                         ││ 客户信用评估 | 授信额度管控 | 保证金冻结 | 预付款释放 | 资金流水对账         │└────────────────────────────────────────────────────────────────────────┘       │       ▼┌────────────────────────────────────────────────────────────────────────┐│ 【业财与协同域】                                                         ││ 应收应付 | 开票(金税) | 银企直联 | 客诉工单 | 异常审批流 | 财务总账(对接ERP)  │└────────────────────────────────────────────────────────────────────────┘

    从全景图可以看出,大宗商品真正的核心业务域不仅包含基础的销采运储,还要深度嵌入风控、金融和业财一体化。

    图片


    三、DDD 落地第一步:划分限界上下文(Bounded Context)

    DDD 的核心思想是:微服务不是按“表”拆,也不是按“前端菜单”拆,而是按“业务能力的边界”拆。

    结合大宗商品特点,我们把系统划分为五大核心限界上下文:

  • 交易上下文:核心域。只管商务行为(客户报价、销售开单、采购寻源、合同生成)。

  • 履约上下文:支撑域。只管物理执行(发货指令、派车调度、多式联运、过磅防作弊)。

  • 库存上下文:核心域。只管物权与数量(批次管理、库位分配、货权转移、盘点)。

  • 风控与金融上下文:支撑域。只管钱的安全(信用额度校验、保证金冻结与释放)。

  • 业财上下文:通用域。只管对账与开票(应收应付、发票开具、财务凭证生成)。

  • 上下文之间怎么交互?
    绝对不允许直接读对方的数据库(微服务红线)。必须通过 领域事件(Domain Event) 或 RPC 接口。
    例如:销售开单成功,交易上下文发布一个 OrderCreatedEvent,履约上下文监听到后,生成派车任务;风控上下文异步扣减客户授信额度。

    图片


    四、DDD 落地第二步:聚合根(Aggregate Root)设计

    在微服务内部,单据表怎么设计?大宗商品的单据头(Order)和单据明细(OrderItem)必须放在一起,不能拆成两个服务。在 DDD 中,这叫聚合(Aggregate)。

    以“销售订单”为例:

    • 聚合根(Aggregate Root):销售订单。它是外部访问的唯一入口。

    • 实体(Entity):订单明细、提货指令。它们依附于订单存在。

    • 值对象(Value Object):价格(金额+币种)、重量(数值+单位)、化验指标。修改必须全量替换。

    聚合根核心代码示例:

    @Entity
    public class SaleOrder {
    @Id
    private String orderNo; // 采用持久层讲过的雪花算法生成

    private String customerId;

    private OrderStatus status;

    // 强关联的子实体集合
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> items;

    private Money totalAmount;

    // 业务行为:创建订单
    public void createOrder() {
    // 1. 校验客户信用额度 (调用风控域接口)
    // 2. 校验实时库存 (调用库存域接口)
    // 3. 计算总价与保证金
    // 4. 触发领域事件:OrderCreatedEvent
    }
    }

    业务规范:外部服务(如财务系统)想要查某个订单,必须通过 SaleOrderService 去查,绝对不允许直接写 SQL 操作 t_order_item 表。


    五、DDD 落地第三步:防腐层(ACL)隔离外部生态的“烂代码”

    大宗商品平台是个巨大的集成中心。除了老旧的 ERP、财务共享系统、第三方物流平台、电子发票系统等。

    如果你直接把对接硬件的代码写在“库存域”,把对接期货的代码写在“交易域”,系统立刻变成意大利面条。

    我们需要引入防腐层(Anti-Corruption Layer, ACL)。

    [业务核心域]    │ 调用 IssueInvoiceUseCase (内部领域接口)   ▼[防腐层 ACL (独立的 Integration 微服务)]    │ 1. 模型转换:将内部过磅单转为地磅硬件协议   │ 2. 协议适配:将 HTTP 转为 TCP/IP / WebService / MQ   │ 3. 异常重试与硬件防抖   ▼[外部生态环境:电子发票/银企/物流/物联网设备]

    设计原则:不管外部系统或硬件长什么样,业务域内部永远只认自己的领域模型。外部系统的变化被死死挡在防腐层里。

    图片


    六、业务层与前文底座的联动(绝不是在孤岛上写代码)

    我们在写业务层时,绝不是从零开始,而是要时刻调用前面建好的底座:

  • 与中间件联动:交易域开单成功后,不直接调用履约域接口,而是发一条 OrderCreatedEvent 到 RocketMQ,由履约域异步消费,实现业务解耦。

  • 与持久层联动:在创建订单的聚合根时,订单号直接调用持久层篇中讲过的雪花算法(Snowflake)生成,且 ID 的低 4 位直接嵌入客户 ID 的基因,方便后续分片路由。

  • 与基础服务联动:所有开单接口必须强制接入接口服务(幂等控制),防止用户重复点击导致重复下单。


  • 七、本篇小结

    业务服务层是系统的“发动机”。不要上来就写接口,先画图,先定边界。

    记住三句话:

  • 业务拆分靠 DDD,按限界上下文划界,不能按表拆、不能按部门拆。

  • 单据设计用聚合根,内部强一致性,外部只能访问根节点。

  • 外部生态对接必须有防腐层,决不让 ERP、税控、物联网硬件的烂代码污染核心架构。


  • 下篇预告:业务域基建(上):复杂单据状态机设计,拆解如何用状态机引擎彻底消灭海量的 if-else,并保证业务流转的严格合规?

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 微服务架构落地:业务域全景与 DDD 落地 —— 如何避免把微服务写成“分布式单体”?
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!