簡介
微服務架構將應用程式劃分為小型的、獨立的服務。 Spring Cloud 提供了完整的工具:服務發現、API 閘道、斷路器、設定伺服器來建置生產就緒的微服務系統。
1. 微服務架構概述
┌──────────────┐
│ Client │
└──────┬───────┘
│
┌──────▼───────┐
│ API Gateway │
│(Spring Cloud)│
└──────┬───────┘
│
┌────────────────┼────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ Order │ │ Product │ │ User │
│ Service │ │ Service │ │ Service │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│Order DB │ │Product │ │User DB │
│(Postgres)│ │DB(Mongo)│ │(Postgres)│
└─────────┘ └─────────┘ └─────────┘
2. 使用 Consul 進行服務發現
2.1 設定 Consul (Docker)
# docker-compose.yml
services:
consul:
image: hashicorp/consul:1.20
ports:
- "8500:8500"
command: agent -server -bootstrap-expect=1 -ui -client=0.0.0.0
2.2 Spring Boot服務註冊
// build.gradle.kts
implementation("org.springframework.cloud:spring-cloud-starter-consul-discovery")
# application.yml (Product Service)
spring:
application:
name: product-service
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name: ${spring.application.name}
health-check-interval: 10s
instance-id: ${spring.application.name}:${random.value}
2.3 服務到服務通信
@Configuration
public class RestClientConfig {
@Bean
@LoadBalanced
public RestClient.Builder restClientBuilder() {
return RestClient.builder();
}
}
@Service
public class OrderService {
private final RestClient restClient;
public OrderService(RestClient.Builder builder) {
this.restClient = builder
.baseUrl("http://product-service") // Tên service, không phải IP
.build();
}
public ProductResponse getProduct(Long productId) {
return restClient.get()
.uri("/api/v1/products/{id}", productId)
.retrieve()
.body(ProductResponse.class);
}
}
3. API 閘道與 Spring Cloud Gateway
3.1 設定網關
// build.gradle.kts (Gateway Service)
implementation("org.springframework.cloud:spring-cloud-starter-gateway")
implementation("org.springframework.cloud:spring-cloud-starter-consul-discovery")
3.2 路由配置
# application.yml
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: product-service
uri: lb://product-service
predicates:
- Path=/api/v1/products/**
filters:
- StripPrefix=0
- name: CircuitBreaker
args:
name: productCircuitBreaker
fallbackUri: forward:/fallback/products
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/v1/orders/**
filters:
- StripPrefix=0
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/v1/users/**
3.3 全域過濾器
@Component
public class LoggingFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String requestId = UUID.randomUUID().toString();
exchange.getRequest().mutate()
.header("X-Request-Id", requestId);
log.info("Request: {} {} [{}]",
exchange.getRequest().getMethod(),
exchange.getRequest().getPath(),
requestId);
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
4.具有 Resilience4j 的斷路器
4.1 設置
// build.gradle.kts
implementation("org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j")
4.2 配置
resilience4j:
circuitbreaker:
instances:
productService:
sliding-window-size: 10
failure-rate-threshold: 50
wait-duration-in-open-state: 10s
permitted-number-of-calls-in-half-open-state: 3
slow-call-duration-threshold: 2s
slow-call-rate-threshold: 80
retry:
instances:
productService:
max-attempts: 3
wait-duration: 1s
exponential-backoff-multiplier: 2
timelimiter:
instances:
productService:
timeout-duration: 3s
4.3 在程式碼中使用
@Service
public class OrderService {
private final RestClient restClient;
private final CircuitBreakerFactory circuitBreakerFactory;
@CircuitBreaker(name = "productService", fallbackMethod = "getProductFallback")
@Retry(name = "productService")
public ProductResponse getProduct(Long productId) {
return restClient.get()
.uri("/api/v1/products/{id}", productId)
.retrieve()
.body(ProductResponse.class);
}
// Fallback khi circuit open hoặc service down
private ProductResponse getProductFallback(Long productId, Throwable t) {
log.warn("Fallback for product {}: {}", productId, t.getMessage());
return new ProductResponse(productId, "Unknown Product",
BigDecimal.ZERO, "N/A");
}
}
4.4 斷路器狀態
┌─────────┐ Failure rate > threshold ┌──────────┐
│ CLOSED │ ──────────────────────────► │ OPEN │
│(normal) │ │(blocking)│
└────▲────┘ └────┬─────┘
│ │
│ Success rate OK Wait timeout │
│ │
┌────┴──────────┐ │
│ HALF-OPEN │ ◄──────────────────────────┘
│(testing) │
└───────────────┘
5.集中配置
5.1 Spring Cloud 設定伺服器
# Config Server application.yml
spring:
cloud:
config:
server:
git:
uri: https://github.com/myorg/config-repo
default-label: main
5.2 客戶端配置
# bootstrap.yml (Client Service)
spring:
application:
name: product-service
config:
import: optional:configserver:http://localhost:8888
總結
- 微服務架構:每個服務都是獨立的,有自己的資料庫,透過REST/gRPC進行通信
- 服務發現(Consul):自動註冊/發現服務,使用@LoadBalanced進行負載平衡
- API閘道:單一入口點、路由、過濾、斷路器集成
- Resilience4j Circuit Breaker:透過回退保護服務免受級聯故障的影響
練習
- 使用 Consul 服務發現建構 3 個微服務(訂單、產品、使用者)。擴展服務時測試負載平衡 2.設定Spring Cloud Gateway:路由到3個服務,全域日誌過濾器,速率限制
- 為訂單→產品通訊實施斷路器:產品服務中斷時測試回退