Theory · Microservice · Overview

微服务架构总览:从单体到云原生

一组围绕业务能力构建、可独立部署的小型服务 —— 拆的是服务,付的是分布式的代价

一句话本质

按业务能力把系统拆成独立开发、独立部署、独立扩缩的服务,用轻量通信协作,数据私有

核心权衡

换来的:独立部署、故障隔离、技术异构、团队自治;付出的:网络不可靠、数据不一致、运维复杂度

本领域导航

本 deck 是入口:注册发现 · RPC · 网关 · 负载均衡 · 熔断限流 · 分布式事务 · 幂等 · ID · 配置 · 可观测 · 网格

这份 deck 回答微服务面试的第一层问题:什么是微服务、为什么拆、怎么拆、拆完要面对什么。组织顺序:演进史 → 定义与特征 → 单体对比 → 拆分收益与代价 → 康威定律与 DDD 拆分方法 → 粒度与反模式 → 全景架构图 → 十二个核心问题导航 → Go 技术栈 → QA。它同时是本库微服务领域 13 份 deck 的目录页。

Evolution

架构演进:每次拆分都在解决上一代的核心矛盾

应用架构演进时间线 从单体、垂直拆分、SOA、微服务到云原生五个阶段的演进:每阶段的部署形态、数据形态与核心矛盾依次变化——单体共享一切但发布耦合,垂直拆分独立部署但数据割裂,SOA 用 ESB 集成但总线笨重,微服务按业务能力拆分并私有数据,云原生进一步把治理下沉到基础设施。 2000 → 2010 → 2014 → 2018 → TODAY 单体 Monolith UI + 业务 + 数据访问 单进程 · 共享 DB 矛盾:一处改动全量发布 代码耦合 · 无法局部扩容 垂直拆分 商城站 后台 各带 DB · 直连互通 矛盾:跨系统调用靠 点对点直连,网状依赖 SOA 服务 A 服务 B ESB 企业服务总线 矛盾:总线承载协议转换、 编排、转换——重、贵、单点 微服务 订单 商品 库存 支付 去中心化:哑管道 + 智能端点 矛盾:分布式全套难题 云原生 K8s 编排 · 声明式 Mesh 治理下沉 Serverless 弹性 开发只写业务 拆分动力始终是同一个:发布与扩容的耦合。SOA 用中心化总线集成存量系统;微服务改成去中心化——治理能力下沉到 SDK(后到 Mesh 下沉到基础设施),服务本身围绕业务能力自治。
讲演进史的关键是讲清每代的"核心矛盾":单体的问题是发布与扩容耦合;垂直拆分后数据与调用网状直连;SOA 把集成逻辑集中到 ESB,总线成了重、贵、慢的单点;微服务的答案是反过来——智能端点哑管道,业务逻辑留在服务内,通信只走轻量协议;云原生再把注册发现、熔断限流这些治理能力进一步下沉到 K8s 和 Mesh。SOA 与微服务的区别是高频对比题。

Definition

微服务的定义:六个可判定的特征

Fowler/Lewis(2014):一组自治的服务,围绕业务能力组织,独立部署轻量机制通信。不是"代码量小",而是六特征同时成立:

1 围绕业务能力

按限界上下文切分,而非技术分层(UI/服务/DAO);每个服务对应一块业务能力

2 独立部署

改一个服务只发一个服务;发布与系统解耦——最实在的收益,也是拆分第一判据

3 数据私有

每个服务私有存储,他人只能走 API 访问;共享数据库 = 假微服务(耦合藏在表结构里)

4 智能端点哑管道

业务逻辑在服务内;服务间只用轻量通信(RPC/消息队列),不做中心化编排总线

5 为失败而设计

依赖随时会挂:超时/重试/熔断/降级是标配;部分失败是常态而非异常

6 演进式设计

边界允许重构:服务可拆可合(Sam Newman《Monolith to Microservices》的拆分/合并模式)

原文关键句:"the service approach … independently deployable … organized around business capabilities";Sam Newman 操作判据:可独立发布、由小团队拥有。是否微服务看这两条,不是数服务数量。

定义题的标准答法:先给 Fowler 的一句话定义,再展开六特征——围绕业务能力、独立部署、数据私有、智能端点哑管道、为失败而设计、演进式。重点强调两个"不是微服务"的常见反例:共享数据库的假拆分,以及拆了服务却要一起发布的分布式单体(下一页展开)。收尾用 Sam Newman 的操作判据:独立发布 + 小团队拥有。

Comparison

单体 vs 微服务:一张表说清收益与代价

对比表

维度单体微服务
部署整包发布,一处改动全量回滚独立发布,变更影响面小
扩展整体扩容,无法按热点伸缩按服务扩容,热点服务单独加机器
故障一崩全崩(单进程)故障隔离,但会级联失败 → 需熔断
数据一个库,本地事务每服务私有库,跨服务一致性难题
技术栈统一可异构(Go/Java/Python 混布)
调用进程内函数调用,强类型可靠网络调用:不可靠、有延迟、要序列化
测试进程内集成测试即可依赖契约测试、集成环境、链路追踪
运维一个应用N 个应用 × M 个实例 × 版本漂移

微服务换来的

  • 发布解耦:几十个团队互不阻塞地发版(最大收益)
  • 故障隔离:单个服务 OOM 不至于拖垮全站
  • 精准扩容:只扩热点服务,资源利用率更高
  • 团队自治:小团队端到端拥有一个服务(Build-it/Run-it)

付出的代价

  • 网络调用从"函数跳转"变成"远程调用":延迟、不可靠、需容错
  • 跨服务数据一致性:本地事务失效 → Saga/TCC/最终一致
  • 可观测性要求陡增:没有链路追踪无法排障
  • 基础设施与流程成本:CI/CD、注册中心、监控告警缺一不可

Fowler 提出的 microservice premium:微服务有一笔固定"保费"(基础设施、运维、分布式复杂度),业务复杂度越高这笔保费越划算;简单业务买贵了。另见其 MonolithFirst 论断:多数团队应先做单体,模块边界清晰后再拆。

对比题建议按表逐维讲:部署、扩展、故障、数据、技术栈、调用、测试、运维。左列收益,右列代价,两边都要讲全——只讲收益是减分项。最后落在 microservice premium:微服务的固定成本(基础设施与分布式复杂度)需要业务复杂度来摊销,所以简单系统拆微服务是负优化。MonolithFirst 是很好的引用论据。

When to Split

什么时候值得拆:三个信号与三个反信号

✅ 该拆的信号

  • 发布阻塞:多个团队改同一个仓库,发版要排期协调——组织协同成本超过代码复杂度
  • 局部热点:某个模块(如推荐、秒杀)需要单独扩容/单独的技术栈,整体扩容太浪费
  • 故障爆炸半径:内存泄漏/死循环拖垮整个进程,需要隔离
  • 模块边界已经清晰:单体内模块间已通过接口访问、低耦合——拆的成本最低的时机

❌ 别拆的反信号

  • 业务领域还没摸清,边界在剧烈变动——先在单体内做模块化
  • 团队规模小(<10 人)、没有 DevOps 与自动化能力——运维成本吃掉所有收益
  • 为了"简历驱动开发"/追新而拆——Martin Fowler:MonolithFirst 是默认答案
  • 数据模型高度耦合:拆服务却共享库,得到分布式单体(最差形态)

拆的正确姿势

绞杀者模式(Strangler Fig):新流量走新服务,按路由灰度逐步迁移,旧功能下线——不搞大爆炸重写

拆的顺序

先拆"边缘稳定"的模块(变化慢、依赖少),后拆核心链路;Sam Newman:优先找"变更率不同"或"风险不同"的边界

拆之前的底座

CI/CD、注册发现、可观测、配置中心要先就位——先有基础设施再拆服务,否则第一天就瘫

这道题考的是判断力不是背功。三个正面信号:发布阻塞、局部热点、故障隔离需求,外加一个时机条件——模块边界已清晰。反面四个:领域未稳、团队太小、简历驱动、数据耦合。给出落地路径:绞杀者模式渐进迁移 + 先拆边缘后拆核心 + 基础设施先行。被问"我们公司该不该拆"时,用信号清单做诊断式回答。

Conway's Law

康威定律:系统结构 = 组织沟通结构

定律本体(Melvin Conway, 1968)

"设计系统的组织,其产生的设计等价于组织内部的沟通结构。"——四个团队做出的系统,天然就是四块互相调用的模块。

  • 第一定律:沟通成本决定模块边界(人话:系统长成组织图的样子)
  • 第二定律:没时间做对,总有时间做短——先能用,回头再做对
  • 第三定律:可能存在线性复杂度的最优设计,但没人扛得住
  • 第四定律:大系统总是演进而来,从不会凭空设计出来

逆康威定律:让架构顺着组织来

想要微服务架构,就先按服务边界组织团队——Team Topologies(2019)给出的四种团队形态:

  • Stream-aligned 团队:端到端拥有一条业务流(订单团队)
  • Platform 团队:提供内部平台(K8s/中间件/脚手架),降低流对齐团队认知负担
  • Enabling 团队:临时赋能,帮助其他团队补能力(如可观测性推广)
  • Complicated-subsystem 团队:深水区专家团队(如推荐算法、支付网关)
1 服务一个团队端到端拥有:开发/测试/部署/值班(You build it, you run it —— Werner Vogels, Amazon)
两个披萨Bezos 的团队规模准则:能被两个披萨喂饱的小团队——对应服务不宜过大
认知负载Team Topologies 的核心度量:一次拆分是否成功,看每个团队要装进脑子的东西是否变少
康威定律是微服务拆分的理论根基:系统结构必然复制组织沟通结构。微服务不是技术决策而是组织决策——想按业务能力拆服务,就得先按业务能力组团队(逆康威定律)。Amazon 的 you build it you run it 把所有权闭环,是 DevOps 与微服务的结合点。面试中把"架构即组织设计"讲出来就是加分项。

Domain-Driven Design

拆分方法论:DDD 限界上下文

DDD 限界上下文划分电商域 电商域被划分为订单、库存、支付、营销、物流五个限界上下文,每个上下文内含自己的一致模型与私有数据库;上下文之间通过上下文映射集成,跨模型的数据交换经过防腐层转换;同一商品一词在不同上下文有不同含义,说明模型只在其上下文内一致。 电商域 · 按限界上下文拆分(每个上下文 = 一个候选微服务) 订单上下文 Order 订单 · 订单项 · 履约状态 聚合:Order / OrderItem 领域事件:OrderCreated 私有库 order_db "商品"=下单快照(名称/价格) 库存上下文 Inventory SKU · 可用库存 · 预占 扣减:预占 + 超时释放 私有库 inventory_db "商品"=SKU 库存计数 支付上下文 Payment 支付单 · 渠道 · 对账 状态机 + 幂等防重 私有库 payment_db "商品"=金额与科目 营销 / 物流上下文 券 · 活动 · 运单 · 地址 同样各自私有库与模型 "商品"=券适用范围 / 包裹项 ACL ACL 上下文映射 Context Map:上下文之间的集成契约(防腐层 ACL 把外部模型翻译成本地模型) 同一个词"商品"在每个上下文里是不同模型——模型只在自己上下文内一致,跨上下文必须翻译
这是"怎么拆"的标准答案:用 DDD 找限界上下文。三个要点:① 上下文是"模型一致"的边界,同一词在不同上下文含义不同(订单里的商品是快照,库存里的是 SKU),所以跨上下文要防腐层翻译;② 每个上下文天然对应候选微服务与私有库;③ 实操工具是事件风暴——把领域事件贴在墙上,事件名词聚类就是上下文候选。常见错误:按技术分层拆(一个服务专门管 DAO)。

Granularity & Anti-patterns

粒度怎么定:警惕"分布式单体"

粒度的判定标准(不数代码行数)

  • 一个服务 = 一个业务能力 + 一个团队能端到端拥有
  • 能独立发布:改它不需要联动改别人(发布耦合 = 拆错了)
  • 数据内聚:核心数据在这个服务内闭环,跨服务只传 ID 与事件
  • 粒度过细的信号:一次用户请求串行跨 5+ 服务;一个需求改 4 个服务;服务间高频同步调用链
  • 粒度过粗的信号:改一个功能要回归整个服务;两个团队天天在同一个服务里冲突

分布式单体 Distributed Monolith(最差形态)

  • 共享数据库:服务拆了,表还是一起用——耦合藏进 schema,谁都不敢改
  • 同步链式调用:A→B→C→D 长事务,任何一个抖动全链路抖动
  • 必须一起发布:接口变更强绑调用方,发版要约时间——比单体还差(单体至少一次编译检查)
  • 循环依赖:A 依赖 B、B 依赖 A,部署顺序死锁
  • 解法:私有库 + 事件驱动解耦 + 明确上下游(依赖只能是 DAG)

上下游铁律

依赖图必须是 DAG:下游(被依赖方)不感知上游;数据同步走事件,不走反向查询;环形依赖用消息队列或抽出公共服务打破

先合后拆

发现拆错粒度不要恋战:把过细的服务先合并回"模块化单体"再重新切分——Sam Newman 把"合并服务"作为一等公民的重构手段

粒度题的核心不是给一个数字,而是给判据:独立发布、数据内聚、依赖成 DAG。分布式单体是必考反模式:共享库、同步长链、绑定发布、循环依赖——它比单体更差,因为既有分布式的成本又有单体的耦合。答"怎么纠正"时提 Sam Newman 的先合后拆,体现工程成熟度。

Big Picture

一张全景图:微服务系统的分层与配套设施

微服务系统全景架构 请求从客户端进入 API 网关完成路由鉴权限流后分发给业务服务;订单商品库存支付等各服务通过 RPC 互联、各自持有私有数据库与缓存,并向消息队列发布事件;注册中心提供寻址、配置中心提供动态配置、可观测平台采集日志指标与链路;全部负载运行在 Kubernetes 编排底座上。 Web / App 第三方调用方 API 网关 路由 · 认证鉴权 · 限流 · 灰度 · 协议转换 APISIX / Kong / Envoy · BFF 聚合层 业务服务层 · RPC 互联(gRPC/HTTP)· 每服务私有数据 订单服务 order_db · cache 商品服务 product_db 库存服务 inventory_db 支付服务 payment_db 用户服务 user_db 同步 RPC · 异步事件(MQ)· 超时/重试/熔断在每一跳生效 消息队列(事件驱动解耦):Kafka / RocketMQ 领域事件广播 · 削峰 · 最终一致性的载体(本地消息表 / 事务消息) 注册中心(发现/健康检查) etcd · Nacos · Consul · K8s DNS CP vs AP 取舍 · lease 心跳 · watch 推送 客户端拿到实例列表后 再做客户端负载均衡(P2C/EWMA) 服务寻址 配置中心 Nacos · Apollo · etcd watch 动态推送 · 灰度 · 审计回滚 限流阈值/降级开关从这里下发 可观测性三支柱:Logging(结构化日志)· Metrics(Prometheus 指标)· Tracing(OpenTelemetry 分布式追踪) trace context 随每一跳 RPC/MQ 传播 —— 跨服务排障的唯一手段 Kubernetes 编排底座:声明式部署 · 自愈 · 弹性伸缩(HPA)—— (可选)Service Mesh 把治理下沉到 Sidecar/Ambient
全景图是回答"描述一个微服务系统"的骨架:请求从客户端到网关(路由/认证/限流/灰度),网关按服务发现分发到业务服务;服务间同步走 RPC、异步走 MQ,每个服务私有数据库;右侧三件套——注册中心负责寻址、配置中心负责动态下发(限流阈值/降级开关都在这)、可观测平台收集三支柱数据;底座是 K8s,治理可进一步下沉到 Mesh。讲图时按请求路径走一遍最自然。

Problem Map

微服务的十二个核心问题 —— 本领域 deck 导航

通信与流量

问题deck
服务间怎么调用?序列化怎么选?服务间通信与 RPC
实例地址动态变化,怎么找到对方?服务注册与发现
请求打到哪个实例?怎么不均?负载均衡
外部流量怎么进来、怎么统一治理?API 网关

稳定性

问题deck
依赖挂了怎么不跟着挂?熔断 · 降级 · 容错
流量洪峰怎么挡?限流
重试/重投导致重复执行怎么办?幂等性设计

数据一致性

问题deck
跨服务操作怎么保证一致?分布式事务
分库分表后主键怎么生成?分布式 ID

工程设施

问题deck
配置怎么动态下发与审计?配置中心
跨几十个服务怎么排障?可观测性
治理能力要写进每个 SDK 吗?服务网格

复习建议:这张图就是面试官追问链——"你们是微服务架构?" → 通信怎么做 → 实例挂了怎么办 → 流量怎么保护 → 数据不一致怎么办 → 线上怎么查。每步对应一份 deck。

这页是本领域的目录:四个象限——通信与流量(RPC/发现/负载均衡/网关)、稳定性(容错/限流/幂等)、数据一致性(分布式事务/分布式 ID)、工程设施(配置/可观测/网格)。背下这个追问链,面试时主动把话题引到自己熟的区域。

Go Ecosystem

Go 微服务技术栈:框架与基础设施选型

主流框架(2026-09 版本核实)

框架特点
go-zero v1.10大而全:goctl 代码生成、内置超时/熔断/限流/监控,API+RPC 双模式,中文社区大
Kratos v2B 站开源:gRPC 为核心、transport/log 中间件分层、Wire 依赖注入、Protobuf 定义 API
Kitex字节开源:高性能 RPC,多协议(Thrift/Protobuf/HTTP2)、内置治理能力、对齐 CloudWeGo 生态
go-micro / Goago-micro 轻量可插拔接口;Goa design-first 代码生成——面试常作"了解即可"项

基础设施选型(本库均有专题)

组件Go 生态常见选择
注册发现etcd(Raft,CP)· K8s 原生 Service/DNS
配置Nacos · Apollo · etcd+viper 本地 watch
RPCgRPC(google.golang.org/grpc v1.8x+)· 双协议网关 grpc-gateway
MQKafka(sarama/franz-go)· RocketMQ(rocketmq-client-go)
存储MySQL(GORM/sqlx)· Redis(go-redis)
可观测OpenTelemetry Go · Prometheus client_golang · zap/slog
熔断限流sony/gobreaker · sentinel-golang · go-zero 内置

选型话术:小团队直接上 go-zero/Kratos(框架自带治理);强定制团队用 gRPC + 自选治理库(gobreaker/sentinel-golang 自由组合);K8s 深度用户把发现/配置交给 K8s 原生 + Mesh,SDK 只保留业务。没有银弹,关键是治理能力三选一:框架内置 / SDK 组合 / Mesh 下沉。

Go 面试常问"你们用什么框架、为什么"。三条主线记忆:go-zero/Kratos 全家桶(治理内置,出活快);裸 gRPC+治理库自由组合(灵活但要自己拼);K8s+Mesh 路线(治理下沉,SDK 变薄)。基础设施表对应本库其他领域 deck:etcd→注册发现、Kafka→MQ、Prometheus/OTel→可观测。版本号说明"信息是新的"即可,不必背。

Interview QA · 1/2

高频 QA(一):概念与拆分

Q1 微服务和 SOA 的区别?

ESB vs 哑管道协议重量数据治理

SOA 中心化:ESB 承担协议转换/消息路由/编排,多用 WS-* 重协议,面向存量系统集成;微服务去中心化:智能端点哑管道,轻量协议(REST/gRPC/MQ),服务自治并私有数据。一句话:SOA 集成异构系统,微服务拆分自治业务。

Q2 服务怎么拆?粒度怎么定?

限界上下文独立发布数据内聚

用 DDD 找限界上下文(事件风暴辅助),每个上下文一个候选服务;粒度判据是"能独立发布 + 一个团队端到端拥有 + 数据内聚",不数代码行数;拆完验证依赖图是 DAG。粒度过细出现长同步链就先合并再拆。

Q3 我们是单体,要拆微服务吗?

MonolithFirst三个信号

默认不拆(Fowler MonolithFirst):先在单体内做好模块化。出现三个信号才拆——多团队发布互相阻塞、局部模块需要独立扩容、故障需要隔离。拆法用绞杀者模式渐进迁移,先拆边缘稳定模块,基础设施(CI/CD/发现/观测)先行。

Q4 微服务带来哪些问题?怎么解决?

链路长一致性排障难

网络不可靠→超时/重试/熔断降级;数据不一致→Saga/TCC/本地消息表(最终一致);排障难→TraceID 全链路追踪 + 结构化日志 + 指标;配置漂移→配置中心;重复调用→幂等设计。答题套路:问题→方案→对应组件。

Q5 什么是分布式单体?

共享库绑定发布同步长链

服务拆了但耦合没拆:共享数据库、接口变更强绑发布、同步调用链过长、循环依赖。比单体更糟——付出分布式成本却留着耦合。解法:数据私有、事件驱动解耦、依赖 DAG 化、必要时先合并重新拆。

Q6 康威定律是什么?有什么用?

组织=架构逆康威

系统设计复制组织沟通结构(Conway 1968)。用途:① 想要什么架构先组什么团队(逆康威定律/Team Topologies);② 评估拆分是否可行——团队不会因此缩小认知负载就是假拆分;③ 解释为什么跨部门系统总是集成困难。

上半场六题偏概念与拆分。Q1 的记忆点是"智能端点哑管道";Q2 是最重要的一题,判据三连:独立发布、团队拥有、数据内聚;Q3 展现工程判断(MonolithFirst);Q4 用"问题→方案→组件"模板串起整个领域;Q5 分布式单体要能举共享数据库的例子;Q6 落到逆康威的组织设计。

Interview QA · 2/2

高频 QA(二):架构与工程

Q7 微服务下数据库怎么设计?

database-per-service跨库靠事件

每服务私有库,禁止跨服务直连他库;查询聚合走 API 组合或 CQRS 读模型;跨服务写一致用 Saga/本地消息表;反模式是共享库。理由:只有数据私有,边界才真实——表结构不再是被共享的隐式契约。

Q8 微服务的 API 怎么设计与管理?

契约先行版本化向后兼容

契约先行(Protobuf/OpenAPI 定义即文档)、版本化(URL 或 package 版本)、只增不改的向后兼容原则(字段只加不删、语义不变);对外 REST 对内 gRPC 是常见组合;变更走 review + 兼容性检查(buf breaking / oasdiff)。

Q9 服务间同步调用还是异步消息?

同步要答案异步要解耦

判断依据:调用方是否需要"立刻的答案"。需要实时结果(扣库存)→ 同步 RPC + 熔断限流;只是通知结果(发积分、发短信)→ 异步事件 + MQ 削峰解耦。混合形态最常见:主链路同步、旁路异步。链路越长越倾向事件化。

Q10 微服务怎么灰度发布?

金丝雀按流量/维度

新版本先接 1%→5%→50%→100% 流量,观察指标再放量;网关按 header/用户标签做精准灰度,Mesh 用 VirtualService 按权重分流;配合快照回滚与告警熔断。发布策略对比(滚动/蓝绿/金丝雀)详见服务网格 deck 的流量管理部分。

Q11 微服务规模多大算合适?

团队约束认知负载

用约束倒推:每个服务一个 owning 团队,团队数 × 每团队能养 2-4 个服务 = 服务数上限;再校验每个服务是否独立可发布。规模不是目标——很多公司几十个服务就解决了协作问题,"几百个微服务"多数是分布式单体。

Q12 单体迁移微服务的完整路径?

模块化绞杀者数据拆分

四步:① 单体内模块化(接口化、依赖理清);② 基础设施先行(CI/CD、发现、观测、配置);③ 绞杀者渐进迁移——新能力用新服务,老功能按接口逐个搬;④ 数据最后拆:先共享库只读视图隔离,再逐步私有化。全程可回滚。

下半场六题偏工程。Q7 数据库设计答"database-per-service + 事件补一致";Q8 API 治理三件套:契约先行、版本化、向后兼容;Q9 同步异步的判断标准是"要不要立刻的答案";Q10 灰度结合网关与 Mesh 讲;Q11 用团队约束倒推服务数;Q12 四步迁移路径是综合题的高分答案。

Related & References

相关知识点与参考

本领域 deck(微服务 · theory/microservice/)

跨领域相关 deck

参考链接(一手来源)

收尾页两列:左列本领域 12 份专题 deck(按主题分组),右列跨领域依赖——Kafka 是事件驱动底座、Redis 锁用于防重、MySQL 事务是分布式事务的对照基线、HTTP/Protobuf 是 gRPC 的协议底层。参考链接全部为一手来源:Fowler 原文、Sam Newman 两本书、Team Topologies、DDD 原书。