单体架构 vs 微服务的取舍
微服务不是银弹,也不是"更先进"的必然选择。在决定采用微服务架构前,需要认真评估成本与收益。
单体架构的优势
- 开发简单,本地调试方便
- 事务边界清晰(单一 DB)
- 部署运维成本低
- 性能好(无网络调用开销)
- 适合小团队(< 5 人)
微服务的适用场景
- 不同模块需要独立扩缩容
- 大型团队需要并行开发
- 技术异构(不同语言/框架)
- 部分模块需要高可用隔离
- 业务复杂度已超过单体边界
核心概念名词解释
服务注册与发现
服务启动时向注册中心(Eureka/Nacos/Consul)上报自己的地址和元数据;调用方从注册中心查询目标服务的实例列表,通过负载均衡选择一个实例发起调用。无需硬编码 IP:Port。
OpenFeign
Spring Cloud 提供的声明式 HTTP 客户端。通过定义接口 + 注解,无需手写 RestTemplate 代码,自动集成负载均衡、熔断、日志等功能。调用远程服务像调用本地方法一样简单。
LoadBalancer(负载均衡)
Spring Cloud LoadBalancer(替代旧版 Ribbon)在客户端侧实现负载均衡,从注册中心获取实例列表,按轮询(Round-Robin)或随机(Random)策略选择实例。
熔断器(Circuit Breaker)
防止级联故障的保护机制。当某个服务持续失败时,熔断器"断开"——后续请求直接返回降级响应,不再等待超时。一段时间后进入半开状态,尝试少量请求,若成功则"闭合"恢复正常。
Resilience4j
轻量级容错库,Spring Cloud 推荐的 Hystrix 替代品。提供熔断器(CircuitBreaker)、限流(RateLimiter)、重试(Retry)、舱壁隔离(Bulkhead)、超时(TimeLimiter)等模式。
服务网格(Service Mesh)
将服务间通信的横切关注点(负载均衡、熔断、认证、链路追踪)从应用代码中剥离,下沉到基础设施层(Sidecar Proxy,如 Envoy)。Istio 是最流行的服务网格实现。
Spring Cloud 核心组件全景
┌─────────────────────────────────────────────────────────────────┐
│ Spring Cloud 生态全景 │
└─────────────────────────────────────────────────────────────────┘
客户端请求
│
▼
┌──────────────────────────────────────┐
│ Spring Cloud Gateway(API 网关) │ ← 路由、鉴权、限流、日志
│ 路由规则:/user-service/** → user-svc │
│ 路由规则:/order-service/** → ord-svc │
└──────────────────────────────────────┘
│ │
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ User │ │ Order Service │
│ Service │ │ │
│ │ │ @FeignClient │ ─── 调用 → Product Service
│ │ │ Resilience4j │ ─── 熔断降级
└──────────────┘ └──────────────────┘
│ │
└─────────┬───────┘
│ 所有服务注册/发现
▼
┌─────────────────────┐
│ Nacos / Eureka │ ← 服务注册中心 + 配置中心
│ 注册表: │
│ user-service → [...] │
│ order-service → [...]│
└─────────────────────┘
分布式链路追踪:Micrometer + Zipkin / Jaeger
配置管理:Spring Cloud Config / Nacos Config
OpenFeign 声明式客户端
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
// 主启动类开启 Feign
@SpringBootApplication
@EnableFeignClients
public class OrderServiceApplication { ... }
// 定义 Feign 客户端接口
@FeignClient(
name = "product-service", // 注册中心的服务名
fallback = ProductClientFallback.class // 降级实现
)
public interface ProductClient {
@GetMapping("/products/{id}")
ProductDTO getProduct(@PathVariable Long id);
@PostMapping("/products/{id}/decrease-stock")
void decreaseStock(@PathVariable Long id,
@RequestBody StockDecreaseRequest req);
}
// 降级实现(熔断后返回默认数据)
@Component
public class ProductClientFallback implements ProductClient {
@Override
public ProductDTO getProduct(Long id) {
// 降级:返回默认商品信息
return ProductDTO.builder().id(id).name("商品暂时不可用").build();
}
@Override
public void decreaseStock(Long id, StockDecreaseRequest req) {
throw new ServiceUnavailableException("库存服务暂时不可用");
}
}
Resilience4j 熔断器配置
resilience4j:
circuitbreaker:
instances:
product-service: # 针对 product-service 的熔断配置
sliding-window-size: 10 # 滑动窗口大小(10次请求)
failure-rate-threshold: 50 # 失败率 ≥ 50% 时熔断
wait-duration-in-open-state: 10s # 断开状态等待 10s
permitted-number-of-calls-in-half-open-state: 3
automatic-transition-from-open-to-half-open-enabled: true
retry:
instances:
product-service:
max-attempts: 3
wait-duration: 500ms
retry-exceptions:
- java.net.ConnectException # 只重试连接异常
Spring Cloud Gateway 路由配置
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service # lb:// 使用负载均衡
predicates:
- Path=/api/users/**
filters:
- StripPrefix=1
- name: RequestRateLimiter # 限流过滤器
args:
redis-rate-limiter.replenishRate: 100 # 每秒 100 个令牌
redis-rate-limiter.burstCapacity: 200
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
filters:
- name: CircuitBreaker
args:
name: order-service-cb
fallbackUri: forward:/fallback/orders
Tip
微服务不是银弹。团队少于 5 人、业务处于探索期、服务间边界不清晰时,强行拆分微服务往往弊大于利。建议先用良好的模块化单体(Modular Monolith)积累业务理解,当某个模块真的需要独立扩缩容时再拆分。
Warning
微服务中的分布式事务是最大挑战。避免使用两阶段提交(2PC),优先考虑业务可接受的最终一致性方案:Saga 模式(将分布式事务拆解为一系列本地事务)或者借助 Seata AT 模式自动管理。
分布式链路追踪
微服务架构中,一次用户请求可能经过 5-10 个服务。当出现问题时,如何快速定位是哪个服务、哪个方法出了问题?分布式链路追踪提供了跨服务的全链路可见性:
Trace(链路)
一次完整的请求路径,从用户发起请求到收到响应的全过程。每个 Trace 有唯一的 Trace ID,该 ID 通过 HTTP Header(X-Trace-ID)在所有服务间传递,将分散在不同服务日志中的调用记录串联起来。
Span(跨度)
Trace 中的一个操作单元,表示一次具体的操作(HTTP 调用、数据库查询、Redis 操作等)。Span 包含起止时间、操作名称、标签(tags)和日志(logs),是链路追踪的最小单位。
Micrometer Tracing
Spring Boot 3.x 内置的观测性框架,替代了旧版 Spring Cloud Sleuth。通过添加
micrometer-tracing-bridge-otel 依赖,自动为所有 HTTP 请求、数据库操作注入 Trace/Span 信息,并可导出到 Zipkin、Jaeger、Grafana Tempo 等平台。<!-- pom.xml:引入 Micrometer Tracing + Zipkin 导出器 -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-exporter-zipkin</artifactId>
</dependency>
management:
tracing:
sampling:
probability: 1.0 # 100% 采样(生产环境建议 0.1 即 10%)
spring:
zipkin:
base-url: http://zipkin:9411
Nacos 服务注册与配置中心
在国内微服务项目中,Nacos 是最常用的注册中心和配置中心(替代 Eureka + Config Server 的组合):
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
# bootstrap.yml(在 application.yml 之前加载,用于配置中心)
spring:
application:
name: user-service
cloud:
nacos:
discovery:
server-addr: nacos:8848 # 注册到 Nacos
config:
server-addr: nacos:8848 # 从 Nacos 拉取配置
file-extension: yaml # 配置文件格式
namespace: production # 命名空间隔离环境
本章小结
微服务架构适合需要独立扩缩容或大型团队并行开发的场景,小团队建议先用模块化单体。Spring Cloud 核心组件:Gateway(API 网关/路由/限流/认证)、OpenFeign(声明式 HTTP 客户端)、Resilience4j(熔断/重试/限流)、Nacos(注册中心 + 配置中心)。分布式事务避免 2PC,优先最终一致性(Saga 模式)。Micrometer Tracing 提供全链路追踪,是微服务可观测性的基础。