架构风格:单体、分层、微服务
一、单体与分层架构
单体(Monolith):整个应用是一个可部署单元,所有功能在同一进程内,共享同一套代码库与数据库。优点:开发简单、部署简单、调用本地无网络开销、事务容易做。缺点:规模一大,构建与发布变慢、局部故障可能拖垮整体、难以按模块独立扩展或换技术栈。
分层架构(Layered):在单体内部按职责划分层次,常见为表现层(UI/API)、业务层(领域逻辑)、数据访问层(持久化)。上层只依赖下层,避免跨层调用。这样代码结构清晰、职责分明,但仍是单体部署;若分层边界清晰、模块化做得好,后续要拆微服务会容易很多。
二、微服务的动机与边界划分
微服务(Microservices):把系统拆成多个小服务,每个服务独立部署、独立扩展、可选用不同技术栈;服务之间通过 API 或消息通信。动机常包括:独立发布(改一个功能只发一个服务)、按需扩展(只扩瓶颈服务)、团队自治(不同团队负责不同服务)、故障隔离(一个服务挂了不必然拖垮全部)。
边界划分是难点:拆得太细则调用链长、运维与调试复杂;拆得太粗则失去微服务优势。常见做法:按业务能力或限界上下文(见 DDD)划分——一个服务负责一块相对完整的业务,内聚高、与外部的接口清晰;避免按技术层拆(「一个用户服务、一个订单服务」比「一个读服务、一个写服务」更合理)。划分时还要考虑数据:尽量让每个服务拥有自己的数据,通过 API 暴露,避免多个服务直接共享同一数据库。
三、服务间通信:同步与异步
微服务之间要协作,通信方式大致分同步与异步。
同步:调用方发请求后等待对方响应(如 HTTP/RPC)。简单、直接,但调用方与被调方强耦合、若被调方慢或挂则调用方也被拖住;链路过长时延迟累加。适合「需要立即拿到结果」的查询或写后读。
异步:通过消息队列或事件总线,发方发完即继续,收方异步消费。解耦、可削峰填谷、失败可重试;但语义变为「最终一致」、调试与追踪更复杂。适合通知、审计、非强实时的流程(如下单后发短信、扣库存后发事件)。
实际系统常混合使用:关键路径用同步,非关键或可滞后用异步。注意:同步调用要设超时与熔断,避免雪崩;异步要保证至少一次或恰好一次语义、幂等与顺序需求。
四、何时微服务、何时不
适合考虑微服务:团队多、模块边界清晰且需独立发布与扩展;业务域复杂、不同子域技术栈或伸缩需求差异大;已有明确瓶颈模块希望单独扩或替换。此时若单体已难以维护,拆成微服务是合理方向。
不必急于微服务:团队小、业务还在快速试错期;单体还没写清楚、模块边界混乱——先做好分层与模块化再谈拆;没有足够的运维与可观测性——分布式后排障与部署复杂度都会上来。很多团队的问题是「单体写成一团」而不是「单体本身不行」;先把单体做成模块化单体(见下节),再按需拆出个别服务,往往更稳。
何时用微服务、何时不
- 适合:团队多、边界清晰、需独立发布/扩展、有运维与可观测基础
- 不必急于:团队小、业务未定型、单体尚未模块化、运维能力不足
- 先做好模块化单体,再按需拆出服务,比一上来就「全微服务」更稳妥
五、模块化单体的价值
模块化单体(Modular Monolith):仍然是单体部署,但在代码与依赖上严格按模块划分——模块之间只通过明确的接口调用,不跨模块直接访问实现或数据库表。这样既保留单体的简单部署与事务便利,又为将来拆微服务留好边界:哪天要拆,只需把某个模块换成独立进程与 API,其余调用改为远程调用即可。
价值在于:在「全微服务」之前,用较低成本获得清晰边界与可维护性;避免「为了微服务而微服务」导致过早承受分布式复杂度。很多系统从模块化单体起步,等真正遇到扩展或团队规模瓶颈时,再按模块逐个拆出,是更务实的路径。
模块化单体要点
- 单体部署,但代码按模块划分,模块间仅通过接口交互
- 为将来拆微服务预留边界,需要时可将某模块独立成服务
- 先写好模块化单体,再按需拆,比一上来全微服务更稳妥
一句话: 单体简单直接,分层在单体内理清职责;微服务按业务能力划分边界、服务间同步或异步通信。何时微服务看团队与运维能力,不必急于拆;模块化单体先写好边界与接口,再按需拆出服务,往往更务实。
六、小结
单体与分层:单体一进程一库,分层在内部划清表现/业务/数据层。微服务:按业务能力或限界上下文划分,各自数据与 API,同步或异步通信。何时用:看团队规模、边界清晰度与运维能力;不必急于全微服务。模块化单体:先写好模块与接口,再按需拆,更稳妥。下一章讲领域驱动设计(DDD)入门,用限界上下文与领域模型把「边界」想清楚。