微服务架构深度实践¶
文档定位:落地实践指南 — 聚焦分布式事务、服务网格、云原生部署、可观测性等高级实践。
前置阅读:各核心组件的工作原理和配置方式请先参阅 → Spring Cloud 核心组件(Eureka / Gateway / Feign / Sentinel)
概述¶
本文深度探讨微服务架构的高级实践,包括分布式事务、服务网格、云原生部署等。
graph TB
A[微服务架构] --> B[服务治理]
A --> C[数据一致性]
A --> D[可观测性]
A --> E[安全与认证]
B --> B1[服务注册发现]
B --> B2[配置管理]
B --> B3[流量控制]
C --> C1[分布式事务]
C --> C2[事件驱动]
C --> C3[数据同步]
D --> D1[链路追踪]
D --> D2[指标监控]
D --> D3[日志聚合]
E --> E1[认证授权]
E --> E2[API 网关]
E --> E3[服务间安全] 分布式事务深度解析¶
分布式事务挑战¶
关于 CAP 理论与 BASE 理论的详细说明,请参阅 → CAP 理论与 BASE 理论
分布式事务模式¶
1. 两阶段提交(2PC)¶
// 协调者接口
public interface TransactionCoordinator {
@PostMapping("/prepare")
ResponseEntity<String> prepare(@RequestBody PrepareRequest request);
@PostMapping("/commit")
ResponseEntity<String> commit(@RequestBody CommitRequest request);
@PostMapping("/rollback")
ResponseEntity<String> rollback(@RequestBody RollbackRequest request);
}
// 参与者服务
@Service
public class OrderService implements TransactionParticipant {
@Transactional
public boolean prepare(Long orderId, BigDecimal amount) {
// 预扣库存、冻结资金等
Order order = orderRepository.findById(orderId).orElseThrow();
if (order.getStatus() != OrderStatus.PENDING) {
return false;
}
order.setStatus(OrderStatus.PREPARED);
orderRepository.save(order);
return true;
}
@Transactional
public void commit(Long orderId) {
Order order = orderRepository.findById(orderId).orElseThrow();
order.setStatus(OrderStatus.COMPLETED);
orderRepository.save(order);
}
@Transactional
public void rollback(Long orderId) {
Order order = orderRepository.findById(orderId).orElseThrow();
order.setStatus(OrderStatus.CANCELLED);
orderRepository.save(order);
}
}
2. TCC(Try-Confirm-Cancel)模式¶
// TCC 服务接口
public interface TccOrderService {
@PostMapping("/try")
ResponseEntity<TryResult> tryCreateOrder(@RequestBody OrderRequest request);
@PostMapping("/confirm")
ResponseEntity<String> confirmOrder(@RequestParam String txId);
@PostMapping("/cancel")
ResponseEntity<String> cancelOrder(@RequestParam String txId);
}
// TCC 实现
@Service
public class TccOrderServiceImpl implements TccOrderService {
@Override
@Transactional
public TryResult tryCreateOrder(OrderRequest request) {
// Try 阶段:资源预留
String txId = UUID.randomUUID().toString();
// 预扣库存
inventoryService.prepareDeduct(request.getProductId(), request.getQuantity(), txId);
// 冻结资金
accountService.prepareFreeze(request.getUserId(), request.getAmount(), txId);
// 创建订单(待确认状态)
Order order = new Order();
order.setTxId(txId);
order.setStatus(OrderStatus.TRY_SUCCESS);
orderRepository.save(order);
return new TryResult(txId, true, "Try success");
}
@Override
@Transactional
public String confirmOrder(String txId) {
// Confirm 阶段:确认操作
Order order = orderRepository.findByTxId(txId)
.orElseThrow(() -> new RuntimeException("Order not found"));
// 确认扣减库存
inventoryService.confirmDeduct(txId);
// 确认扣款
accountService.confirmDeduct(txId);
// 更新订单状态
order.setStatus(OrderStatus.CONFIRMED);
orderRepository.save(order);
return "Confirm success";
}
@Override
@Transactional
public String cancelOrder(String txId) {
// Cancel 阶段:取消操作
Order order = orderRepository.findByTxId(txId)
.orElseThrow(() -> new RuntimeException("Order not found"));
// 回滚库存
inventoryService.cancelDeduct(txId);
// 解冻资金
accountService.cancelFreeze(txId);
// 更新订单状态
order.setStatus(OrderStatus.CANCELLED);
orderRepository.save(order);
return "Cancel success";
}
}
3. Saga 模式¶
// Saga 协调器
@Component
public class OrderSagaCoordinator {
private final Map<String, SagaExecution> executions = new ConcurrentHashMap<>();
public SagaResult executeOrderSaga(OrderRequest request) {
String sagaId = UUID.randomUUID().toString();
SagaExecution execution = new SagaExecution(sagaId);
executions.put(sagaId, execution);
try {
// 步骤1:创建订单
execution.addStep("createOrder", () -> orderService.createOrder(request));
// 步骤2:扣减库存
execution.addStep("deductInventory",
() -> inventoryService.deduct(request.getProductId(), request.getQuantity()),
() -> inventoryService.compensateDeduct(request.getProductId(), request.getQuantity())
);
// 步骤3:扣款
execution.addStep("deductAccount",
() -> accountService.deduct(request.getUserId(), request.getAmount()),
() -> accountService.compensateDeduct(request.getUserId(), request.getAmount())
);
// 执行 Saga
return execution.execute();
} catch (Exception e) {
// 执行补偿操作
execution.compensate();
return SagaResult.failed(sagaId, e.getMessage());
}
}
}
// Saga 步骤定义
public class SagaStep {
private final String name;
private final Supplier<Boolean> action;
private final Runnable compensation;
public SagaStep(String name, Supplier<Boolean> action, Runnable compensation) {
this.name = name;
this.action = action;
this.compensation = compensation;
}
public boolean execute() {
return action.get();
}
public void compensate() {
if (compensation != null) {
compensation.run();
}
}
}
Seata 分布式事务框架¶
Seata AT 模式配置¶
# application.yml
seata:
enabled: true
application-id: order-service
tx-service-group: my_tx_group
service:
vgroup-mapping:
my_tx_group: default
grouplist:
default: 127.0.0.1:8091
config:
type: nacos
nacos:
server-addr: 127.0.0.1:8848
namespace: ""
group: SEATA_GROUP
registry:
type: nacos
nacos:
application: seata-server
server-addr: 127.0.0.1:8848
namespace: ""
group: SEATA_GROUP
Seata 使用示例¶
@Service
public class OrderService {
@GlobalTransactional(timeoutMills = 300000, name = "create-order")
public Order createOrder(OrderRequest request) {
// 1. 创建订单
Order order = new Order();
order.setUserId(request.getUserId());
order.setAmount(request.getAmount());
orderRepository.save(order);
// 2. 扣减库存(远程调用)
inventoryFeignClient.deduct(request.getProductId(), request.getQuantity());
// 3. 扣款(远程调用)
accountFeignClient.deduct(request.getUserId(), request.getAmount());
return order;
}
}
// Feign 客户端配置
@FeignClient(name = "inventory-service", configuration = FeignConfig.class)
public interface InventoryFeignClient {
@PostMapping("/inventory/deduct")
ResponseEntity<String> deduct(@RequestParam Long productId, @RequestParam Integer quantity);
}
// Feign 配置支持 Seata
@Configuration
public class FeignConfig {
@Bean
public RequestInterceptor seataFeignInterceptor() {
return template -> {
String xid = RootContext.getXID();
if (StringUtils.isNotBlank(xid)) {
template.header(RootContext.KEY_XID, xid);
}
};
}
}
服务网格(Service Mesh)集成¶
Istio 与 Spring Cloud 集成¶
Sidecar 自动注入¶
# Kubernetes 部署配置
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
labels:
app: order-service
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
annotations:
sidecar.istio.io/inject: "true" # 启用 Sidecar 注入
spec:
containers:
- name: order-service
image: registry.example.com/order-service:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "kubernetes"
---
apiVersion: v1
kind: Service
metadata:
name: order-service
labels:
app: order-service
spec:
ports:
- port: 80
targetPort: 8080
name: http
selector:
app: order-service
Istio 流量管理¶
# VirtualService 配置
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: order-service
spec:
hosts:
- order-service
- order-service.example.com
http:
- match:
- headers:
user-type:
exact: vip
route:
- destination:
host: order-service
subset: v1 # VIP 用户路由到 v1 版本
- route:
- destination:
host: order-service
subset: v2 # 普通用户路由到 v2 版本
weight: 80
- destination:
host: order-service
subset: v1
weight: 20
---
# DestinationRule 配置
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: order-service
spec:
host: order-service
subsets:
- name: v1
labels:
version: v1.0.0
- name: v2
labels:
version: v2.0.0
Spring Cloud 与 Istio 协同¶
@Configuration
public class IstioIntegrationConfig {
// 使用 Istio 的服务发现
@Bean
@ConditionalOnProperty(name = "istio.enabled", havingValue = "true")
public ServiceInstanceListSupplier istioServiceInstanceListSupplier(
ConfigurableApplicationContext context) {
return ServiceInstanceListSupplier.builder()
.withBlockingDiscoveryClient()
.withCaching()
.withHealthChecks()
.build(context);
}
// 集成 Istio 链路追踪
@Bean
public TracingCustomizer istioTracingCustomizer() {
return builder -> {
builder.sampler(Sampler.ALWAYS_SAMPLE);
builder.propagationFactory(B3Propagation.FACTORY);
};
}
}
// 使用 Istio 的熔断器
@Configuration
public class CircuitBreakerConfig {
@Bean
public Customizer<Resilience4JCircuitBreakerFactory> defaultCustomizer() {
return factory -> factory.configureDefault(id -> {
return Resilience4JConfigBuilder.of(id)
.circuitBreakerConfig(CircuitBreakerConfig.custom()
.slidingWindowSize(100)
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofSeconds(60))
.build())
.timeLimiterConfig(TimeLimiterConfig.custom()
.timeoutDuration(Duration.ofSeconds(5))
.build())
.build();
});
}
}
云原生部署实践¶
Kubernetes 部署配置¶
完整的部署清单¶
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
labels:
app: order-service
version: v1.0.0
spec:
replicas: 3
selector:
matchLabels:
app: order-service
template:
metadata:
labels:
app: order-service
version: v1.0.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
prometheus.io/path: "/actuator/prometheus"
spec:
containers:
- name: order-service
image: registry.example.com/order-service:latest
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "kubernetes"
- name: JAVA_OPTS
value: "-Xmx512m -Xms256m -XX:+UseG1GC"
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
initialDelaySeconds: 30
periodSeconds: 5
---
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: order-service
labels:
app: order-service
spec:
ports:
- port: 80
targetPort: 8080
name: http
selector:
app: order-service
---
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: order-service
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
tls:
- hosts:
- orders.example.com
secretName: tls-secret
rules:
- host: orders.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: order-service
port:
number: 80
ConfigMap 配置管理¶
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: order-service-config
data:
application.yml: |
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://mysql-service:3306/order_db
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
cloud:
kubernetes:
config:
enabled: true
discovery:
enabled: true
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
endpoint:
health:
show-details: always
Secret 敏感信息管理¶
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: order-service-secret
type: Opaque
data:
DB_USERNAME: dXNlcm5hbWU= # username
DB_PASSWORD: cGFzc3dvcmQ= # password
JWT_SECRET: c2VjcmV0a2V5 # secretkey
健康检查与自愈¶
Spring Boot Actuator 配置¶
management:
endpoint:
health:
enabled: true
show-details: always
show-components: always
group:
liveness:
include: livenessState,diskSpace
readiness:
include: readinessState,ping,db
health:
livenessstate:
enabled: true
readinessstate:
enabled: true
diskspace:
enabled: true
自定义健康检查¶
@Component
public class DatabaseHealthIndicator implements HealthIndicator {
private final DataSource dataSource;
public DatabaseHealthIndicator(DataSource dataSource) {
this.dataSource = dataSource;
}
@Override
public Health health() {
try (Connection connection = dataSource.getConnection()) {
if (connection.isValid(5)) {
return Health.up()
.withDetail("database", "Connected")
.build();
} else {
return Health.down()
.withDetail("database", "Connection invalid")
.build();
}
} catch (SQLException e) {
return Health.down(e).build();
}
}
}
@Component
public class LivenessHealthIndicator implements HealthIndicator {
@Override
public Health health() {
// 检查应用是否存活的基本指标
long usedMemory = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
long maxMemory = Runtime.getRuntime().maxMemory();
double memoryUsage = (double) usedMemory / maxMemory;
if (memoryUsage > 0.9) {
return Health.down()
.withDetail("memory", "High memory usage: " + memoryUsage)
.build();
}
return Health.up()
.withDetail("memory", "Usage: " + memoryUsage)
.build();
}
}
可观测性实践¶
分布式链路追踪¶
Spring Cloud Sleuth + Zipkin¶
# application.yml
spring:
zipkin:
base-url: http://zipkin:9411
enabled: true
sleuth:
sampler:
probability: 1.0
web:
enabled: true
自定义追踪¶
@Service
public class OrderService {
private final Tracer tracer;
public OrderService(Tracer tracer) {
this.tracer = tracer;
}
public Order createOrder(OrderRequest request) {
// 创建自定义 Span
Span orderSpan = tracer.nextSpan().name("create-order").start();
try (Tracer.SpanInScope ws = tracer.withSpanInScope(orderSpan)) {
orderSpan.tag("order.amount", request.getAmount().toString());
orderSpan.tag("order.userId", request.getUserId().toString());
// 业务逻辑
Order order = processOrder(request);
orderSpan.event("order.created");
return order;
} catch (Exception e) {
orderSpan.tag("error", "true");
orderSpan.tag("error.message", e.getMessage());
throw e;
} finally {
orderSpan.finish();
}
}
}
指标监控¶
Micrometer 指标收集¶
@Component
public class OrderMetrics {
private final MeterRegistry meterRegistry;
private final Counter orderCounter;
private final Timer orderProcessingTimer;
private final Gauge memoryUsageGauge;
public OrderMetrics(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
this.orderCounter = Counter.builder("orders.created")
.description("Total number of orders created")
.register(meterRegistry);
this.orderProcessingTimer = Timer.builder("orders.processing.time")
.description("Time taken to process an order")
.register(meterRegistry);
this.memoryUsageGauge = Gauge.builder("jvm.memory.used")
.description("JVM memory used")
.register(meterRegistry, this, OrderMetrics::getMemoryUsage);
}
public void recordOrderCreation() {
orderCounter.increment();
}
public void recordOrderProcessingTime(long duration) {
orderProcessingTimer.record(duration, TimeUnit.MILLISECONDS);
}
private double getMemoryUsage() {
Runtime runtime = Runtime.getRuntime();
long usedMemory = runtime.totalMemory() - runtime.freeMemory();
long maxMemory = runtime.maxMemory();
return (double) usedMemory / maxMemory;
}
}
安全与认证¶
OAuth2 + JWT 集成¶
授权服务器配置¶
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("web-app")
.secret(passwordEncoder().encode("secret"))
.authorizedGrantTypes("password", "refresh_token")
.scopes("read", "write")
.accessTokenValiditySeconds(3600)
.refreshTokenValiditySeconds(86400);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.authenticationManager(authenticationManager)
.userDetailsService(userDetailsService)
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter());
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("secret");
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
}
资源服务器配置¶
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/public/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/**").authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}
}
服务间安全调用¶
@Configuration
public class FeignSecurityConfig {
@Bean
public RequestInterceptor oauth2FeignRequestInterceptor() {
return requestTemplate -> {
// 从安全上下文中获取 Token 并添加到请求头
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication != null && authentication.getCredentials() instanceof OAuth2AccessToken) {
OAuth2AccessToken token = (OAuth2AccessToken) authentication.getCredentials();
requestTemplate.header("Authorization", "Bearer " + token.getValue());
}
};
}
}
// 安全的 Feign 客户端
@FeignClient(name = "user-service", configuration = FeignSecurityConfig.class)
public interface UserServiceClient {
@GetMapping("/api/users/{id}")
User getUser(@PathVariable("id") Long id);
}
总结¶
微服务架构深度实践涉及多个层面的技术挑战:
- 分布式事务:根据业务场景选择合适的模式(2PC、TCC、Saga)
- 服务网格:利用 Istio 等工具实现高级流量管理
- 云原生部署:Kubernetes 提供完整的应用生命周期管理
- 可观测性:链路追踪、指标监控、日志聚合三位一体
- 安全认证:OAuth2 + JWT 保障服务间安全通信
通过本文的深度实践指南,您将能够构建高可用、可扩展、易维护的微服务架构。
📖 相关文档:各核心组件原理速查 → Spring Cloud 核心组件