2、微服务设计原则:单一职责、服务自治、接口隔离、数据去中心化
好,咱们直接进入正题。微服务设计不是拍脑袋想出来的,它背后有四个核心原则撑着。我这些年拆过不少系统,也踩过坑,今天就把这些原则掰开了讲清楚。
2.1 单一职责原则:一个服务只做一件事
说白了,就是每个微服务只负责一个明确的业务功能。比如订单服务只管订单,用户服务只管用户。别把两者混在一起。
为什么这么重要?
你想想看,如果一个服务既管订单又管支付,哪天支付逻辑改了,订单也得跟着重新部署。这还叫微服务吗?
核心要点:
- 每个服务有且仅有一个业务边界
- 服务内部高内聚,服务之间低耦合
- 修改一个功能,不影响其他服务
我在项目中遇到过这样一个案例:有个团队把用户认证和商品管理放在同一个服务里。结果每次改登录逻辑,商品接口就得跟着重启。嗯,这其实已经违背了单一职责。
我的建议:划分服务时,先画业务领域图。每个虚线框就是一个潜在的服务边界。别急着写代码,先想清楚边界在哪。
2.2 服务自治原则:每个服务都能独立存活
服务自治,说白了就是每个微服务可以独立开发、独立测试、独立部署、独立运行。它不依赖其他服务的本地资源。
自治体现在哪?
- 独立数据库:每个服务有自己的数据库,不共享
- 独立代码库:每个服务一个 Git 仓库
- 独立部署:可以单独上线,不影响全局
- 独立团队:一个小团队全权负责一个服务
我曾经见过一个系统,所有服务共享同一个 MySQL 实例。结果一个服务跑慢查询,整个系统都跟着卡。这就是典型的没有自治。
避坑指南:服务自治不等于完全隔离。服务之间还是要通过 API 通信的。我曾经犯过一个错,为了追求自治,把所有服务之间的调用都改成了异步消息队列。结果调试起来特别痛苦。自治是相对的,不是绝对的。
2.3 接口隔离原则:给客户端刚刚好的接口
接口隔离原则,说白了就是:不要强迫客户端依赖它不需要的接口。
举个例子,一个订单服务对外暴露了 20 个接口。但前端只需要 3 个。那前端就不应该看到其他 17 个。否则前端开发者会困惑,也容易误调用。
怎么做到接口隔离?
- 按客户端类型拆分接口(Web端、移动端、内部系统)
- 每个接口只做一件事
- 接口参数尽量少,返回值尽量精简
反面教材:
# 一个接口返回所有信息
GET /api/order/detail
返回:订单信息 + 用户信息 + 商品信息 + 物流信息 + 支付信息
# 前端只需要订单状态,却要下载整个数据包
# 这就是接口隔离没做好
我个人习惯是,每个微服务对外暴露的接口数量控制在 5-8 个以内。超过这个数,说明服务可能拆得不够细。
2.4 数据去中心化:每个服务管好自己的数据
这是微服务最核心也最容易被忽视的原则。数据去中心化,就是每个服务拥有自己的数据存储,不共享数据库。
为什么不能共享数据库?
- 共享数据库 = 共享耦合。一个服务改表结构,其他服务全崩
- 共享数据库 = 单点瓶颈。所有服务抢同一个连接池
- 共享数据库 = 技术绑定。你想换 NoSQL?得所有服务一起换
我记得有个项目,一开始图省事,所有服务共用同一个 PostgreSQL。后来订单服务要加个字段,结果用户服务的查询全报错了。那次事故让我彻底明白了数据去中心化的价值。
数据去中心化的实现方式:
| 场景 | 推荐方案 | 说明 |
|---|---|---|
| 关系型数据 | 每个服务独立 MySQL/PostgreSQL 实例 | 物理隔离,互不影响 |
| 缓存数据 | 每个服务独立 Redis 实例 | 避免 key 冲突和性能干扰 |
| 文件存储 | 每个服务独立对象存储桶 | 权限隔离,便于管理 |
| 消息队列 | 每个服务独立 Topic/Queue | 避免消息互相干扰 |
你可能会问:那服务之间需要数据怎么办?答案是:通过 API 调用,而不是直接查数据库。订单服务需要用户信息?调用用户服务的接口,而不是连用户服务的数据库。
注意:数据去中心化会带来数据一致性的挑战。比如订单服务和库存服务,怎么保证扣库存和创建订单是原子操作?嗯,这里就要用到分布式事务或者最终一致性方案了。这个我们后面章节会详细讲。
小结
这四个原则,说白了就是一句话:每个微服务应该是一个独立的小王国,有自己的边界、自己的数据、自己的生命周期。
我在实际项目中,通常先用单一职责原则划分服务边界,再用服务自治原则确定每个服务的独立性,接着用接口隔离原则设计对外 API,最后用数据去中心化原则确定数据存储方案。这个顺序走下来,基本不会出大问题。
下一章,我们会聊微服务的技术选型。到时候我会分享一些我在选型时踩过的坑,嗯,挺有意思的。