{SITE.title} logo 云萱笔记
架构设计 · · 4 分钟阅读

微服务架构设计全景指南:从拆分原则到落地选型

大家好,我是云萱。

最近在准备 Senior DevOps Engineer 的面试,把微服务架构相关的知识系统地梳理了一遍。发现很多人对微服务的理解停留在”把单体拆成多个服务”这个层面,但真正落地的时候会遇到各种问题:拆多细?用什么注册中心?分布式事务怎么搞?熔断降级怎么配?

这篇文章把我整理的内容分享出来,从拆分原则到技术选型,从核心组件到安全体系,尽量覆盖全面。希望对你有帮助。


一、微服务拆分原则

拆服务是微服务的第一步,也是最考验架构能力的一步。拆粗了等于白拆,拆细了运维爆炸。

常见的拆分方法

方法说明适用场景
按业务领域拆分(DDD 限界上下文)每个服务对应一个业务领域,高内聚低耦合最常用,推荐首选
按子域拆分核心域、支撑域、通用域分别拆复杂业务系统
按团队拆分(康威定律)一个团队负责一个服务,减少跨团队协作团队组织相对稳定

我个人最推荐的是 DDD 限界上下文 方法——先梳理清楚业务领域,再根据领域边界来划分服务。这样拆出来的服务边界清晰,职责明确,后期也不容易变味。

拆分粒度的把握

拆太粗的问题:

  • 部署耦合,改一个功能全量发布
  • 团队协作冲突多
  • 技术栈无法灵活选择

拆太细的问题:

  • 服务数量爆炸,运维成本高
  • 调用链太长,性能差
  • 分布式事务复杂
  • 排查问题困难

经验法则: 一个服务能被 23 个披萨喂饱的团队维护(2 Pizza Team),大概 610 人,代码量在团队可完全理解的范围内。

这个法则听起来很玄,但实际工作中挺好用的——当你对一个服务已经没有”整体感”了,可能就是该拆的时候了。


二、核心组件

微服务不是”把单体拆开”就完事了,你需要一整套基础设施来支撑它。

1. 服务注册与发现

基本流程很简单:

服务启动 → 注册到注册中心(写入服务名 + IP + 端口)
服务调用 → 从注册中心获取可用实例列表 → 负载均衡调用
服务下线 → 心跳检测失败 → 自动剔除

但具体选型的时候,差异就大了:

方案一致性可用性性能语言
NacosCP + AP 可切换高高Java
ConsulCP中中Go
EurekaAP高高Java
etcdCP中高Go
K8s Service-高高-

面试常问:服务注册中心选 CP 还是 AP 好?

注册中心选 AP 更好。原因很简单:服务发现宁可返回不可靠的列表,也不能因为注册中心挂了导致服务间完全无法调用。大不了客户端自己做健康检查、熔断降级。Nacos 支持切换模式,默认 AP。

如果你的服务跑在 Kubernetes 上,其实 K8s Service + CoreDNS 已经能解决大部分服务发现问题了,不一定非要引入 Nacos/Consul。

2. 配置中心

作用:

  • 统一管理各环境配置
  • 配置热更新(不需要重启服务)
  • 配置版本管理、灰度发布
  • 敏感信息加密

常见方案: Nacos、Apollo、Spring Cloud Config、etcd

我个人的偏好:Java 生态选 Nacos(一站式,注册+配置都搞定),云原生生态选 etcd + 自己封装或者用 ConfigMap(但 ConfigMap 热更新要自己处理)。

3. API 网关

核心功能:

  • 路由转发(统一入口)
  • 认证鉴权(JWT、OAuth2)
  • 限流熔断
  • 日志监控
  • 灰度发布(按权重/用户/Header 路由)
  • 协议转换(HTTP → gRPC)

常见方案: Kong、APISIX、Spring Cloud Gateway、Nginx + Lua、Istio Ingress

选型思路:

  • Spring 生态 → Spring Cloud Gateway
  • 高性能、插件丰富 → APISIX / Kong
  • 服务网格体系 → Istio Ingress Gateway

三、服务间通信

1. 同步 vs 异步

同步(HTTP/gRPC)异步(消息队列)
耦合度高(调用方依赖被调用方可用)低(解耦)
实时性实时有延迟
可靠性依赖对方服务依赖 MQ,可重试
适用场景需要立即返回结果异步通知、流量削峰、事件驱动

实际项目中,同步和异步是搭配使用的。核心链路用同步保证一致性,非核心操作(发通知、记日志、统计数据)用异步解耦。

2. gRPC vs REST

REST (HTTP + JSON)gRPC (HTTP/2 + Protobuf)
性能一般(JSON 解析慢)高(二进制、压缩好)
可读性好(JSON 直观)差(二进制)
语言无关是是(代码生成)
流式通信不支持(SSE/WebSocket 另说)支持(4 种流模式)
适用对外 API、浏览器端内部服务间高性能调用

简单来说:对外给人用的 API 选 REST,内部服务之间追求性能选 gRPC。

3. 超时、重试、熔断

这三个是微服务弹性设计的三板斧。

超时(Timeout): 每次调用都要设超时时间,防止一个慢服务把整条链路拖死。

重试(Retry): 失败后重试,但要注意几个坑:

  • 幂等性:不是所有接口都能重试(写操作要慎重)
  • 重试风暴:所有客户端一起重试会加剧后端压力
  • 退避策略:指数退避 + 抖动(Exponential Backoff with Jitter)

熔断(Circuit Breaker):

Closed(关闭)→ 正常请求,失败计数
    ↓ 失败率超阈值
Open(打开)→ 直接返回失败,不调用后端
    ↓ 等待一段时间(半开)
Half-Open(半开)→ 放少量请求试探
    ↓ 成功 → 回到 Closed
    ↓ 失败 → 回到 Open

常见实现:Sentinel(阿里,功能最全)、Resilience4j(轻量,Java 8+ 函数式)、Hystrix(已停更,不推荐新项目用)


四、分布式事务

这是微服务最头疼的问题之一。没有银弹,只有 trade-off。

常见方案对比

方案一致性性能复杂度适用场景
2PC / XA强一致差中传统单体拆服务,强一致要求高
TCC最终一致中高对性能有要求,业务可分 Try/Confirm/Cancel
可靠消息 + 最终一致最终一致好中异步场景,容忍短暂不一致
Saga最终一致好高长事务、多服务编排
本地消息表最终一致好低简单可靠,业务侵入小

最常用的方案:可靠消息最终一致

1. 业务操作 + 写本地消息表(同一个本地事务)
2. 后台任务定时扫描消息表,投递到 MQ
3. 消费端消费,幂等处理
4. 消费成功后更新状态 / 删除消息

这个方案的核心思路是:用本地事务保证”业务做了 + 消息发了”是原子的,然后靠 MQ 的可靠性保证最终一定会被消费。

CAP & BASE

CAP 定理: C(一致性)、A(可用性)、P(分区容错性)三者不可兼得。 分布式系统中 P 是必须的,所以只能在 C 和 A 之间权衡。

  • CP 系统:etcd、ZooKeeper、HBase —— 一致性优先
  • AP 系统:Eureka、Cassandra —— 可用性优先

BASE 理论: Basically Available(基本可用)、Soft state(软状态)、Eventually consistent(最终一致)。 对大多数互联网业务,最终一致就够了,不必强求强一致。

金融场景另说——但银行内部的很多系统,其实也不是所有操作都要强一致的。关键是想清楚哪些数据必须强一致、哪些可以容忍短暂不一致。


五、可观测性

三大支柱

作用工具
Logging(日志)记录具体事件,排查问题ELK、Loki
Metrics(指标)聚合统计,监控告警Prometheus、InfluxDB
Tracing(链路追踪)请求链路,性能分析Jaeger、Zipkin、SkyWalking

三者是互补关系,不是替代关系。排查问题的路径通常是: 告警(Metrics)→ 定位到具体请求(Tracing)→ 看详细错误(Logging)

告警分级策略

级别响应时间通知方式示例
P0 - 紧急立即(5 分钟内)电话 + 短信 + IM整个系统不可用、数据丢失
P1 - 严重15 分钟内IM + 电话核心功能不可用、大量用户影响
P2 - 一般1 小时内IM非核心功能异常、性能下降
P3 - 提示工作日处理邮件 / 工单磁盘使用率预警、日志告警

没有分级的告警 = 没有告警。告警泛滥的结果就是大家都麻木了,真正重要的告警反而被忽略。

黄金指标(Four Golden Signals)

Google SRE 提出的四个关键监控指标:

  1. 延迟(Latency) - 处理请求花了多久
  2. 流量(Traffic) - 每秒多少请求
  3. 错误率(Errors) - 失败请求占比
  4. 饱和度(Saturation) - 资源使用了多少(CPU、内存、磁盘)

把这四个指标的趋势图看明白,系统的健康状况基本就有数了。


六、部署策略

常见发布方式对比

方式零停机回滚速度资源成本流量控制适用场景
重建发布❌慢低❌开发环境
滚动发布✅中低粗(副本数)大多数场景
蓝绿发布✅快高(2 套环境)✅(切换快)重要业务
灰度发布✅快中✅(精确控制)大版本、风险高
A/B 测试✅快中✅(按用户特征)功能验证

灰度发布的几种实现方式

  • 副本数比例:简单粗糙,按 Pod 数量比例(不精确)
  • Ingress / 网关权重:Nginx / Istio 按比例分流(更精确)
  • Header / Cookie 路由:指定用户走新版本(内测用)
  • 按地域 / 用户分群:更精细的灰度策略

七、安全

微服务的安全是体系化的,不能只靠防火墙。

1. 认证(Authentication) — 你是谁

  • JWT、OAuth2、SAML、mTLS

2. 鉴权(Authorization) — 你能做什么

  • RBAC(基于角色)、ABAC(基于属性)

3. 服务间安全

  • mTLS(双向 TLS)- 服务身份认证
  • Service Mesh(Istio)统一管理

4. 数据安全

  • 传输加密(TLS)
  • 存储加密
  • 敏感数据脱敏

5. 网络安全

  • 网络策略(K8s NetworkPolicy)
  • 安全组 / 防火墙
  • WAF(Web 应用防火墙)

八、几个常被问到的问题

最后整理几个面试中高频出现的问题,也是实际工作中经常需要思考的。

Q: 你怎么设计一个高可用的微服务架构?

  1. 多可用区部署,避免单点故障
  2. 服务无状态化,方便水平扩展
  3. 限流、熔断、降级,防止雪崩
  4. 多级缓存,减轻数据库压力
  5. 异步解耦,用消息队列削峰
  6. 完善的监控告警,快速发现问题
  7. 灰度发布 + 自动回滚

Q: 微服务带来了什么问题?

  • 分布式系统复杂度(网络延迟、分区容错、一致性)
  • 运维成本高(服务多、环境复杂)
  • 排查问题困难(调用链长)
  • 数据一致性难(分布式事务)
  • 团队协作成本高(跨服务联调)

所以不是所有系统都适合微服务,要权衡收益和成本。

Q: Service Mesh 是什么?和 API 网关有什么区别?

Service Mesh(服务网格)是微服务间通信的基础设施层, 典型实现是 Sidecar 模式(每个 Pod 旁边挂一个代理)。

和 API 网关的区别:

  • API 网关:南北向流量(外部 → 内部),一层
  • Service Mesh:东西向流量(服务间),每服务都有

功能上有重叠(路由、限流、熔断、监控),但位置不同。 Istio 是目前最流行的 Service Mesh 实现。

Q: 怎么判断一个系统要不要拆微服务?

看痛点:

  • 团队协作冲突严重 → 需要解耦
  • 单服务部署太频繁,影响稳定性 → 需要独立发布
  • 某些模块性能瓶颈,需要单独扩展 → 需要独立扩缩容
  • 技术栈需要灵活选择 → 需要异构

如果团队小、业务简单,单体反而更高效。 微服务不是银弹,是复杂度的转移。

Q: 分布式 ID 生成方案有哪些?

  1. UUID:简单,但是无序、长、不适合做主键
  2. 数据库自增:简单,但单点瓶颈
  3. 号段模式:一次取一批,减少数据库压力(美团 Leaf)
  4. Snowflake(雪花算法):64 位,时间有序,趋势递增
    • 1位符号 + 41位时间戳 + 10位机器ID + 12位序列号
    • 主要问题:时钟回拨
  5. Redis INCR:性能好,依赖 Redis 高可用

写在最后

微服务这个话题很大,一篇文章不可能穷尽。我整理这些内容的过程中,最大的感受是:架构设计的核心不是用了多少技术,而是在各种约束条件下做合理的 trade-off。

没有最好的架构,只有最适合当前阶段的架构。

如果你觉得这篇文章有用,欢迎分享给需要的朋友。有问题也可以在评论区交流~