认识微服务

1 阅读7分钟

一、什么是微服务

1. 传统单体架构(对比理解)

一个项目所有功能写在同一个工程里:用户、订单、支付、商品、文件上传全部耦合在一起,打包成一个 war/jar 包部署。 痛点:

  1. 改一行订单代码,整个项目全量发布;
  2. 一处代码崩溃,整个系统宕机;
  3. 技术栈统一,不能单独给模块换框架;
  4. 团队大了代码冲突严重,编译、启动极慢;
  5. 扩容只能整体扩容,资源浪费。

2. 微服务定义

将单一单体应用,按业务领域拆分成多个独立、小型、自治的服务,每个服务只负责一类业务,独立开发、独立部署、独立扩容、独立技术栈,通过网络接口互相调用。

  • 每个服务:单一职责(高内聚、低耦合)
  • 服务之间:通过 HTTP/RPC 通信
  • 数据:大多每个服务自有独立数据库(避免库耦合)

举个电商拆分例子: 单体 → 拆分为 用户服务、商品服务、订单服务、支付服务、购物车服务、物流服务、搜索服务、文件服务

二、微服务核心特征

  1. 单一业务职责 一个服务只做一件事,订单只管下单、退款、库存扣减,不处理用户登录。
  2. 独立部署 更新订单服务,只重启订单,不影响商品、支付。
  3. 独立进程 每个服务是单独进程,互不干扰,某服务故障不会连锁全站崩溃。
  4. 去中心化数据管理 各服务自有数据库,禁止跨服务连库;跨服务查数据只能调用接口。
  5. 轻量级通信 主流两种:
  • RESTful HTTP(简单通用)
  • RPC(Dubbo、gRPC,高性能内网调用)
  1. 技术栈灵活 用户服务用 SpringBoot Java,搜索服务可用 Go,数据分析可用 Python。
  2. 基础设施自动化 依赖容器 Docker、K8s、CI/CD 实现批量部署、弹性扩缩容。

三、微服务架构必备核心组件

一套完整微服务体系,离不开这几大模块:

1. 服务注册与发现(注册中心)

解决:服务地址不固定,消费者怎么找到提供者? 主流:Nacos、Eureka、Consul、etcd 流程: 服务启动 → 把 IP、端口注册到注册中心 消费者启动 → 从注册中心拉取所有可用服务列表

2. 配置中心

统一管理所有服务配置(数据库地址、开关、超时参数),不用每个服务改 yml 重启。 主流:Nacos、Apollo、Spring Cloud Config

3. API 网关(Gateway)

所有前端请求统一入口,做路由转发、鉴权、限流、跨域、日志、灰度发布。 主流:Spring Cloud Gateway、Kong、Sentinel Gateway 作用:屏蔽后端众多微服务,前端只对接网关一个地址。

4. 远程调用(RPC/HTTP 客户端)

服务之间内部调用工具:

  • HTTP:OpenFeign
  • RPC:Dubbo、gRPC

5. 服务熔断、降级、限流(容错组件)

防止某个服务卡顿拖垮整条链路(雪崩效应) 主流:Sentinel、Resilience4j、Hystrix

  • 熔断:下游服务大量报错,直接切断调用,快速失败
  • 降级:高峰期关闭非核心功能(商品详情关闭推荐)
  • 限流:限制每秒请求量,保护服务不被打垮

6. 分布式事务

多服务操作同时成功 / 同时回滚(下单扣库存 + 扣余额) 方案:Seata(AT/TCC/SAGA)、本地消息表、可靠消息队列

7. 消息队列(异步解耦)

同步调用耦合高,用 MQ 异步通信,削峰、解耦、最终一致性 中间件:RocketMQ、RabbitMQ、Kafka 场景:下单后异步发通知、异步扣积分、异步生成物流单

8. 分布式链路追踪

排查跨服务调用慢、报错,记录完整调用链 工具:SkyWalking、Pinpoint、Zipkin、Jaeger

9. 容器编排 & 运维

Docker(打包服务环境)+ K8s(容器调度、自动扩缩容、自愈)

四、单体 vs 微服务优缺点对比

微服务优点

  1. 故障隔离:单个服务宕机不影响整体
  2. 独立迭代,小版本快速发布
  3. 按需扩容:订单高峰只扩容订单服务
  4. 团队并行开发,各司其职
  5. 技术栈自由,适配不同业务性能需求

微服务缺点(重点,不要盲目拆分)

  1. 架构复杂度大幅上升:要维护网关、注册中心、MQ、链路追踪等中间件

  2. 分布式带来一堆新问题:

    • 分布式事务
    • 分布式锁
    • 接口调用超时、重试、数据一致性
    • 跨服务日志排查困难
  3. 运维成本高:几十上百个服务,部署监控压力大

  4. 本地开发麻烦,需要启动一堆依赖服务

  5. 网络开销:服务间调用走网络,比本地方法调用慢

五、什么时候适合用微服务?什么时候别用

适合微服务场景

  1. 业务量大、并发高,单体扛不住扩容
  2. 多团队并行开发,代码经常冲突
  3. 不同模块迭代节奏完全不同(支付每月更,商品每周更)
  4. 部分模块需要高性能、更换技术栈
  5. 对可用性要求高,不能全站停机更新

不推荐微服务(先用单体)

  1. 小型项目、团队只有 1~3 人
  2. 业务简单,模块边界模糊,拆分后大量跨服务调用
  3. 无运维能力,不会部署中间件、容器
  4. 并发低、访问量小,单体完全够用

六、DDD 领域驱动设计:微服务拆分标准

微服务最难的是合理拆分,不能按层拆(Controller/Service 分开),要按业务领域拆分,DDD 是行业标准拆分思路:

  1. 界限上下文:一个独立业务域 = 一个微服务
  2. 聚合根:每个服务以核心实体为边界(订单聚合根 = 订单服务)
  3. 禁止跨服务直接操作数据库,所有数据交互走接口

错误拆分示例: 按技术分层拆分:Web 服务、Service 服务、DAO 服务(调用链极长,完全错误)

正确拆分: 用户域、商品域、订单域、支付域,每个域完整包含自身增删改查逻辑。

七、微服务常见落地架构分层

  1. 客户端层:小程序、APP、管理后台、前端页面
  2. 网关层:统一入口,路由、鉴权、限流
  3. 业务微服务层:用户 / 订单 / 商品等核心业务服务
  4. 公共基础服务层:文件存储、短信、日志、定时任务、第三方支付对接
  5. 中间件层:注册中心、配置中心、MQ、分布式缓存 Redis、链路追踪
  6. 存储层:MySQL 分库分表、Redis、ES、对象存储 OSS

八、微服务常见经典问题(面试高频)

  1. 服务雪崩:大量请求打到故障下游,连锁拖垮所有服务 → 熔断降级解决
  2. 分布式事务:跨服务数据一致性 → Seata、可靠消息队列
  3. 接口幂等:重复下单、重复支付造成脏数据 → 唯一请求 ID 防重
  4. 分布式锁:多服务同时操作库存超卖 → Redis 分布式锁、Zookeeper
  5. 服务版本兼容:接口升级不影响旧调用方 → 版本号、灰度发布
  6. 数据查询跨服务:不连其他库,通过 Feign 调用接口聚合数据

九、总结一句话

微服务是按业务领域拆分、独立自治、分布式协作的架构,用复杂度换取扩展性、可用性和团队并行效率;小项目优先单体,业务规模上来后再逐步拆分微服务,同时配套全套中间件与运维体系。