业务边界由端到端业务能力决定,服务须闭环处理用户可感知动作;需通过专属数据库、独立api前缀、限界上下文和grpc隔离来落地,避免过早按功能模块切分导致新单体。

业务边界不是靠技术分层划出来的,而是由端到端的业务能力决定的——一个服务必须能独立完成某个核心流程,比如“下单”不能拆成库存、价格、订单三个服务来回调用。
怎么判断一个服务是否具备完整业务能力
关键看它能否闭环处理一个用户可感知的业务动作。比如“患者提交电子问卷”,这个动作背后涉及身份校验、访视计划匹配、数据写入,如果这些逻辑分散在三个服务里,一次提交就要跨三次网络调用+三次事务协调,失败概率指数级上升。
- 检查现有单体中高频耦合的函数链:
ValidatePatient()→FetchVisitSchedule()→SavePROData(),若它们共享状态或强依赖时序,就该保留在同一服务内 - 问自己:这个服务上线/回滚时,会不会影响其他业务功能?如果答案是“会”,说明边界没切开
- 数据库是否物理隔离?
PatientService的表不该被ePROService直接SELECT,哪怕初期共用集群,也必须通过 gRPC 调用获取脱敏后的SubjectUUID
为什么按功能模块切(user/order/payment)容易出问题
这不是错,而是过早抽象。当“用户”服务里塞进实名认证、地址校验、支付回调、登录风控,它就不再是“用户”服务,而是披着微服务外衣的单体。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 所有逻辑堆在
UserService里,导致每次改一个字段(比如身份证号加密方式),就得全量测试、全量发布 - 权限失控:数据分析团队需要读取订单行为,却意外获得访问用户敏感字段的路径
- 扩缩容失效:促销期间订单突增,你得把整个
UserService扩容,哪怕它 80% 的 CPU 花在无关的地址校验上
如何用限界上下文(Bounded Context)落地业务边界
DDD 不是画图工具,而是帮你识别哪些数据和逻辑必须原子化协作。在医疗场景中,“患者”和“临床试验”天然就是两个上下文——前者受 HIPAA 严格监管,后者侧重方案版本管理,混在一起只会增加合规风险。
- 每个上下文对应一个 Go module,路径如
github.com/org/project/patient,根目录下只放cmd/、internal/、api/ -
internal/下按业务域组织,不是按技术层:internal/patient/handler.go、internal/patient/service.go、internal/patient/repository.go - 跨上下文通信只走
.proto定义的 gRPC 接口,禁止import另一个模块的internal/包;DTO 必须由调用方定义,不共享model.User
最容易被忽略的边界信号:数据库与 API 前缀
很多团队以为服务拆了,其实只是目录结构变了。真正可靠的边界信号只有两个:专属数据库表 + 独立 API 路由前缀。没有这两条,所谓的“微服务”只是进程隔离的单体。
-
PatientService的 API 必须以/v1/patient/...开头,且所有路由都落在这个前缀下,不暴露/auth或/trial - 它的数据库迁移文件只能操作
patients、consent_records等表,绝不碰trials或pro_responses - 构建命令要精确到服务:
go build -o patient ./cmd/patient,而不是go build -o main ./...
边界一旦定错,越往后重构成本越高——不是改几行代码的事,而是要重跑数据迁移、重写上下游契约、重新做安全审计。所以别急着写代码,先用一张白纸写下:“这个服务,用户能做什么?失败时谁负责?数据归谁管?”
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










