Skip to content

微服务架构设计

你有没有这种感觉:写代码一年,突然发现整个系统像一个巨大的意大利面条——这里改一行,那里就崩了;没人完全理解整个系统是怎么工作的;每次上线都像拆炸弹。

恭喜你,你可能正在经历「单体地狱」。

微服务架构,就是来解决这个问题的。


微服务的定义

微服务没有官方定义,但社区公认的核心特征是:

每个服务围绕业务能力构建,可独立部署、独立扩展。

翻译成人话:一个微服务只做一件事,而且这件事可以独立上线,不需要等其他团队。

比如:

  • 用户服务:只管用户注册、登录、资料
  • 订单服务:只管订单创建、支付、取消
  • 库存服务:只管库存查询、扣减、返还

每个服务有自己的数据库,服务之间通过 API 通信。


微服务 vs 单体:不是「非此即彼」

很多人误解微服务,觉得它是银弹,恨不得第一天就把系统拆成 100 个微服务。

这是一个危险的想法。

微服务解决的是「大型团队的协作问题」,不是「代码组织问题」。

场景推荐架构
小团队(< 10 人)、业务简单单体起步
中型团队(10-50 人)、业务复杂渐进式拆分
大型团队(> 50 人)、高并发微服务 + 容器化

单体不是原罪。 Twitter、Netflix 早期都是单体,只是后来团队太大了,单体成了瓶颈,才拆的。


微服务拆分维度

拆分的核心原则是业务边界(Bounded Context),这是 Eric Evans 在《领域驱动设计》里提出的概念。

按业务边界拆分

强相关、同步调用的功能,拆到同一个服务。

比如「下单」这个功能,涉及到:

  • 用户验证(用户服务)
  • 库存扣减(库存服务)
  • 支付扣款(支付服务)
  • 订单创建(订单服务)

这些应该拆成 4 个服务吗?不一定。

如果「下单」是一个高频操作,需要强一致性,可能把「下单」做成一个服务,内部调用用户、库存、支付的 API 更合理。

按团队所有权拆分

一个服务应该由一个团队完全负责,从开发到部署到运维。

如果一个服务需要两个团队同时修改,那就是拆分失败的信号。


微服务的四大黄金原则

原则一:独立部署

每个服务可以独立部署,不需要协调其他团队。

如果你的「微服务」每次上线还需要通知其他 5 个团队,那它不是微服务,是「分布式巨石」。

原则二:无共享数据

每个服务有自己的数据库,表不共享。

如果服务 A 直接读写服务 B 的数据库表,恭喜你,你把网络调用变成了 SQL 调用,问题更多。

原则三:异构技术

每个服务可以用不同的技术栈。

Python 团队做机器学习服务,Java 团队做交易系统,Go 团队做高并发网关——这是微服务的优势。

但前提是:技术选型要服务于业务,而不是为了炫技。

原则四:故障隔离

一个服务挂了,不能导致整个系统崩溃。

常见的故障隔离手段:

  • 舱壁模式:不同服务用不同的连接池
  • 熔断器:服务不可用时快速失败,不无限重试
  • 限流:保护服务不被突发流量冲垮

微服务的技术栈全景图

构建微服务需要很多组件:

┌─────────────────────────────────────────────────────────┐
│                      微服务架构                          │
├─────────────────────────────────────────────────────────┤
│  服务框架:Spring Cloud / Dubbo / gRPC                   │
│  通信协议:HTTP REST / gRPC / Dubbo RPC                 │
│  服务注册:Nacos / Eureka / Consul                      │
│  配置中心:Apollo / Nacos Config / Spring Config        │
│  网关层:Spring Cloud Gateway / Kong / Zuul             │
│  认证鉴权:JWT / OAuth2 / Spring Security              │
│  分布式事务:Seata / TX-LCN / Saga                      │
│  链路追踪:SkyWalking / Zipkin / Jaeger                 │
│  日志聚合:ELK / Loki / EFK                            │
│  容器化:Docker + Kubernetes                            │
└─────────────────────────────────────────────────────────┘

每个组件都有其适用场景,后面会专门讲。


微服务陷阱

微服务不是银弹,它带来了新的问题:

陷阱一:过度拆分

把一个简单的 CRUD 应用拆成 20 个微服务,每个服务就 3 张表、5 个接口。

结果:20 个服务 = 20 个数据库 = 20 套配置 = 20 套监控 = 20 倍的运维复杂度。

建议:当一个服务的代码量超过 10 万行,或者团队超过 5 个人专门维护时,再考虑拆分。

陷阱二:分布式复杂性爆炸

单体里一个函数调用解决的问题,微服务里可能涉及:

  • 网络调用
  • 序列化/反序列化
  • 服务发现
  • 负载均衡
  • 熔断降级
  • 分布式事务

这不是换一套框架能解决的,是架构层面的复杂度转移。

陷阱三:数据一致性

单体里一个数据库事务解决的问题,微服务里需要分布式事务或最终一致性。

这是一道鸿沟,没有完美的解决方案,只有业务层面的 trade-off。


什么时候不该用微服务

微服务是有成本的,以下场景建议先不要用:

  1. 小团队:运维成本可能超过收益
  2. 业务简单:不需要高扩展、高可用
  3. 创业初期:快速验证业务比架构重要
  4. 强一致性场景:微服务天然是最终一致,强一致需要额外的工程成本

面试追问方向

微服务和 SOA 有什么区别?

SOA 有 ESB 总线,所有服务通过 ESB 通信;微服务去中心化,服务之间直接通信。SOA 是粗粒度,微服务是细粒度。

微服务如何保证数据一致性?

这是一个开放性问题,没有标准答案:

  • 强一致:分布式事务(2PC/TCC/Saga)
  • 最终一致:消息队列 + 补偿机制
  • 业务层处理:乐观锁 + 重试 + 对账

服务拆分后,接口版本怎么管理?

  • URL 路径:/api/v1/users
  • Header:API-Version: 1.0
  • 蓝绿部署:新旧版本并行,流量切换

留给你的问题

微服务解决了「大型团队的协作问题」,但引入了「分布式系统的复杂度问题」。

你有没有遇到过这种情况:一个功能,单体里 1 小时搞定,微服务里需要 1 周(分布式事务 + 服务间联调 + 链路追踪 + ...)?

如果是你,会怎么权衡?

基于 VitePress 构建