核心概念 #
一、分布式系统基础理论 #
1.1 CAP理论 #
CAP理论指出,分布式系统不可能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition Tolerance)三个特性,最多只能同时满足两个。
text
┌───────────────┐
│ CAP │
│ 理论三角 │
└───────┬───────┘
/|\
/ | \
/ | \
/ | \
/ | \
C A P
一致性 可用性 分区容错性
| 特性 | 说明 |
|---|---|
| 一致性 © | 所有节点在同一时间看到的数据是一致的 |
| 可用性 (A) | 每个请求都能在合理时间内得到响应 |
| 分区容错性 (P) | 系统在网络分区发生时仍能继续运行 |
CAP选择策略:
| 组合 | 说明 | 典型系统 |
|---|---|---|
| CP | 一致性 + 分区容错 | ZooKeeper、Redis |
| AP | 可用性 + 分区容错 | Eureka、Cassandra |
| CA | 一致性 + 可用性 | 单机数据库 |
1.2 BASE理论 #
BASE理论是对CAP理论的补充,强调通过牺牲强一致性来获得高可用性。
| 特性 | 说明 |
|---|---|
| Basically Available | 基本可用,允许损失部分可用性 |
| Soft State | 软状态,允许中间状态存在 |
| Eventually Consistent | 最终一致性,一段时间后达到一致 |
1.3 微服务设计原则 #
| 原则 | 说明 |
|---|---|
| 单一职责 | 每个服务只做一件事 |
| 服务自治 | 服务独立开发、部署、扩展 |
| 接口标准化 | 使用标准协议通信 |
| 去中心化 | 避免单点故障 |
二、服务注册与发现 #
2.1 为什么需要服务注册发现 #
在微服务架构中,服务实例数量和地址是动态变化的:
text
传统方式:
┌─────────┐ 硬编码IP ┌─────────┐
│ 服务A │ ──────────────────►│ 服务B │
└─────────┘ 192.168.1.100 └─────────┘
问题:IP变化需要修改代码
服务发现方式:
┌─────────┐ 查询服务 ┌─────────┐
│ 服务A │ ──────────────────►│ 注册中心 │
└─────────┘ └────┬────┘
│ │
│ 获取服务列表 │
│◄─────────────────────────────┘
│
│ 调用服务实例
▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 实例B-1 │ │ 实例B-2 │ │ 实例B-3 │
└─────────┘ └─────────┘ └─────────┘
2.2 服务注册发现流程 #
text
┌────────────────────────────────────────────────────────────┐
│ 服务注册发现流程 │
├────────────────────────────────────────────────────────────┤
│ │
│ 1. 服务启动 │
│ │ │
│ ▼ │
│ 2. 向注册中心发送注册请求 │
│ │ │
│ ▼ │
│ 3. 注册中心保存服务信息 │
│ │ │
│ ▼ │
│ 4. 服务定时发送心跳(续约) │
│ │ │
│ ▼ │
│ 5. 消费者从注册中心获取服务列表 │
│ │ │
│ ▼ │
│ 6. 消费者根据负载均衡策略选择实例调用 │
│ │
└────────────────────────────────────────────────────────────┘
2.3 注册中心对比 #
| 特性 | Eureka | Nacos | Consul | ZooKeeper |
|---|---|---|---|---|
| CAP | AP | AP/CP | CP | CP |
| 一致性 | 弱一致 | 最终一致 | 强一致 | 强一致 |
| 健康检查 | 心跳 | 心跳/TCP/HTTP | TCP/HTTP | 心跳 |
| 配置中心 | ❌ | ✅ | ✅ | ❌ |
| 雪崩保护 | ✅ | ✅ | ❌ | ❌ |
| 社区活跃 | 维护模式 | 活跃 | 活跃 | 活跃 |
2.4 Eureka核心概念 #
text
┌─────────────────────────────────────────────────────────────┐
│ Eureka架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Eureka Server │◄───────►│ Eureka Server │ │
│ │ (节点A) │ 复制 │ (节点B) │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ ┌──────┴──────┐ ┌──────┴──────┐ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ 服务实例 │ │ 服务实例 │ │ 服务实例 │ │ 服务实例 │ │
│ │ Provider│ │ Consumer│ │ Provider│ │ Consumer│ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
核心组件:
| 组件 | 说明 |
|---|---|
| Application Service | 服务提供者 |
| Application Client | 服务消费者 |
| Eureka Server | 注册中心服务器 |
| Service Registry | 服务注册表 |
| Renew | 心跳续约 |
| Cancel | 服务下线 |
| Eviction | 服务剔除 |
三、负载均衡 #
3.1 负载均衡概念 #
负载均衡是将请求分发到多个服务实例的机制,提高系统吞吐量和可用性。
text
┌─────────────┐
│ 客户端 │
└──────┬──────┘
│
▼
┌────────────────────────┐
│ 负载均衡器 │
│ Round Robin / Random │
└────────────┬───────────┘
│
┌──────────────────┼──────────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 实例 1 │ │ 实例 2 │ │ 实例 3 │
│ 30% │ │ 40% │ │ 30% │
└─────────┘ └─────────┘ └─────────┘
3.2 负载均衡分类 #
| 类型 | 说明 | 典型实现 |
|---|---|---|
| 服务端负载均衡 | 独立的负载均衡服务器 | Nginx、F5 |
| 客户端负载均衡 | 客户端内置负载均衡 | Ribbon、LoadBalancer |
3.3 负载均衡策略 #
| 策略 | 说明 | 适用场景 |
|---|---|---|
| 轮询 | 按顺序分发 | 服务实例性能相近 |
| 随机 | 随机选择 | 服务实例性能相近 |
| 加权轮询 | 按权重分发 | 服务实例性能不同 |
| 最少连接 | 选择连接最少的实例 | 长连接场景 |
| 一致性哈希 | 相同请求路由到相同实例 | 有状态服务 |
| 响应时间加权 | 响应时间越短权重越高 | 对响应时间敏感 |
3.4 Spring Cloud LoadBalancer #
java
@Configuration
public class LoadBalancerConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(
Environment environment,
LoadBalancerClientFactory factory) {
String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME);
return new RandomLoadBalancer(
factory.getLazyProvider(name, ServiceInstanceListSupplier.class),
name
);
}
}
四、服务调用 #
4.1 服务调用方式 #
text
┌─────────────────────────────────────────────────────────────┐
│ 服务调用方式对比 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. RestTemplate(传统方式) │
│ String result = restTemplate.getForObject( │
│ "http://service-provider/hello", String.class); │
│ │
│ 2. OpenFeign(声明式) │
│ @FeignClient("service-provider") │
│ interface ProviderClient { │
│ @GetMapping("/hello") │
│ String hello(); │
│ } │
│ │
│ 3. WebClient(响应式) │
│ webClient.get() │
│ .uri("/hello") │
│ .retrieve() │
│ .bodyToMono(String.class); │
│ │
└─────────────────────────────────────────────────────────────┘
4.2 OpenFeign核心概念 #
java
// 1. 定义Feign客户端
@FeignClient(
name = "service-provider",
path = "/api",
fallback = ProviderFallback.class
)
public interface ProviderClient {
@GetMapping("/users/{id}")
User getUser(@PathVariable("id") Long id);
@PostMapping("/users")
User createUser(@RequestBody User user);
}
// 2. 降级处理
@Component
public class ProviderFallback implements ProviderClient {
@Override
public User getUser(Long id) {
return new User(-1L, "默认用户");
}
@Override
public User createUser(User user) {
return null;
}
}
// 3. 使用
@Service
public class UserService {
@Autowired
private ProviderClient providerClient;
public User getUser(Long id) {
return providerClient.getUser(id);
}
}
4.3 服务调用流程 #
text
┌─────────┐ 1. 发起调用 ┌─────────────┐
│ 消费者 │ ─────────────────►│ Feign Client │
└─────────┘ └──────┬──────┘
│
2. 解析服务名
│
▼
┌─────────────┐
│ 注册中心 │
│ (Eureka) │
└──────┬──────┘
│
3. 返回服务列表
│
▼
┌─────────────┐
│ LoadBalancer │
│ 选择实例 │
└──────┬──────┘
│
4. 发送HTTP请求
│
▼
┌─────────────┐
│ 服务提供者 │
└─────────────┘
五、服务容错 #
5.1 为什么需要服务容错 #
微服务架构中,服务间存在依赖关系,一个服务故障可能导致级联故障:
text
正常情况:
A ──► B ──► C ──► D
✓ ✓ ✓ ✓
故障传播:
A ──► B ──► C ──► D
✓ ✓ ✗ ✗
│
└──► C故障导致B超时
B超时导致A超时
整个链路崩溃(雪崩效应)
5.2 服务容错模式 #
| 模式 | 说明 | 实现方式 |
|---|---|---|
| 熔断 | 故障达到阈值时快速失败 | Circuit Breaker |
| 降级 | 提供备选响应 | Fallback |
| 限流 | 限制请求速率 | Rate Limiter |
| 隔离 | 隔离故障服务 | Bulkhead |
| 超时 | 设置请求超时时间 | Timeout |
5.3 熔断器状态机 #
text
熔断器状态机
┌──────────────────────────────┐
│ │
▼ │
┌─────────┐ 失败率<阈值 ┌─────────┐
│ 关闭 │ ◄────────────────│ 半开 │
│ Closed │ │ Half-Open│
└────┬────┘ └────┬────┘
│ │
│ 失败率>阈值 │ 成功
│ │
▼ │
┌─────────┐ 超时后尝试 ──────┘
│ 打开 │ ─────────────────►
│ Open │
└─────────┘
关闭:正常状态,请求正常通过
打开:熔断状态,请求直接失败
半开:尝试状态,允许部分请求通过测试
5.4 Resilience4j配置 #
yaml
resilience4j:
circuitbreaker:
configs:
default:
slidingWindowSize: 10
failureRateThreshold: 50
waitDurationInOpenState: 10s
permittedNumberOfCallsInHalfOpenState: 3
instances:
serviceA:
baseConfig: default
ratelimiter:
configs:
default:
limitForPeriod: 10
limitRefreshPeriod: 1s
timeoutDuration: 0
instances:
serviceA:
baseConfig: default
六、API网关 #
6.1 网关的作用 #
text
没有网关:
客户端 ──► 服务A (认证、限流、日志...)
客户端 ──► 服务B (认证、限流、日志...)
客户端 ──► 服务C (认证、限流、日志...)
问题:每个服务都要处理公共逻辑
使用网关:
客户端 ──► API网关 ──► 服务A
──► 服务B
──► 服务C
优势:统一处理认证、限流、日志等
6.2 网关核心功能 #
| 功能 | 说明 |
|---|---|
| 路由 | 请求转发到目标服务 |
| 过滤 | 请求/响应过滤处理 |
| 限流 | 保护后端服务 |
| 熔断 | 服务故障时快速失败 |
| 认证 | 统一身份认证 |
| 日志 | 统一日志记录 |
| 监控 | 统一监控指标 |
6.3 Spring Cloud Gateway架构 #
text
┌─────────────────────────────────────────────────────────────┐
│ Spring Cloud Gateway │
├─────────────────────────────────────────────────────────────┤
│ │
│ 客户端请求 │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Handler Mapping │ │
│ │ (路由匹配) │ │
│ └───────────────────────────┬───────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ Web Handler │ │
│ └───────────────────────────┬───────────────────────────┘ │
│ │ │
│ ┌───────────────────────────┼───────────────────────────┐ │
│ │ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Filter │─►│ Filter │─►│ Filter │─►│ Filter │ │ │
│ │ │ 前置 │ │ 前置 │ │ 后置 │ │ 后置 │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │ │
│ │ │ │ │
│ │ Filter Chain │ │
│ └───────────────────────────┼───────────────────────────┘ │
│ │ │
│ ▼ │
│ 目标微服务 │
│ │
└─────────────────────────────────────────────────────────────┘
七、配置中心 #
7.1 配置中心的作用 #
text
传统配置管理:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 服务实例 │ │ 服务实例 │ │ 服务实例 │
│ 配置文件 │ │ 配置文件 │ │ 配置文件 │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└────────────┼────────────┘
│
需要逐个修改
配置中心管理:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ 服务实例 │ │ 服务实例 │ │ 服务实例 │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└────────────┼────────────┘
│
▼
┌─────────────┐
│ 配置中心 │
│ Config Server│
└─────────────┘
│
统一管理、动态刷新
7.2 配置中心功能 #
| 功能 | 说明 |
|---|---|
| 配置存储 | 集中存储配置信息 |
| 版本管理 | 配置变更历史 |
| 动态刷新 | 运行时更新配置 |
| 环境隔离 | 开发/测试/生产环境配置 |
| 权限控制 | 配置访问权限管理 |
八、链路追踪 #
8.1 为什么需要链路追踪 #
微服务架构中,一个请求可能经过多个服务,排查问题困难:
text
请求链路:
客户端 ──► 网关 ──► 服务A ──► 服务B ──► 服务C
│
└──► 服务D
问题:服务C响应慢,是哪个服务导致的?
8.2 链路追踪核心概念 #
| 概念 | 说明 |
|---|---|
| Trace | 一次完整请求的链路,包含多个Span |
| Span | 一个服务处理过程 |
| Annotation | Span中的事件标记 |
| TraceId | 全局唯一链路ID |
| SpanId | 当前Span唯一ID |
| ParentSpanId | 父Span的ID |
8.3 链路追踪示例 #
text
Trace: 1234567890
│
├── Span: gateway (SpanId: a1, ParentSpanId: null)
│ └── cs: client send
│ └── sr: server receive
│ │
│ ├── Span: service-a (SpanId: a2, ParentSpanId: a1)
│ │ └── cs: client send
│ │ └── sr: server receive
│ │ │
│ │ ├── Span: service-b (SpanId: a3, ParentSpanId: a2)
│ │ │ └── cs, sr, ss, cr
│ │ │
│ │ └── Span: service-c (SpanId: a4, ParentSpanId: a2)
│ │ └── cs, sr, ss, cr
│ │
│ └── ss: server send
│ └── cr: client receive
九、总结 #
9.1 核心概念总结 #
| 概念 | 说明 | 核心组件 |
|---|---|---|
| 服务注册发现 | 服务自动注册与发现 | Eureka、Nacos、Consul |
| 负载均衡 | 请求分发策略 | LoadBalancer |
| 服务调用 | 服务间通信 | OpenFeign、RestTemplate |
| 服务容错 | 故障处理机制 | Resilience4j、Sentinel |
| API网关 | 统一入口 | Spring Cloud Gateway |
| 配置中心 | 配置集中管理 | Config、Nacos |
| 链路追踪 | 请求链路追踪 | Sleuth、Zipkin |
9.2 下一步 #
现在你已经掌握了Spring Cloud的核心概念,接下来让我们深入学习 服务注册与发现,从Eureka服务端开始!
最后更新:2026-03-28