25、MVC中的微服务架构:从单体到分布式
聊到微服务,很多同学第一反应是「拆」。但怎么拆?拆了之后 MVC 还管用吗?
我这些年见过不少团队,一上来就把系统拆成几十个服务,结果接口调用乱成一锅粥,比原来还难维护。说白了,微服务不是银弹,它只是把 MVC 的「层」变成了「服务」。
单体 MVC 的痛点
先说说单体应用。一个典型的 Spring MVC 项目,Controller、Service、DAO 都在一个进程里。开发初期很爽,但一旦业务复杂起来,问题就来了:
- 部署耦合:改一行代码,整个应用要重新部署
- 团队冲突:多人改同一个模块,合并代码像打仗
- 扩展困难:某个功能流量大,却要扩容整个应用
我记得有个电商项目,订单模块和用户模块耦合在一起。双十一那天订单量暴增,结果用户登录也跟着卡。你说冤不冤?
微服务架构下的 MVC 变形
微服务不是把 MVC 扔掉,而是把每一层「服务化」。我习惯这样理解:
- Controller → 网关层(API Gateway)
- Service → 业务微服务
- Model → 数据服务 + 领域模型
每个微服务内部,依然遵循 MVC 的分层思想。只不过服务之间通过 RPC 或消息队列通信。
核心原则:微服务是「水平拆分」,MVC 是「垂直分层」。两者不冲突,而是互补。
如何拆分?一个实战案例
假设我们有一个电商单体应用,包含用户、商品、订单、支付四个模块。怎么拆?
我建议按「业务边界」来拆,而不是按「技术层」来拆。什么意思?
- 用户服务:注册、登录、个人信息
- 商品服务:商品列表、详情、库存
- 订单服务:下单、订单状态
- 支付服务:支付、退款
每个服务内部,都有自己的 Controller、Service、DAO。服务之间通过 API 调用。
// 订单服务调用用户服务(伪代码)
@RestController
public class OrderController {
@Autowired
private UserServiceClient userClient; // 远程调用
@PostMapping("/order/create")
public Result createOrder(@RequestBody OrderDTO order) {
// 1. 调用用户服务验证用户
User user = userClient.getUser(order.getUserId());
if (user == null) {
return Result.error("用户不存在");
}
// 2. 调用商品服务扣减库存
boolean stockOk = stockClient.deduct(order.getProductId(), order.getQuantity());
if (!stockOk) {
return Result.error("库存不足");
}
// 3. 创建订单(本地逻辑)
orderService.create(order);
return Result.success();
}
}
你看,Controller 里依然做参数校验和路由,Service 里做业务逻辑。只不过 Service 里调用了其他服务的接口。
避坑指南:我曾经把一个服务拆得太细,用户服务拆成了「登录服务」「注册服务」「信息查询服务」。结果一个简单的用户页面要调三个接口,延迟翻了三倍。后来我合并成「用户域服务」,一个服务搞定所有用户相关操作。
服务间通信:RPC vs 消息队列
微服务之间怎么通信?我常用的两种方式:
| 方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| RPC(如 Dubbo、gRPC) | 同步调用,实时性要求高 | 调用简单,像本地方法 | 耦合度高,服务依赖强 |
| 消息队列(如 RabbitMQ、Kafka) | 异步处理,削峰填谷 | 解耦,容错性好 | 最终一致性,调试困难 |
我个人习惯:核心链路用 RPC,非核心链路用消息队列。比如下单必须实时扣库存,用 RPC;下单成功后发短信通知,用消息队列。
数据一致性:分布式事务
单体应用里,事务很简单:一个 @Transactional 搞定。但微服务里,每个服务有自己的数据库,怎么保证一致性?
嗯,这里要注意。分布式事务没有银弹。我常用的方案:
- TCC(Try-Confirm-Cancel):适合强一致性场景,比如支付
- Saga 模式:适合长事务,比如下单流程
- 最终一致性:适合非关键数据,比如用户积分
我曾经在一个支付项目里用 TCC,代码量翻了一倍。但没办法,钱的事不能含糊。
警告:不要为了微服务而微服务。如果你的团队不到 10 人,业务复杂度不高,单体应用 + 良好分层完全够用。微服务带来的运维成本,可能比收益还高。
SVG:单体 MVC → 微服务架构演进图
总结一下
微服务架构下的 MVC,本质上是把「层」变成了「服务」。每个服务内部依然保持 MVC 的分层结构,但服务之间通过 RPC 或消息队列通信。
拆分的核心是「业务边界」,不是「技术层」。我见过太多人把 Service 层拆成独立服务,结果 Controller 层还在单体里,搞得四不像。
最后说一句:微服务是手段,不是目的。如果你的业务还没复杂到需要拆,老老实实用单体 MVC。等流量来了、团队大了,再考虑演进。
一句话记住:单体 MVC 是「三层一库」,微服务 MVC 是「多服务多库,每服务三层」。