1 什么是微服务?
微服务不是“把服务做小”,而是一种按业务拆分的架构思想:
把单体应用按领域边界(如用户、订单、支付)拆成多个高内聚、低耦合、独立进程、独立数据库、独立部署的小服务,服务间用 HTTP/gRPC 等轻量协议通信,技术栈也可自由选择(Java/Go/Python 各用各的)。
- 分布式系统(Distributed System):一种将系统组件部署在多个物理节点上,通过网络协同工作的架构范式。
- 微服务(Microservices):一种基于业务领域边界构建的分布式架构风格,强调服务自治、独立演进与松耦合协作。
1.1 为什么需要微服务?(直击单体痛点)
单体架构的四大死穴:
🔹部署:改一点,发全部→ 上线风险高;
🔹扩容:扩一个,全跟着涨→ 资源浪费严重;
🔹代码:多人抢一库→ 合并冲突多、构建等待久;
🔹技术:技术绑死→ 想换框架?重写半边天。
微服务对症下药:✅ 独立部署|✅ 按需扩容|✅ 团队自治|✅ 技术解耦
1.2 微服务不是银弹,用对时机才有效
🔹适合微服务:团队 ≥5人|代码 ≥10万行|业务高频迭代|需独立扩缩容或技术异构;
🔹坚持单体更优:小系统(如内部管理、MVP验证)、低流量、业务稳定、人力有限——简单即可靠。
⚠️ 过早微服务 = 自建复杂度,却无实际收益。
1.3 单体 vs 微服务
| 维度 | 单体架构 | 微服务架构 |
|---|---|---|
| 代码 | 一个仓库,越长越难管 | 多个仓库,各司其职,边界清晰 |
| 部署 | 全量发布,牵一发而动全身 | 某服务更新,其他照常运行 |
| 扩容 | 整体加机器,大炮打蚊子 | 哪儿忙扩哪儿(如秒杀只扩订单服务) |
| 故障 | 一处崩,全站挂 | 隔离故障,降级兜底,全局可用 |
| 演进 | 初期快,后期维护成本爆炸 | 初期基建重,长期迭代更快更稳 |
| 技术 | 一套技术栈,难以替换 | “合适场景用合适语言”,灵活演进 |
| 运维 | 简单(管1个)→ 但不可持续 | 复杂(管N个+中间件)→ 但可标准化自动化 |
| 适合谁 | 小项目、MVP、验证阶段 | 中大型系统、高频迭代、多团队协作场景 |
1.4 微服务的组成及选型(这里比较全可以参考哈)
| 组件类型 | 推荐实现 | 核心能力(一句话概括) |
|---|---|---|
| 1. 服务注册与发现 | Nacos | 自动感知服务上下线,实时同步健康实例列表 |
| 2. 配置中心 | Nacos | 集中存储 + 实时推送配置,实现配置与代码分离 |
| 3. API 网关 | Spring Cloud Gateway | 统一入口路由 + 权限校验 + 流量控制 + 协议转换 |
| 4. 服务间通信 | OpenFeign(HTTP) Dubbo(RPC) | Feign:像调本地方法一样发 HTTP 请求; Dubbo:高性能远程过程调用,内置负载均衡与容错 |
| 5. 负载均衡器 | Spring Cloud LoadBalancer | 客户端自动选择可用服务实例,支持自定义策略 |
| 6. 熔断降级 & 限流 | Sentinel | 实时拦截异常流量,自动熔断故障服务,防止雪崩 |
| 7. 分布式事务 | Seata | 保证跨服务操作要么全部成功,要么全部回滚(AT/TCC/Saga) |
| 8. 消息队列 | Apache RocketMQ | 异步解耦 + 削峰填谷 + 事务消息保障最终一致性 |
| 9. 分布式追踪 | SkyWalking | 一键追踪请求全链路,定位慢调用与异常节点 |
| 10. 服务网格 | Istio | 无需改代码,实现服务间安全通信、流量治理与可观测性 |
| 12. 日志管理 | ELK Stack | 一站式收集、搜索、分析和可视化所有服务日志 |
| 13. 容器和编排 | Docker + Kubernetes | 标准化运行环境 + 自动部署、扩缩容、自我修复 |
| 14. CI/CD | GitLab CI / GitHub Actions | 代码提交后自动构建、测试、打包、部署到环境 |
| 15. 监控和报警 | Prometheus + Grafana + Alertmanager | 自动采集指标 + 可视化看板 + 异常自动通知(邮件/Webhook) |
| 16. 弹性和容错 | K8s + Sentinel + Chaos Mesh | 故障自愈 + 流量兜底 + 主动验证系统抗压能力 |
1.5 生产级选型(Spring Cloud Alibaba)
🔹 基础选型(入门 → 中小型项目)
| 组件类型 | 推荐方案 | 说明 |
|---|---|---|
| 注册 & 配置 | Nacos(唯一推荐) | 一体化能力完备,无优质平替 |
| API 网关 | Spring Cloud Gateway | 性能优、生态好、扩展性强 |
| 服务通信 | OpenFeign(默认) Dubbo(高并发/低延迟场景) | HTTP 简洁,RPC 高效 |
| 熔断限流 | Sentinel | 规则丰富、实时生效、国产深度优化 |
| 链路追踪 | SkyWalking(首选) Zipkin(轻量备选) | 开源免费、探针稳定、UI 友好 |
| 日志管理 | Loki + Grafana(推荐) ELK(日志量 >10GB/天) | 轻量高效、云原生友好 |
🔹 进阶选型(中大型 / 高并发)
- 分布式事务:
Seata AT 模式(通用)+TCC 备案(强一致性关键链路) - 消息队列:
RocketMQ(高可靠、事务消息、阿里系深度适配) - 缓存:
Redis Cluster+Nacos 动态配置缓存策略(如过期时间、降级开关) - 监控告警:
Prometheus + Grafana(统一指标采集,对接 Sentinel/SkyWalking) - 服务网格:
Istio(仅当 Kubernetes 成熟且需精细化流量治理时引入)
🔹 配置最佳实践(避坑要点)
- Nacos:按
环境 + 服务名分组;敏感配置启用Nacos AES 加密。 - Sentinel:规则存储用
Nacos 推模式(持久化+动态生效),禁用内存拉模式。 - Gateway:路由写
lb://service-name,严禁硬编码 IP/端口。 - 版本管理:全程使用
spring-cloud-alibaba-dependenciesBOM 控制版本,禁止单独升级子组件。
2 微服务核心组件
2.1 服务注册 / 发现
🔹 服务注册流程
- 注册请求发起
服务提供者启动时,通过Nacos SDK向 Nacos 服务端发送注册请求,携带关键元数据:- 服务名(
serviceName)、主机 IP(ip) 、服务端口(port) 、健康检查路径(healthChecker.path,如/actuator/health)
- 服务名(
- 元数据持久化与同步
- Nacos 服务端将实例信息持久化写入 MySQL(保障高可用与可恢复性);
- 同时基于Distro 协议(去中心化、最终一致性协议)异步广播至集群其他节点,实现跨节点元数据同步。
- 健康状态维护(心跳机制)
- 提供者以默认 5 秒间隔向服务端发送心跳;
- 服务端判定逻辑:
- 超过15 秒未收到心跳→ 标记该实例为
UNHEALTHY(不健康); - 连续30 秒无心跳→ 从内存及持久层自动剔除该实例。
- 超过15 秒未收到心跳→ 标记该实例为
🔹 服务发现流程
- 首次查询
服务消费者启动时,向 Nacos 服务端发起GET /nacos/v1/ns/instance/list?serviceName=xxx请求,指定目标服务名。 - 服务端响应策略
- Nacos 优先从本地内存缓存(非实时查库)中获取该服务下所有
healthy = true的实例列表; - 返回结果包含 IP、端口、权重、集群名等字段,支持负载均衡路由。
- Nacos 优先从本地内存缓存(非实时查库)中获取该服务下所有
- 客户端本地缓存优化
- 消费者 SDK 自动缓存服务列表,默认每 30 秒拉取一次更新(可配置
nacos.client.refresh.interval); - 后续远程调用直接读取本地缓存,避免频繁网络请求,显著降低延迟与服务端压力。
- 消费者 SDK 自动缓存服务列表,默认每 30 秒拉取一次更新(可配置
🔹 实际应用
- 📚Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现
- 📚Spring Cloud Alibaba基础教程:Nacos的集群部署
2.2 配置中心
🔹 核心流程
| 环节 | 方式 | 关键行为 | 优势 |
|---|---|---|---|
| 初始化 | 拉(Pull) | 客户端启动时全量拉取配置并本地缓存 | 快速就绪,保障启动一致性 |
| 监听变更 | 长轮询(Pull) | 默认每30s 发起一次 HTTP 长连接请求,服务端挂起响应直至超时或有变更 | 低延迟(秒级)、低开销(非高频 polling) |
| 变更通知 | 推(Push) | 配置更新时,服务端立即唤醒对应长轮询请求,返回true变更标识 | 实时触达,避免轮询空转 |
| 生效流程 | 拉 + 刷新 | 客户端收到通知后主动拉取新配置 → 更新本地缓存 → 触发@RefreshScope或ConfigurationProperties自动刷新 | 零重启生效,支持热更新 |
🔹 配置分级模型(Namespace / Group / DataID)
| 层级 | 定位 | 命名建议 | 目的 |
|---|---|---|---|
Namespace | 环境维度 | dev/test/prod | ⚠️ 强隔离,物理级数据分片(不同库表前缀),杜绝跨环境污染 |
Group | 业务维度 | user-service/order-service | 同一微服务所有配置归属统一组,便于批量管理与权限控制 |
DataID | 功能维度 | application.yml/redis.yml/mq.yml | 按配置语义拆分,支持独立发布、灰度、回滚与审计 |
🔹 常见误解澄清:
| 误解 | 真相 |
|---|---|
❌ “我把application.yml放进项目,Nacos 就能自动同步” | Nacos不扫描、不读取、不上传你的本地文件;它只响应你明确声明要拉取的dataId+group+namespace。 |
❌ “Nacos 会把我的@Value("${xxx}")变量自动托管” | 不会!必须显式在bootstrap.yml中配置spring.cloud.nacos.config.data-id,且该dataId对应的配置已在 Nacos 中存在,变量才能从 Nacos 加载。 |
| ❌ “Nacos 能替代 Spring Boot 的所有配置机制” | 不能!它只接管spring.cloud.nacos.config.*指定的部分;server.port、logging.level等基础配置仍走本地application.yml。 |
🔹 实际应用
- 📚Spring Cloud Alibaba基础教程:使用Nacos作为配置中心
2.3 API 网关
🔹 网关的核心功能特性
| 能力 | 一句话本质 | 关键特性 |
|---|---|---|
| 权限控制 | “谁可以访问?”——统一鉴权守门员 | JWT/OAuth2 解析 + RBAC 权限校验,非法请求直拒(401/403) |
| 路由 | “请求发给谁?”——智能路径分发器 | 基于路径、Header、Method 等谓词匹配,动态绑定服务名(如user-service) |
| 负载均衡 | “发给哪个实例?”——客户端自主选节点 | 网关内置 Spring Cloud LoadBalancer,实时感知实例健康状态,支持轮询/权重/响应时间加权 |
💡本质一句话:
网关 = 统一入口 + 安全闸机 + 智能导航 + 流量调度员,所有能力均在客户端侧闭环完成,零侵入后端服务。
🔹 “客户端负载均衡” 和 “服务端负载均衡” 的分水岭
| 类型 | 特征 |
|---|---|
| ✅客户端 LB | 决策在应用进程内、与注册中心联动、策略可编程、面向微服务语义 |
| ❌服务端 LB | 决策在外部中间件、与注册中心解耦、策略静态、仅面向网络地址 |
1. 负载均衡永远作用于“被调用方”(下游服务),而非“调用方”(自身)。
2. 调用方只负责「从多个候选实例中选一个」,不向自己发起转发。
3. 网关 或是 业务服务使用的都是客户端负载均衡。
🔹 路由配置组成
| 配置项 | 说明 | 示例 |
|---|---|---|
路由 ID(id) | 路由的唯一标识 | user-service-route |
路由目标(uri) | 路由的目标地址: • http://表示固定地址• lb://表示根据服务名负载均衡 | lb://user-servicehttp://mockapi.com |
路由断言(predicates) | 判断请求是否匹配该路由的规则集合(多个断言为AND 关系) | 见下表 |
路由过滤器(filters) | 对匹配请求的请求或响应进行增强处理(如增删 Header、限流、重试等) | 见下表 |
🔹 内置路由断言(Predicates)列表
| 名称 | 说明 | 示例 |
|---|---|---|
After | 是某个时间点后的请求 | - After=2037-01-20T17:42:47.789-07:00[America/Denver] |
Before | 是某个时间点之前的请求 | - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai] |
Between | 是某两个时间点之间的请求 | - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver] |
Cookie | 请求必须包含指定名称和正则匹配值的 Cookie | - Cookie=chocolate, ch\.p |
Header | 请求必须包含指定名称和正则匹配值的 Header | - Header=X-Request-Id, \d+ |
Host | 请求 Host 头必须匹配指定域名(支持通配符) | - Host=**.somehost.org,**.anotherhost.org |
Method | 请求方式必须是指定 HTTP 方法 | - Method=GET,POST |
Path | 请求路径必须匹配指定 Ant 风格路径模式 | - Path=/red/{segment},/blue/** |
Query | 请求必须包含指定参数名(支持可选正则值) | - Query=name, Jack- Query=name |
RemoteAddr | 请求者 IP 必须在指定 CIDR 范围内 | - RemoteAddr=192.168.1.1/24 |
Weight | 按权重将流量分发到某组路由(需配合Group使用) | - Weight=group1, 8 |
🔹 内置路由过滤器工厂(Filters)种类
Spring Cloud Gateway 提供了31 种不同的路由过滤器工厂。例如:
| 名称 | 说明 |
|---|---|
AddRequestHeader | 给当前请求添加一个请求头 |
RemoveRequestHeader | 移除请求中的一个请求头 |
AddResponseHeader | 给响应结果中添加一个响应头 |
RemoveResponseHeader | 从响应结果中移除一个响应头 |
RequestRateLimiter | 限制请求的流量(需集成 Redis) |
💡 其他常用过滤器还包括:
Retry,StripPrefix,SetPath,DedupeResponseHeader,SaveSession,SetStatus等(共 31 种,详见官方文档)。
🔹 实际应用
- 📚Spring Cloud构建微服务架构:服务网关(Spring Cloud Gateway)
2.4 服务通信
🔹 微服务调用方式速查表
| 方式 | 类型 | 协议 | 是否声明式 | 负载均衡 | 注册中心集成 | 适用场景 |
|---|---|---|---|---|---|---|
LoadBalancerClient | 底层 API | HTTP | ❌ | ✅(手动选实例) | ✅ | 需精细控制选例逻辑 |
RestTemplate(Ribbon) | 模板类 | HTTP | ❌ | ✅(自动) | ✅ | 简单 HTTP 调用(已不推荐新项目使用) |
@FeignClient | 声明式客户端 | HTTP | ✅ | ✅(自动) | ✅ | 接口化开发、HTTP 服务间调用 |
@DubboReference | RPC 代理 | TCP(二进制) | ✅ | ✅(自动) | ✅ | 高性能、低延迟、强一致内部调用 |
✅一句话选型建议:
- 写 REST API → 选
@FeignClient;- 写核心链路/高并发内部服务 → 选
@DubboReference;- 学原理或特殊调度 → 用
LoadBalancerClient;RestTemplate + Ribbon仅用于兼容老系统。
🔹RPC 与 HTTP 的核心区别
| 维度 | RPC(如 Dubbo) | HTTP(如 REST/Feign) |
|---|---|---|
| 定位 | 远程过程调用协议(让远程调用像本地方法一样) | 应用层通信协议(通用、无状态、基于请求-响应模型) |
| 传输层 | 通常基于TCP(长连接、二进制流) | 基于TCP,但语义上是应用层协议(明文/JSON/XML) |
| 数据格式 | 二进制序列化(Hessian2、Kryo、Protobuf)→ 小、快、语言相关 | 文本为主(JSON/XML)→ 可读、通用、跨语言友好 |
| 性能 | ⚡ 高(低序列化开销、连接复用、无 HTTP 头开销) | 🐢 相对低(文本解析慢、Header 冗余、短连接默认) |
| 耦合度 | ⚠️ 较高(强依赖接口定义、序列化协议、注册中心) | ✅ 较低(URL + JSON 即可调用,浏览器/Fiddler 直接测) |
| 典型框架 | Dubbo、gRPC、Thrift | SpringRestTemplate、Feign、Axios、curl |
💡一句话理解:
HTTP 是“打电话说普通话”——通用、易懂、谁都能接;
RPC 是“打电话说密语+专用耳机”——更快更省,但双方得装同款APP、约定暗号。
🔹 声明式 vs 命令式
| 维度 | 声明式 | 命令式 |
|---|---|---|
| 怎么写 | 写接口/注解(如@FeignClient) | 写调用代码(如restTemplate.getForEntity(url, ...)) |
| 谁干活 | 框架自动代理 + AOP 增强 | 开发者手动拼 URL、选实例、发请求 |
| 关注点 | 业务逻辑(What) | 实现细节(How) |
| 推荐场景 | ✅ 主流开发(简洁、安全、可维护) | ⚠️ 调试、学习原理、特殊定制 |
🌟 本质:
声明式 =“定义契约,框架实现”;
命令式 =“手写流程,自己掌控”。
🔹 Dubbo 为何比 Feign 更适合高并发场景
| 对比维度 | Dubbo | Feign(默认 HTTP) |
|---|---|---|
| 通信协议 | TCP 长连接,自定义Dubbo协议,低开销 | HTTP/1.1 短连接(或复用),文本头+JSON 开销大 |
| 序列化 | 支持高效二进制序列化(Kryo/FST/Hessian) | 默认 JSON(文本、反射多、体积大、解析慢) |
| 线程模型 | Netty 异步非阻塞 + 事件驱动,高吞吐 | 同步阻塞(依赖OkHttp连接池),易线程阻塞 |
| 调用模式 | 原生支持异步(CompletableFuture)、回调 | 默认同步;异步需手动封装或集成 WebFlux/RSocket |
| 服务治理 | 内置负载均衡、熔断、路由、动态配置、元数据中心 | 依赖 Spring Cloud 生态(如 LoadBalancer、Resilience4j),能力分散且较重 |
🔹 实际应用
- 📚Spring Cloud构建微服务架构:服务消费者(LoadBalancerClient、RestTemplate、FeignClient、Dubbo)
- 📚Spring Cloud Alibaba基础教程:Dubbo
2.5 熔断限流
🎈核心功能
| 维度 | 关键能力 | 一句话本质 | 典型场景 |
|---|---|---|---|
| 流控(限流) | QPS/线程/热点/关联/Warm Up | “流量守门员”:按策略动态拦截超额请求 | 秒杀抢购、突发爬虫、接口防刷 |
| 熔断降级 | 慢调用/异常比例/异常数触发 | “系统保险丝”:自动熔断故障依赖,防止雪崩 | 第三方服务超时、数据库抖动 |
| 授权控制 | 黑白名单(基于origin) | “访问安检口”:按来源(租户/IP/Token)精准放行或拦截 | 多租户隔离、API 网关鉴权 |
| 系统防护 | CPU/Load/RT/QPS/线程数全局阈值 | “兜底防火墙”:单机或集群维度防系统性过载 | 高并发下保核心链路可用 |
| 集群流控 | Token Server 统一配额调度 | “全局水龙头”:突破单机限制,实现集群总流量硬约束 | 大促期间保障资源公平分配 |
| 实时监控 | 秒级 QPS/通过量/拦截量/RT/成功率 | “数字仪表盘”:毫秒级指标驱动可观测 + 快速定位 | 性能瓶颈分析、告警联动 |
| 簇点链路 | 自动生成调用拓扑 + 入出口流量 | “调用地图”:可视化依赖关系,识别瓶颈与环路 | 微服务治理、容量规划 |
🔑三大设计哲学(本质总结):
- 零侵入:仅需
@SentinelResource注解,规则全靠控制台配置;- 强实时:秒级指标采集、毫秒级响应、内存保留5分钟(长期可对接 Prometheus);
- 全维度:覆盖单机→集群→系统→链路→授权五层防护体系。
🎈代码实现
@SentinelResource(value = "xxx")是唯一必写代码;所有流控策略(QPS/线程/热点/Warm
Up/关联等)均通过控制台配置生效,零侵入、动态生效、无需重启应用。
| 场景 | 代码示例 | 说明 |
|---|---|---|
| 限流后返回友好提示 | blockHandler = "handleBlock"+ 对应方法 | public String handleBlock(Long id, BlockException e) { return "限流中"; } |
| 异常降级(非限流) | fallback = "fallbackMethod"+ 对应方法 | public String fallbackMethod(Long id) { return "服务降级"; }(不捕获BlockException) |
| 解析调用方(用于授权规则) | 实现RequestOriginParser接口 | 从 Header/IP/Token 提取origin,供「授权规则」黑白名单使用 |
🎈@FeignClient客户端(Feign + Nacos + Sentinel)
importcom.alibaba.csp.sentinel.annotation.SentinelResource;importcom.alibaba.csp.sentinel.slots.block.BlockException;importorg.springframework.cloud.openfeign.FeignClient;importorg.springframework.web.bind.annotation.GetMapping;importorg.springframework.web.bind.annotation.PathVariable;importjava.util.Map;// Feign 自动从 Nacos 发现 user-service 实例(需 application.yml 配置 nacos discovery)@FeignClient(name="user-service")publicinterfaceUserClient{@SentinelResource(value="feign-user-get",// 资源名(控制台规则匹配依据)blockHandler="blockHandler",// 流控/熔断触发fallback="fallback",// 远程异常触发(如 500、超时)fallbackClass=UserClientFallback.class// 静态 fallback 类)@GetMapping("/api/user/{id}")Map<String,Object>getUser(@PathVariable("id")Longid);}// ← 静态 fallback 类(必须 public static 方法,无 Spring 依赖)classUserClientFallback{publicstaticMap<String,Object>blockHandler(Longid,BlockExceptione){returnMap.of("id",id,"status","BLOCKED","reason",e.getClass().getSimpleName());}publicstaticMap<String,Object>fallback(Longid,Throwablet){returnMap.of("id",id,"status","FALLBACK","error",t.getMessage());}}✅ 调用方式不变:
userClient.getUser(123)→ 自动具备:
- ✅ Nacos 服务发现(负载均衡)
- ✅ Sentinel QPS/线程数限流
- ✅ 慢调用/异常比例熔断
- ✅ 全链路降级兜底
🎈@DubboReference客户端(Dubbo + Nacos + Sentinel)
importcom.alibaba.csp.sentinel.annotation.SentinelResource;importcom.alibaba.csp.sentinel.slots.block.BlockException;importorg.apache.dubbo.config.annotation.DubboReference;importorg.springframework.stereotype.Service;importjava.util.Map;@ServicepublicclassUserService{// Dubbo 自动从 Nacos 订阅 user-service 提供者(需 application.yml 配置 nacos registry)@DubboReferenceprivatecom.example.demo.service.UserServiceuserService;@SentinelResource(value="dubbo-user-get",// 资源名(独立于 Feign,可同名也可区分)blockHandler="blockHandler",fallback="fallback",fallbackClass=UserServiceFallback.class)publicMap<String,Object>fetchUser(Longid){returnuserService.getUser(id);// ← 原始 RPC 调用,Sentinel 在其外层织入保护}// 静态 fallback 方法(同上)staticclassUserServiceFallback{publicstaticMap<String,Object>blockHandler(Longid,BlockExceptione){returnMap.of("id",id,"status","DUBBO_BLOCKED","reason",e.getClass().getSimpleName());}publicstaticMap<String,Object>fallback(Longid,Throwablet){returnMap.of("id",id,"status","DUBBO_FALLBACK","error",t.getMessage());}}}✅ 调用方式不变:
userService.fetchUser(123)→ 自动具备:
- ✅ Nacos 服务发现(Dubbo provider 列表)
- ✅ Sentinel 对Dubbo consumer 端的全维度防护(方法级资源)
- ✅ 支持
@DubboReference(check=false)避免启动报错,与 Sentinel fallback 协同更健壮
🔹 实际应用
- 📚Spring Cloud Alibaba基础教程:Sentinel
2.6 分布式事务
- 📚Spring Cloud Alibaba基础教程:Seata
2.7 消息队列
- 📚Spring Cloud Alibaba基础教程:RocketMQ
3 Mall4j商城实战
- 📚mall4j 商城实战