文档
Spring Cloud 微服务架构设计指南
第一章:服务注册与发现
1.1 为什么需要注册中心?
在微服务架构中,服务实例动态变化(扩容、缩容、故障),需要一种机制让服务消费者自动发现可用的服务提供者。
[User Service 实例1] ──注册──→ [Eureka Server]
[User Service 实例2] ──注册──→ ↑
[Order Service] ──发现─────────┘
1.2 Eureka 核心配置
# Eureka Server
eureka:
server:
enable-self-preservation: false # 开发环境关闭自我保护
eviction-interval-timer-in-ms: 5000
# Eureka Client
eureka:
client:
registry-fetch-interval-seconds: 30 # 拉取注册表间隔
instance:
lease-renewal-interval-in-seconds: 10 # 心跳间隔
lease-expiration-duration-in-seconds: 30 # 过期时间
prefer-ip-address: true # 优先使用 IP 注册
第二章:API 网关设计
2.1 Gateway vs Zuul
| 特性 | Spring Cloud Gateway | Netflix Zuul |
|---|---|---|
| 底层 | WebFlux (Netty) | Servlet (Tomcat) |
| 性能 | 非阻塞、高并发 | 阻塞式,性能较低 |
| 维护状态 | 活跃 | 进入维护模式 |
| 推荐 | ✅ 新项目首选 | ❌ 遗留项目 |
2.2 Gateway 路由与过滤器
spring:
cloud:
gateway:
routes:
- id: custom-route
uri: lb://target-service
predicates:
- Path=/api/v1/**
- Header=X-API-Version, 2
- Method=GET,POST
filters:
- AddRequestHeader=X-Gateway, true
- name: CircuitBreaker
args:
name: fallbackCmd
fallbackUri: forward:/fallback
2.3 全局过滤器
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getHeaders()
.getFirst("Authorization");
if (token == null) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1; // 高优先级
}
}
第三章:声明式 HTTP 调用
3.1 Feign 最佳实践
@FeignClient(name = "user-service", configuration = FeignConfig.class)
public interface UserClient {
@GetMapping("/users/{id}")
UserDto getUser(@PathVariable Long id);
@PostMapping("/users")
UserDto create(@RequestBody CreateUserRequest request);
@GetMapping("/users")
Page<UserDto> list(@SpringQueryMap UserQuery query);
}
// 统一配置
@Configuration
public class FeignConfig {
@Bean
public RequestInterceptor authInterceptor() {
return requestTemplate -> {
requestTemplate.header("Authorization",
"Bearer " + getCurrentToken());
};
}
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL; // 完整日志
}
}
第四章:熔断与降级
4.1 Resilience4j 三种模式
// 1. 熔断器 (Circuit Breaker)
@CircuitBreaker(name = "userService", fallbackMethod = "fallback")
public UserDto getUser(Long id) { ... }
public UserDto fallback(Long id, Throwable t) {
return new UserDto(id, "Default", "N/A");
}
// 2. 重试 (Retry)
@Retry(name = "userService", fallbackMethod = "fallback")
public UserDto getUserWithRetry(Long id) { ... }
// 3. 限流 (Rate Limiter)
@RateLimiter(name = "userService")
public UserDto getUserWithRateLimit(Long id) { ... }
// 4. 组合使用
@Bulkhead(name = "userService") // 隔仓
@CircuitBreaker(name = "userService")
@Retry(name = "userService")
public UserDto getUserWithFullProtection(Long id) { ... }
4.2 配置示例
resilience4j:
circuitbreaker:
instances:
userService:
sliding-window-size: 10 # 滑动窗口大小
minimum-number-of-calls: 5 # 最小调用次数
failure-rate-threshold: 50 # 失败率阈值(%)
wait-duration-in-open-state: 30s
permitted-number-of-calls-in-half-open-state: 3
retry:
instances:
userService:
max-attempts: 3
wait-duration: 500ms
retry-exceptions:
- java.net.ConnectException
第五章:配置中心
5.1 Config Server + Bus 动态刷新
# Config Server
spring:
cloud:
config:
server:
git:
uri: https://github.com/myorg/config-repo
search-paths: '{application}'
// 客户端使用 @RefreshScope
@RestController
@RefreshScope // 配置变化时自动刷新
public class ConfigController {
@Value("${app.message}")
private String message;
@GetMapping("/message")
public String getMessage() {
return message;
}
}
# 触发批量刷新
curl -X POST http://localhost:8080/actuator/busrefresh
思考题
- 服务注册中心 CAP 权衡:Eureka(AP)vs Consul(CP)vs Nacos(AP+CP)如何选择?
- Gateway 中如何实现基于请求体的路由?
- Feign 底层如何实现负载均衡?
- 分布式事务在微服务中有哪些解决方案?