LabHub
学习 学习路径 课程

微服务架构

把单体拆成两个服务

在 LabHub 中继续学习

目标

将订单和库存置于同一进程中的单体应用,在先固定契约后拆分为两个独立服务,并自动验证拆分前后的响应是否一致。

为什么重要

拆分服务时,真正困难的并不是移动代码,而是确认迁移后仍会得到相同答案,以及数据所有权是否也一并完成了迁移。实践中最常见的失败是“服务拆开了,数据表却仍然共享”。这样一来,部署虽然能够独立进行,但变更模式仍然需要两个团队协商,因为耦合存在于数据而不是代码中。因此,本实验要求在移动代码之前,先将契约(contract)固定在文件中,最后再检查源代码,确认数据访问是否真正断开。在绞杀者模式中,如果无法确信门面背后的两个实现会给出相同答案,就不能切换流量。

步骤

  1. 在 127.0.0.1:8101 启动 /opt/fixtures/msa/monolith.py,使 GET /health 返回 200。
  2. 检查单体应用的路由,在 /root/msa/seams.txt 中按每行一项的方式,以 경로 도메인 格式记录。必须同时出现 ordersinventory 两个领域,并且至少有 4 行。
  3. 创建 /root/msa/contract.json。顶层键只有 ordersinventory 两个,每个键都包含 port(整数)和 paths(字符串数组)。orders 为 8103,inventory 为 8102。
  4. 创建 /root/msa/inventory_svc.py 并在 127.0.0.1:8102 启动。GET /stock/SKU-1 应返回 {"sku":"SKU-1","qty":<정수>}
  5. 创建 /root/msa/orders_svc.py 并在 127.0.0.1:8103 启动。POST /orders 接收 {"sku":"SKU-1","qty":2},查询库存服务后,库存充足时返回 201 和 order_id,不足时返回 409。
  6. orders_svc.py 源代码中不得出现 /opt/fixtures/msa/inventory.json 之类的库存数据路径,而应调用 8102。
  7. 创建 /root/msa/parity.sh。向单体应用(8101)和新的订单服务(8103)发送相同请求,当状态码和判定一致时输出 PARITY OK。将执行结果保存到 /root/msa/parity.out
  8. /root/msa/decision.md 中加入 ## 쪼갠 이유## 쪼개지 말았어야 할 이유 两个标题,并在每个标题下至少写 30 个字符。

参考

启动单体应用并建立基线

在 127.0.0.1:8101 启动 /opt/fixtures/msa/monolith.py,使 GET /health 返回 200。

使用 python3 运行 /opt/fixtures/msa/monolith.py 后,它会在 8101 端口启动。不要忘记后台运行(&)和日志重定向。

列出接缝(seam)

检查单体应用的路由,在 /root/msa/seams.txt 中按每行一项的方式,以 경로 도메인 格式记录。必须同时出现 ordersinventory 两个领域,并且至少有 4 行。

拆分前先写出候选边界。使用 grep 检查单体应用的路由定义,逐行记录路径及其所属领域。

固定两个服务的契约

创建 /root/msa/contract.json。顶层键只有 ordersinventory 两个,每个键都包含 port(整数)和 paths(字符串数组)。orders 为 8103,inventory 为 8102。

契约先于代码。使用 JSON 记录服务名、端口和公开路径。关键在于库存服务承诺提供什么。

拆分库存服务

创建 /root/msa/inventory_svc.py 并在 127.0.0.1:8102 启动。GET /stock/SKU-1 应返回 {"sku":"SKU-1","qty":<정수>}

只将库存相关逻辑移到新文件,并在 8102 端口启动。响应必须是包含 sku 和 qty 的 JSON。

拆分订单服务

创建 /root/msa/orders_svc.py 并在 127.0.0.1:8103 启动。POST /orders 接收 {"sku":"SKU-1","qty":2},查询库存服务后,库存充足时返回 201 和 order_id,不足时返回 409。

订单服务不直接读取库存,而是通过 HTTP 查询。库存不足时返回 409 是契约的一部分。

证明数据所有权已拆分

orders_svc.py 源代码中不得出现 /opt/fixtures/msa/inventory.json 之类的库存数据路径,而应调用 8102。

如果订单服务源代码中仍保留库存数据文件路径,说明它们依然耦合。请检查源代码。

比较单体应用与新服务的响应等价性

创建 /root/msa/parity.sh。向单体应用(8101)和新的订单服务(8103)发送相同请求,当状态码和判定一致时输出 PARITY OK。将执行结果保存到 /root/msa/parity.out

编写一个脚本,将相同输入发送到两条路径并比较结果。两个响应相同时,让它输出 PARITY OK。

记录拆分决策

/root/msa/decision.md 中加入 ## 쪼갠 이유## 쪼개지 말았어야 할 이유 两个标题,并在每个标题下至少写 30 个字符。

分别写明应该拆分和本不应该拆分的理由。必须准确使用指定的两个 Markdown 标题,才能通过评分。