微服务架构设计指南

知识库
知识库文档
/tech-stacks/spring-cloud/tutorial/微服务架构设计指南.md

文档

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

思考题

  1. 服务注册中心 CAP 权衡:Eureka(AP)vs Consul(CP)vs Nacos(AP+CP)如何选择?
  2. Gateway 中如何实现基于请求体的路由?
  3. Feign 底层如何实现负载均衡?
  4. 分布式事务在微服务中有哪些解决方案?

信息

路径
/tech-stacks/spring-cloud/tutorial/微服务架构设计指南.md
更新时间
2026/5/30