微服务架构设计与实践指南

深入探讨微服务架构的设计原则、实现模式和最佳实践,从单体应用到微服务的完整转型指南

2025年9月18日
DocsLib Team
微服务架构设计分布式系统Spring Cloud服务治理

微服务架构设计与实践指南

微服务架构是一种将单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,并使用轻量级机制(通常是HTTP API)进行通信。本文将深入探讨微服务架构的设计原则、实现模式和最佳实践。

1. 微服务架构概述

1.1 什么是微服务

微服务架构是一种架构风格,它将应用程序构建为一组松散耦合的服务。每个服务:

  • 独立部署:可以独立开发、测试和部署
  • 业务导向:围绕业务能力组织
  • 去中心化:去中心化的数据管理和治理
  • 故障隔离:一个服务的故障不会影响整个系统
  • 技术多样性:可以使用不同的编程语言和数据库

1.2 微服务 vs 单体架构

单体架构 (Monolithic):
┌─────────────────────────────────┐
│           单体应用              │
│  ┌─────┐ ┌─────┐ ┌─────┐       │
│  │用户 │ │订单 │ │支付 │       │
│  │管理 │ │管理 │ │管理 │       │
│  └─────┘ └─────┘ └─────┘       │
│         共享数据库              │
└─────────────────────────────────┘

微服务架构 (Microservices):
┌─────────┐    ┌─────────┐    ┌─────────┐
│ 用户服务 │    │ 订单服务 │    │ 支付服务 │
│ ┌─────┐ │    │ ┌─────┐ │    │ ┌─────┐ │
│ │ API │ │    │ │ API │ │    │ │ API │ │
│ └─────┘ │    │ └─────┘ │    │ └─────┘ │
│ ┌─────┐ │    │ ┌─────┐ │    │ ┌─────┐ │
│ │ DB  │ │    │ │ DB  │ │    │ │ DB  │ │
│ └─────┘ │    │ └─────┘ │    │ └─────┘ │
└─────────┘    └─────────┘    └─────────┘

1.3 微服务的优势与挑战

优势

  • 技术多样性:每个服务可以选择最适合的技术栈
  • 独立部署:加快开发和部署速度
  • 故障隔离:提高系统整体可用性
  • 团队自治:小团队可以独立负责特定服务
  • 可扩展性:可以针对特定服务进行扩展

挑战

  • 分布式系统复杂性:网络延迟、故障处理
  • 数据一致性:分布式事务管理
  • 服务间通信:API设计和版本管理
  • 运维复杂性:监控、日志、部署管理
  • 测试复杂性:集成测试和端到端测试

2. 微服务设计原则

2.1 单一职责原则

每个微服务应该有明确的业务边界和职责。

// 用户服务 - 只负责用户相关操作
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    /**
     * 获取用户信息
     */
    @GetMapping("/{userId}")
    public ResponseEntity<User> getUser(@PathVariable Long userId) {
        User user = userService.findById(userId);
        return ResponseEntity.ok(user);
    }
    
    /**
     * 创建用户
     */
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody CreateUserRequest request) {
        User user = userService.createUser(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(user);
    }
    
    /**
     * 更新用户信息
     */
    @PutMapping("/{userId}")
    public ResponseEntity<User> updateUser(
            @PathVariable Long userId, 
            @RequestBody UpdateUserRequest request) {
        User user = userService.updateUser(userId, request);
        return ResponseEntity.ok(user);
    }
}

// 订单服务 - 只负责订单相关操作
@RestController
@RequestMapping("/api/orders")
public class OrderController {
    
    @Autowired
    private OrderService orderService;
    
    /**
     * 创建订单
     */
    @PostMapping
    public ResponseEntity<Order> createOrder(@RequestBody CreateOrderRequest request) {
        Order order = orderService.createOrder(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(order);
    }
    
    /**
     * 获取用户订单列表
     */
    @GetMapping("/user/{userId}")
    public ResponseEntity<List<Order>> getUserOrders(@PathVariable Long userId) {
        List<Order> orders = orderService.findByUserId(userId);
        return ResponseEntity.ok(orders);
    }
}

2.2 数据库分离

每个微服务应该拥有自己的数据库,避免共享数据库。

# docker-compose.yml
version: '3.8'
services:
  # 用户服务数据库
  user-db:
    image: mysql:8.0
    environment:
      MYSQL_DATABASE: user_service
      MYSQL_ROOT_PASSWORD: password
    ports:
      - "3306:3306"
    volumes:
      - user_data:/var/lib/mysql
  
  # 订单服务数据库
  order-db:
    image: mysql:8.0
    environment:
      MYSQL_DATABASE: order_service
      MYSQL_ROOT_PASSWORD: password
    ports:
      - "3307:3306"
    volumes:
      - order_data:/var/lib/mysql
  
  # 支付服务数据库
  payment-db:
    image: postgresql:13
    environment:
      POSTGRES_DB: payment_service
      POSTGRES_PASSWORD: password
    ports:
      - "5432:5432"
    volumes:
      - payment_data:/var/lib/postgresql/data

volumes:
  user_data:
  order_data:
  payment_data:

2.3 API优先设计

在开发服务之前,先设计API接口。

# user-service-api.yaml
openapi: 3.0.0
info:
  title: User Service API
  version: 1.0.0
  description: 用户服务API文档

paths:
  /api/users:
    post:
      summary: 创建用户
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateUserRequest'
      responses:
        '201':
          description: 用户创建成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '400':
          description: 请求参数错误
  
  /api/users/{userId}:
    get:
      summary: 获取用户信息
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: 成功获取用户信息
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '404':
          description: 用户不存在

components:
  schemas:
    User:
      type: object
      properties:
        id:
          type: integer
          format: int64
        username:
          type: string
        email:
          type: string
        firstName:
          type: string
        lastName:
          type: string
        createdAt:
          type: string
          format: date-time
    
    CreateUserRequest:
      type: object
      required:
        - username
        - email
        - password
      properties:
        username:
          type: string
          minLength: 3
          maxLength: 50
        email:
          type: string
          format: email
        password:
          type: string
          minLength: 8
        firstName:
          type: string
        lastName:
          type: string

3. 服务间通信

3.1 同步通信 - REST API

// 订单服务调用用户服务
@Service
public class OrderService {
    
    @Autowired
    private UserServiceClient userServiceClient;
    
    @Autowired
    private OrderRepository orderRepository;
    
    /**
     * 创建订单
     */
    public Order createOrder(CreateOrderRequest request) {
        // 验证用户是否存在
        User user = userServiceClient.getUser(request.getUserId());
        if (user == null) {
            throw new UserNotFoundException("User not found: " + request.getUserId());
        }
        
        // 创建订单
        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setProductId(request.getProductId());
        order.setQuantity(request.getQuantity());
        order.setStatus(OrderStatus.PENDING);
        order.setCreatedAt(LocalDateTime.now());
        
        return orderRepository.save(order);
    }
}

// 用户服务客户端
@Component
public class UserServiceClient {
    
    @Autowired
    private RestTemplate restTemplate;
    
    @Value("${services.user.url}")
    private String userServiceUrl;
    
    /**
     * 获取用户信息
     */
    public User getUser(Long userId) {
        try {
            String url = userServiceUrl + "/api/users/" + userId;
            ResponseEntity<User> response = restTemplate.getForEntity(url, User.class);
            return response.getBody();
        } catch (HttpClientErrorException.NotFound e) {
            return null;
        } catch (Exception e) {
            throw new ServiceCommunicationException("Failed to get user: " + userId, e);
        }
    }
}

// 配置RestTemplate
@Configuration
public class RestTemplateConfig {
    
    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        
        // 设置超时时间
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        factory.setConnectTimeout(5000);
        factory.setReadTimeout(10000);
        restTemplate.setRequestFactory(factory);
        
        // 添加错误处理
        restTemplate.setErrorHandler(new CustomResponseErrorHandler());
        
        return restTemplate;
    }
}

3.2 异步通信 - 消息队列

// 使用RabbitMQ进行异步通信
@Configuration
@EnableRabbit
public class RabbitConfig {
    
    public static final String ORDER_EXCHANGE = "order.exchange";
    public static final String ORDER_CREATED_QUEUE = "order.created.queue";
    public static final String ORDER_CREATED_ROUTING_KEY = "order.created";
    
    @Bean
    public TopicExchange orderExchange() {
        return new TopicExchange(ORDER_EXCHANGE);
    }
    
    @Bean
    public Queue orderCreatedQueue() {
        return QueueBuilder.durable(ORDER_CREATED_QUEUE).build();
    }
    
    @Bean
    public Binding orderCreatedBinding() {
        return BindingBuilder
                .bind(orderCreatedQueue())
                .to(orderExchange())
                .with(ORDER_CREATED_ROUTING_KEY);
    }
    
    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate template = new RabbitTemplate(connectionFactory);
        template.setMessageConverter(new Jackson2JsonMessageConverter());
        return template;
    }
}

// 订单服务 - 发布事件
@Service
public class OrderService {
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    /**
     * 创建订单并发布事件
     */
    public Order createOrder(CreateOrderRequest request) {
        // 创建订单
        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setProductId(request.getProductId());
        order.setQuantity(request.getQuantity());
        order.setStatus(OrderStatus.PENDING);
        order.setCreatedAt(LocalDateTime.now());
        
        Order savedOrder = orderRepository.save(order);
        
        // 发布订单创建事件
        OrderCreatedEvent event = new OrderCreatedEvent(
            savedOrder.getId(),
            savedOrder.getUserId(),
            savedOrder.getProductId(),
            savedOrder.getQuantity(),
            savedOrder.getCreatedAt()
        );
        
        rabbitTemplate.convertAndSend(
            RabbitConfig.ORDER_EXCHANGE,
            RabbitConfig.ORDER_CREATED_ROUTING_KEY,
            event
        );
        
        return savedOrder;
    }
}

// 库存服务 - 监听事件
@Component
public class InventoryEventListener {
    
    @Autowired
    private InventoryService inventoryService;
    
    /**
     * 处理订单创建事件
     */
    @RabbitListener(queues = RabbitConfig.ORDER_CREATED_QUEUE)
    public void handleOrderCreated(OrderCreatedEvent event) {
        try {
            // 减少库存
            inventoryService.decreaseStock(event.getProductId(), event.getQuantity());
            
            log.info("Successfully decreased stock for product: {} by quantity: {}", 
                    event.getProductId(), event.getQuantity());
        } catch (InsufficientStockException e) {
            log.error("Insufficient stock for product: {}", event.getProductId());
            // 发布库存不足事件,触发订单取消
            publishInsufficientStockEvent(event);
        } catch (Exception e) {
            log.error("Failed to process order created event", e);
            // 重试机制或死信队列处理
        }
    }
}

// 事件对象
public class OrderCreatedEvent {
    private Long orderId;
    private Long userId;
    private Long productId;
    private Integer quantity;
    private LocalDateTime createdAt;
    
    // 构造函数、getter、setter
}

3.3 服务发现

// 使用Spring Cloud Eureka进行服务发现
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

// eureka-server配置
# application.yml
server:
  port: 8761

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

// 微服务注册到Eureka
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

// 微服务配置
# application.yml
spring:
  application:
    name: user-service

server:
  port: 8081

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true

// 使用Feign进行服务调用
@FeignClient(name = "user-service")
public interface UserServiceClient {
    
    @GetMapping("/api/users/{userId}")
    User getUser(@PathVariable("userId") Long userId);
    
    @PostMapping("/api/users")
    User createUser(@RequestBody CreateUserRequest request);
}

// 启用Feign
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
}

4. 数据管理

4.1 分布式事务

Saga模式

// 订单处理Saga
@Component
public class OrderProcessingSaga {
    
    @Autowired
    private OrderService orderService;
    
    @Autowired
    private PaymentService paymentService;
    
    @Autowired
    private InventoryService inventoryService;
    
    @Autowired
    private NotificationService notificationService;
    
    /**
     * 处理订单创建的Saga流程
     */
    public void processOrder(CreateOrderRequest request) {
        SagaTransaction saga = new SagaTransaction();
        
        try {
            // 步骤1:创建订单
            Order order = orderService.createOrder(request);
            saga.addCompensation(() -> orderService.cancelOrder(order.getId()));
            
            // 步骤2:减少库存
            inventoryService.reserveStock(request.getProductId(), request.getQuantity());
            saga.addCompensation(() -> inventoryService.releaseStock(request.getProductId(), request.getQuantity()));
            
            // 步骤3:处理支付
            Payment payment = paymentService.processPayment(order.getId(), request.getPaymentInfo());
            saga.addCompensation(() -> paymentService.refund(payment.getId()));
            
            // 步骤4:确认订单
            orderService.confirmOrder(order.getId());
            
            // 步骤5:发送通知
            notificationService.sendOrderConfirmation(order.getUserId(), order.getId());
            
            log.info("Order processed successfully: {}", order.getId());
            
        } catch (Exception e) {
            log.error("Order processing failed, executing compensation", e);
            saga.compensate();
            throw new OrderProcessingException("Failed to process order", e);
        }
    }
}

// Saga事务管理器
public class SagaTransaction {
    private final List<Runnable> compensations = new ArrayList<>();
    
    public void addCompensation(Runnable compensation) {
        compensations.add(0, compensation); // 逆序添加
    }
    
    public void compensate() {
        for (Runnable compensation : compensations) {
            try {
                compensation.run();
            } catch (Exception e) {
                log.error("Compensation failed", e);
            }
        }
    }
}

事件溯源模式

// 事件存储
@Entity
@Table(name = "event_store")
public class EventStore {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "aggregate_id")
    private String aggregateId;
    
    @Column(name = "event_type")
    private String eventType;
    
    @Column(name = "event_data", columnDefinition = "TEXT")
    private String eventData;
    
    @Column(name = "version")
    private Long version;
    
    @Column(name = "created_at")
    private LocalDateTime createdAt;
    
    // getter、setter
}

// 事件
public abstract class DomainEvent {
    private final String aggregateId;
    private final LocalDateTime occurredAt;
    
    protected DomainEvent(String aggregateId) {
        this.aggregateId = aggregateId;
        this.occurredAt = LocalDateTime.now();
    }
    
    // getter
}

public class OrderCreatedEvent extends DomainEvent {
    private final Long userId;
    private final Long productId;
    private final Integer quantity;
    private final BigDecimal amount;
    
    public OrderCreatedEvent(String orderId, Long userId, Long productId, Integer quantity, BigDecimal amount) {
        super(orderId);
        this.userId = userId;
        this.productId = productId;
        this.quantity = quantity;
        this.amount = amount;
    }
    
    // getter
}

// 聚合根
public class OrderAggregate {
    private String id;
    private Long userId;
    private OrderStatus status;
    private List<OrderItem> items;
    private BigDecimal totalAmount;
    private Long version;
    
    private final List<DomainEvent> uncommittedEvents = new ArrayList<>();
    
    /**
     * 创建订单
     */
    public static OrderAggregate createOrder(String orderId, Long userId, List<OrderItem> items) {
        OrderAggregate order = new OrderAggregate();
        order.id = orderId;
        order.userId = userId;
        order.items = items;
        order.status = OrderStatus.PENDING;
        order.totalAmount = items.stream()
                .map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        order.version = 0L;
        
        // 添加事件
        order.addEvent(new OrderCreatedEvent(
                orderId, userId, 
                items.get(0).getProductId(), 
                items.get(0).getQuantity(), 
                order.totalAmount
        ));
        
        return order;
    }
    
    /**
     * 确认订单
     */
    public void confirmOrder() {
        if (this.status != OrderStatus.PENDING) {
            throw new IllegalStateException("Order can only be confirmed when pending");
        }
        
        this.status = OrderStatus.CONFIRMED;
        this.addEvent(new OrderConfirmedEvent(this.id));
    }
    
    private void addEvent(DomainEvent event) {
        this.uncommittedEvents.add(event);
        this.version++;
    }
    
    public List<DomainEvent> getUncommittedEvents() {
        return new ArrayList<>(uncommittedEvents);
    }
    
    public void markEventsAsCommitted() {
        uncommittedEvents.clear();
    }
}

// 事件存储仓库
@Repository
public class EventStoreRepository {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    /**
     * 保存事件
     */
    public void saveEvents(String aggregateId, List<DomainEvent> events, Long expectedVersion) {
        for (DomainEvent event : events) {
            try {
                String eventData = objectMapper.writeValueAsString(event);
                
                jdbcTemplate.update(
                        "INSERT INTO event_store (aggregate_id, event_type, event_data, version, created_at) VALUES (?, ?, ?, ?, ?)",
                        aggregateId,
                        event.getClass().getSimpleName(),
                        eventData,
                        expectedVersion + 1,
                        event.getOccurredAt()
                );
                
                expectedVersion++;
            } catch (Exception e) {
                throw new EventStoreException("Failed to save event", e);
            }
        }
    }
    
    /**
     * 加载事件
     */
    public List<DomainEvent> loadEvents(String aggregateId) {
        List<EventStore> eventStores = jdbcTemplate.query(
                "SELECT * FROM event_store WHERE aggregate_id = ? ORDER BY version",
                new Object[]{aggregateId},
                (rs, rowNum) -> {
                    EventStore eventStore = new EventStore();
                    eventStore.setId(rs.getLong("id"));
                    eventStore.setAggregateId(rs.getString("aggregate_id"));
                    eventStore.setEventType(rs.getString("event_type"));
                    eventStore.setEventData(rs.getString("event_data"));
                    eventStore.setVersion(rs.getLong("version"));
                    eventStore.setCreatedAt(rs.getTimestamp("created_at").toLocalDateTime());
                    return eventStore;
                }
        );
        
        return eventStores.stream()
                .map(this::deserializeEvent)
                .collect(Collectors.toList());
    }
    
    private DomainEvent deserializeEvent(EventStore eventStore) {
        try {
            Class<?> eventClass = Class.forName("com.example.events." + eventStore.getEventType());
            return (DomainEvent) objectMapper.readValue(eventStore.getEventData(), eventClass);
        } catch (Exception e) {
            throw new EventStoreException("Failed to deserialize event", e);
        }
    }
}

4.2 CQRS模式

// 命令模型
@Entity
@Table(name = "orders")
public class OrderWriteModel {
    @Id
    private String id;
    
    @Column(name = "user_id")
    private Long userId;
    
    @Enumerated(EnumType.STRING)
    private OrderStatus status;
    
    @Column(name = "total_amount")
    private BigDecimal totalAmount;
    
    @Column(name = "created_at")
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at")
    private LocalDateTime updatedAt;
    
    // getter、setter
}

// 查询模型
@Document(collection = "order_views")
public class OrderReadModel {
    @Id
    private String id;
    
    private Long userId;
    private String userEmail;
    private String userName;
    private OrderStatus status;
    private BigDecimal totalAmount;
    private List<OrderItemView> items;
    private LocalDateTime createdAt;
    private LocalDateTime updatedAt;
    
    // getter、setter
}

public class OrderItemView {
    private Long productId;
    private String productName;
    private String productImage;
    private BigDecimal price;
    private Integer quantity;
    private BigDecimal subtotal;
    
    // getter、setter
}

// 命令处理器
@Component
public class OrderCommandHandler {
    
    @Autowired
    private OrderWriteRepository orderWriteRepository;
    
    @Autowired
    private EventPublisher eventPublisher;
    
    /**
     * 处理创建订单命令
     */
    public void handle(CreateOrderCommand command) {
        // 验证命令
        validateCreateOrderCommand(command);
        
        // 创建订单
        OrderWriteModel order = new OrderWriteModel();
        order.setId(UUID.randomUUID().toString());
        order.setUserId(command.getUserId());
        order.setStatus(OrderStatus.PENDING);
        order.setTotalAmount(command.getTotalAmount());
        order.setCreatedAt(LocalDateTime.now());
        order.setUpdatedAt(LocalDateTime.now());
        
        orderWriteRepository.save(order);
        
        // 发布事件
        eventPublisher.publish(new OrderCreatedEvent(
                order.getId(),
                order.getUserId(),
                command.getItems(),
                order.getTotalAmount()
        ));
    }
    
    /**
     * 处理确认订单命令
     */
    public void handle(ConfirmOrderCommand command) {
        OrderWriteModel order = orderWriteRepository.findById(command.getOrderId())
                .orElseThrow(() -> new OrderNotFoundException(command.getOrderId()));
        
        if (order.getStatus() != OrderStatus.PENDING) {
            throw new IllegalStateException("Order can only be confirmed when pending");
        }
        
        order.setStatus(OrderStatus.CONFIRMED);
        order.setUpdatedAt(LocalDateTime.now());
        
        orderWriteRepository.save(order);
        
        // 发布事件
        eventPublisher.publish(new OrderConfirmedEvent(order.getId()));
    }
}

// 查询处理器
@Component
public class OrderQueryHandler {
    
    @Autowired
    private OrderReadRepository orderReadRepository;
    
    /**
     * 获取用户订单列表
     */
    public List<OrderReadModel> getUserOrders(Long userId, Pageable pageable) {
        return orderReadRepository.findByUserIdOrderByCreatedAtDesc(userId, pageable);
    }
    
    /**
     * 获取订单详情
     */
    public OrderReadModel getOrderDetail(String orderId) {
        return orderReadRepository.findById(orderId)
                .orElseThrow(() -> new OrderNotFoundException(orderId));
    }
    
    /**
     * 搜索订单
     */
    public List<OrderReadModel> searchOrders(OrderSearchCriteria criteria) {
        Query query = new Query();
        
        if (criteria.getUserId() != null) {
            query.addCriteria(Criteria.where("userId").is(criteria.getUserId()));
        }
        
        if (criteria.getStatus() != null) {
            query.addCriteria(Criteria.where("status").is(criteria.getStatus()));
        }
        
        if (criteria.getStartDate() != null && criteria.getEndDate() != null) {
            query.addCriteria(Criteria.where("createdAt")
                    .gte(criteria.getStartDate())
                    .lte(criteria.getEndDate()));
        }
        
        query.with(Sort.by(Sort.Direction.DESC, "createdAt"));
        
        return mongoTemplate.find(query, OrderReadModel.class);
    }
}

// 事件处理器 - 更新查询模型
@Component
public class OrderViewUpdater {
    
    @Autowired
    private OrderReadRepository orderReadRepository;
    
    @Autowired
    private UserServiceClient userServiceClient;
    
    @Autowired
    private ProductServiceClient productServiceClient;
    
    /**
     * 处理订单创建事件
     */
    @EventHandler
    public void on(OrderCreatedEvent event) {
        // 获取用户信息
        User user = userServiceClient.getUser(event.getUserId());
        
        // 获取商品信息
        List<OrderItemView> itemViews = event.getItems().stream()
                .map(item -> {
                    Product product = productServiceClient.getProduct(item.getProductId());
                    OrderItemView itemView = new OrderItemView();
                    itemView.setProductId(item.getProductId());
                    itemView.setProductName(product.getName());
                    itemView.setProductImage(product.getImageUrl());
                    itemView.setPrice(item.getPrice());
                    itemView.setQuantity(item.getQuantity());
                    itemView.setSubtotal(item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())));
                    return itemView;
                })
                .collect(Collectors.toList());
        
        // 创建查询模型
        OrderReadModel orderView = new OrderReadModel();
        orderView.setId(event.getOrderId());
        orderView.setUserId(event.getUserId());
        orderView.setUserEmail(user.getEmail());
        orderView.setUserName(user.getFirstName() + " " + user.getLastName());
        orderView.setStatus(OrderStatus.PENDING);
        orderView.setTotalAmount(event.getTotalAmount());
        orderView.setItems(itemViews);
        orderView.setCreatedAt(event.getOccurredAt());
        orderView.setUpdatedAt(event.getOccurredAt());
        
        orderReadRepository.save(orderView);
    }
    
    /**
     * 处理订单确认事件
     */
    @EventHandler
    public void on(OrderConfirmedEvent event) {
        OrderReadModel orderView = orderReadRepository.findById(event.getOrderId())
                .orElseThrow(() -> new OrderNotFoundException(event.getOrderId()));
        
        orderView.setStatus(OrderStatus.CONFIRMED);
        orderView.setUpdatedAt(event.getOccurredAt());
        
        orderReadRepository.save(orderView);
    }
}

5. 服务治理

5.1 API网关

// 使用Spring Cloud Gateway
@SpringBootApplication
public class ApiGatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiGatewayApplication.class, args);
    }
}

// 网关配置
# application.yml
spring:
  cloud:
    gateway:
      routes:
        # 用户服务路由
        - id: user-service
          uri: lb://user-service
          predicates:
            - Path=/api/users/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 10
                redis-rate-limiter.burstCapacity: 20
                key-resolver: "#{@userKeyResolver}"
            - name: CircuitBreaker
              args:
                name: user-service-cb
                fallbackUri: forward:/fallback/user
        
        # 订单服务路由
        - id: order-service
          uri: lb://order-service
          predicates:
            - Path=/api/orders/**
          filters:
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 5
                redis-rate-limiter.burstCapacity: 10
            - AddRequestHeader=X-Request-Source, api-gateway
        
        # 支付服务路由
        - id: payment-service
          uri: lb://payment-service
          predicates:
            - Path=/api/payments/**
          filters:
            - name: Retry
              args:
                retries: 3
                statuses: BAD_GATEWAY,GATEWAY_TIMEOUT
                methods: GET,POST
      
      # 全局过滤器
      default-filters:
        - name: GlobalLogging
        - name: AddResponseHeader
          args:
            name: X-Response-Time
            value: "#{T(System).currentTimeMillis()}"

// 自定义过滤器
@Component
public class AuthenticationFilter implements GlobalFilter, Ordered {
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        
        // 跳过认证的路径
        if (isPublicPath(request.getPath().value())) {
            return chain.filter(exchange);
        }
        
        // 获取Authorization头
        String authHeader = request.getHeaders().getFirst("Authorization");
        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            return unauthorized(exchange);
        }
        
        String token = authHeader.substring(7);
        
        try {
            // 验证JWT token
            if (!jwtTokenUtil.validateToken(token)) {
                return unauthorized(exchange);
            }
            
            // 提取用户信息并添加到请求头
            String userId = jwtTokenUtil.getUserIdFromToken(token);
            ServerHttpRequest modifiedRequest = request.mutate()
                    .header("X-User-Id", userId)
                    .build();
            
            return chain.filter(exchange.mutate().request(modifiedRequest).build());
            
        } catch (Exception e) {
            return unauthorized(exchange);
        }
    }
    
    private boolean isPublicPath(String path) {
        return path.startsWith("/api/auth/") || 
               path.startsWith("/api/public/") ||
               path.equals("/health");
    }
    
    private Mono<Void> unauthorized(ServerWebExchange exchange) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        return response.setComplete();
    }
    
    @Override
    public int getOrder() {
        return -100; // 高优先级
    }
}

// 限流Key解析器
@Component("userKeyResolver")
public class UserKeyResolver implements KeyResolver {
    
    @Override
    public Mono<String> resolve(ServerWebExchange exchange) {
        // 基于用户ID限流
        String userId = exchange.getRequest().getHeaders().getFirst("X-User-Id");
        if (userId != null) {
            return Mono.just(userId);
        }
        
        // 基于IP限流
        String clientIp = getClientIp(exchange.getRequest());
        return Mono.just(clientIp);
    }
    
    private String getClientIp(ServerHttpRequest request) {
        String xForwardedFor = request.getHeaders().getFirst("X-Forwarded-For");
        if (xForwardedFor != null && !xForwardedFor.isEmpty()) {
            return xForwardedFor.split(",")[0].trim();
        }
        
        String xRealIp = request.getHeaders().getFirst("X-Real-IP");
        if (xRealIp != null && !xRealIp.isEmpty()) {
            return xRealIp;
        }
        
        return request.getRemoteAddress() != null ? 
                request.getRemoteAddress().getAddress().getHostAddress() : "unknown";
    }
}

5.2 熔断器

// 使用Resilience4j
@Configuration
public class CircuitBreakerConfig {
    
    @Bean
    public CircuitBreaker userServiceCircuitBreaker() {
        return CircuitBreaker.ofDefaults("user-service");
    }
    
    @Bean
    public CircuitBreakerConfig userServiceCircuitBreakerConfig() {
        return CircuitBreakerConfig.custom()
                .failureRateThreshold(50) // 失败率阈值50%
                .waitDurationInOpenState(Duration.ofSeconds(30)) // 熔断器打开后等待30秒
                .slidingWindowSize(10) // 滑动窗口大小
                .minimumNumberOfCalls(5) // 最小调用次数
                .permittedNumberOfCallsInHalfOpenState(3) // 半开状态允许的调用次数
                .build();
    }
}

// 在服务调用中使用熔断器
@Service
public class OrderService {
    
    @Autowired
    private UserServiceClient userServiceClient;
    
    private final CircuitBreaker circuitBreaker;
    
    public OrderService(CircuitBreaker userServiceCircuitBreaker) {
        this.circuitBreaker = userServiceCircuitBreaker;
    }
    
    /**
     * 创建订单(带熔断保护)
     */
    public Order createOrder(CreateOrderRequest request) {
        // 使用熔断器保护用户服务调用
        Supplier<User> userSupplier = CircuitBreaker
                .decorateSupplier(circuitBreaker, () -> userServiceClient.getUser(request.getUserId()));
        
        try {
            User user = userSupplier.get();
            
            // 创建订单逻辑
            Order order = new Order();
            order.setUserId(user.getId());
            order.setUserEmail(user.getEmail());
            // ... 其他订单创建逻辑
            
            return orderRepository.save(order);
            
        } catch (CallNotPermittedException e) {
            // 熔断器打开,使用降级逻辑
            log.warn("User service circuit breaker is open, using fallback");
            return createOrderWithFallback(request);
        }
    }
    
    /**
     * 降级方法
     */
    private Order createOrderWithFallback(CreateOrderRequest request) {
        // 使用缓存的用户信息或默认值
        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setUserEmail("unknown@example.com"); // 默认值
        order.setStatus(OrderStatus.PENDING_VERIFICATION); // 特殊状态,需要后续验证
        
        return orderRepository.save(order);
    }
}

// 使用注解方式
@Component
public class PaymentService {
    
    @Autowired
    private BankServiceClient bankServiceClient;
    
    /**
     * 处理支付(使用注解配置熔断器)
     */
    @CircuitBreaker(name = "bank-service", fallbackMethod = "processPaymentFallback")
    @Retry(name = "bank-service")
    @TimeLimiter(name = "bank-service")
    public CompletableFuture<Payment> processPayment(PaymentRequest request) {
        return CompletableFuture.supplyAsync(() -> {
            // 调用银行服务
            BankResponse response = bankServiceClient.processPayment(request);
            
            // 创建支付记录
            Payment payment = new Payment();
            payment.setOrderId(request.getOrderId());
            payment.setAmount(request.getAmount());
            payment.setStatus(PaymentStatus.COMPLETED);
            payment.setTransactionId(response.getTransactionId());
            
            return paymentRepository.save(payment);
        });
    }
    
    /**
     * 支付降级方法
     */
    public CompletableFuture<Payment> processPaymentFallback(PaymentRequest request, Exception ex) {
        log.error("Payment processing failed, using fallback", ex);
        
        return CompletableFuture.supplyAsync(() -> {
            // 创建待处理的支付记录
            Payment payment = new Payment();
            payment.setOrderId(request.getOrderId());
            payment.setAmount(request.getAmount());
            payment.setStatus(PaymentStatus.PENDING); // 待处理状态
            payment.setFailureReason(ex.getMessage());
            
            return paymentRepository.save(payment);
        });
    }
}

// Resilience4j配置
# application.yml
resilience4j:
  circuitbreaker:
    instances:
      user-service:
        failure-rate-threshold: 50
        wait-duration-in-open-state: 30s
        sliding-window-size: 10
        minimum-number-of-calls: 5
        permitted-number-of-calls-in-half-open-state: 3
      bank-service:
        failure-rate-threshold: 60
        wait-duration-in-open-state: 60s
        sliding-window-size: 20
  
  retry:
    instances:
      bank-service:
        max-attempts: 3
        wait-duration: 1s
        retry-exceptions:
          - java.net.SocketTimeoutException
          - java.io.IOException
  
  timelimiter:
    instances:
      bank-service:
        timeout-duration: 10s

6. 监控和可观测性

6.1 分布式链路追踪

// 使用Spring Cloud Sleuth + Zipkin
@SpringBootApplication
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }
    
    // 配置采样率
    @Bean
    public ProbabilityBasedSampler alwaysSampler() {
        return new ProbabilityBasedSampler(1.0f); // 100%采样
    }
}

// 配置链路追踪
# application.yml
spring:
  sleuth:
    zipkin:
      base-url: http://zipkin-server:9411
    sampler:
      probability: 1.0 # 采样率
  application:
    name: order-service

// 自定义Span
@Service
public class OrderService {
    
    private final Tracer tracer;
    
    public OrderService(Tracer tracer) {
        this.tracer = tracer;
    }
    
    /**
     * 创建订单(带自定义追踪)
     */
    public Order createOrder(CreateOrderRequest request) {
        Span span = tracer.nextSpan()
                .name("create-order")
                .tag("user.id", String.valueOf(request.getUserId()))
                .tag("order.amount", request.getTotalAmount().toString())
                .start();
        
        try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) {
            // 验证用户
            Span userValidationSpan = tracer.nextSpan()
                    .name("validate-user")
                    .start();
            
            try (Tracer.SpanInScope userWs = tracer.withSpanInScope(userValidationSpan)) {
                User user = userServiceClient.getUser(request.getUserId());
                userValidationSpan.tag("user.email", user.getEmail());
            } finally {
                userValidationSpan.end();
            }
            
            // 创建订单
            Order order = new Order();
            order.setUserId(request.getUserId());
            order.setTotalAmount(request.getTotalAmount());
            order.setStatus(OrderStatus.PENDING);
            order.setCreatedAt(LocalDateTime.now());
            
            Order savedOrder = orderRepository.save(order);
            
            span.tag("order.id", savedOrder.getId());
            span.event("order.created");
            
            return savedOrder;
            
        } catch (Exception e) {
            span.tag("error", e.getMessage());
            throw e;
        } finally {
            span.end();
        }
    }
}

// 异步处理的链路追踪
@Component
public class OrderEventHandler {
    
    private final Tracer tracer;
    
    public OrderEventHandler(Tracer tracer) {
        this.tracer = tracer;
    }
    
    @RabbitListener(queues = "order.created.queue")
    public void handleOrderCreated(OrderCreatedEvent event, 
                                   @Header Map<String, Object> headers) {
        // 从消息头中恢复追踪上下文
        SpanBuilder spanBuilder = tracer.nextSpan().name("handle-order-created");
        
        // 如果有父Span信息,设置父子关系
        if (headers.containsKey("X-Trace-Id")) {
            String traceId = (String) headers.get("X-Trace-Id");
            String spanId = (String) headers.get("X-Span-Id");
            // 设置追踪上下文
        }
        
        Span span = spanBuilder.start();
        
        try (Tracer.SpanInScope ws = tracer.withSpanInScope(span)) {
            span.tag("order.id", event.getOrderId());
            span.tag("user.id", String.valueOf(event.getUserId()));
            
            // 处理订单创建事件
            processOrderCreatedEvent(event);
            
            span.event("order.processed");
            
        } catch (Exception e) {
            span.tag("error", e.getMessage());
            throw e;
        } finally {
            span.end();
        }
    }
}

6.2 指标监控

// 使用Micrometer + Prometheus
@Configuration
public class MetricsConfig {
    
    @Bean
    public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
        return registry -> registry.config().commonTags(
                "application", "order-service",
                "version", "1.0.0"
        );
    }
    
    @Bean
    public TimedAspect timedAspect(MeterRegistry registry) {
        return new TimedAspect(registry);
    }
}

// 自定义指标
@Service
public class OrderService {
    
    private final Counter orderCreatedCounter;
    private final Timer orderProcessingTimer;
    private final Gauge activeOrdersGauge;
    private final DistributionSummary orderAmountSummary;
    
    public OrderService(MeterRegistry meterRegistry) {
        this.orderCreatedCounter = Counter.builder("orders.created")
                .description("Number of orders created")
                .register(meterRegistry);
        
        this.orderProcessingTimer = Timer.builder("orders.processing.time")
                .description("Order processing time")
                .register(meterRegistry);
        
        this.activeOrdersGauge = Gauge.builder("orders.active")
                .description("Number of active orders")
                .register(meterRegistry, this, OrderService::getActiveOrderCount);
        
        this.orderAmountSummary = DistributionSummary.builder("orders.amount")
                .description("Order amount distribution")
                .baseUnit("dollars")
                .register(meterRegistry);
    }
    
    /**
     * 创建订单(带指标监控)
     */
    @Timed(name = "orders.create", description = "Time taken to create an order")
    public Order createOrder(CreateOrderRequest request) {
        return Timer.Sample.start(orderProcessingTimer)
                .stop(() -> {
                    try {
                        Order order = doCreateOrder(request);
                        
                        // 记录指标
                        orderCreatedCounter.increment(
                                Tags.of(
                                        "status", "success",
                                        "user.type", getUserType(request.getUserId())
                                )
                        );
                        
                        orderAmountSummary.record(order.getTotalAmount().doubleValue());
                        
                        return order;
                        
                    } catch (Exception e) {
                        orderCreatedCounter.increment(
                                Tags.of(
                                        "status", "error",
                                        "error.type", e.getClass().getSimpleName()
                                )
                        );
                        throw e;
                    }
                });
    }
    
    private double getActiveOrderCount() {
        return orderRepository.countByStatus(OrderStatus.PENDING);
    }
}

// 健康检查
@Component
public class OrderServiceHealthIndicator implements HealthIndicator {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private UserServiceClient userServiceClient;
    
    @Override
    public Health health() {
        try {
            // 检查数据库连接
            long orderCount = orderRepository.count();
            
            // 检查依赖服务
            boolean userServiceHealthy = checkUserServiceHealth();
            
            if (userServiceHealthy) {
                return Health.up()
                        .withDetail("database", "UP")
                        .withDetail("orderCount", orderCount)
                        .withDetail("userService", "UP")
                        .build();
            } else {
                return Health.down()
                        .withDetail("database", "UP")
                        .withDetail("orderCount", orderCount)
                        .withDetail("userService", "DOWN")
                        .build();
            }
            
        } catch (Exception e) {
            return Health.down()
                    .withDetail("database", "DOWN")
                    .withDetail("error", e.getMessage())
                    .build();
        }
    }
    
    private boolean checkUserServiceHealth() {
        try {
            // 简单的健康检查调用
            userServiceClient.healthCheck();
            return true;
        } catch (Exception e) {
            return false;
        }
    }
}

// Prometheus配置
# application.yml
management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics,prometheus
  endpoint:
    health:
      show-details: always
    metrics:
      enabled: true
    prometheus:
      enabled: true
  metrics:
    export:
      prometheus:
        enabled: true
    distribution:
      percentiles-histogram:
        http.server.requests: true
        orders.processing.time: true

6.3 日志聚合

// 结构化日志配置
@Configuration
public class LoggingConfig {
    
    @Bean
    public Logger structuredLogger() {
        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
        
        // JSON编码器
        JsonEncoder jsonEncoder = new JsonEncoder();
        jsonEncoder.setContext(context);
        jsonEncoder.start();
        
        // 控制台输出
        ConsoleAppender<ILoggingEvent> consoleAppender = new ConsoleAppender<>();
        consoleAppender.setContext(context);
        consoleAppender.setEncoder(jsonEncoder);
        consoleAppender.start();
        
        // 根日志器
        ch.qos.logback.classic.Logger rootLogger = context.getLogger(Logger.ROOT_LOGGER_NAME);
        rootLogger.addAppender(consoleAppender);
        rootLogger.setLevel(Level.INFO);
        
        return rootLogger;
    }
}

// 日志配置文件
<!-- logback-spring.xml -->
<configuration>
    <springProfile name="!local">
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
                <providers>
                    <timestamp/>
                    <logLevel/>
                    <loggerName/>
                    <message/>
                    <mdc/>
                    <arguments/>
                    <stackTrace/>
                    <pattern>
                        <pattern>
                            {
                                "service": "order-service",
                                "traceId": "%X{traceId:-}",
                                "spanId": "%X{spanId:-}"
                            }
                        </pattern>
                    </pattern>
                </providers>
            </encoder>
        </appender>
    </springProfile>
    
    <springProfile name="local">
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level [%X{traceId:-},%X{spanId:-}] %logger{36} - %msg%n</pattern>
            </encoder>
        </appender>
    </springProfile>
    
    <root level="INFO">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

// 自定义日志组件
@Component
public class AuditLogger {
    
    private final Logger logger = LoggerFactory.getLogger("AUDIT");
    private final ObjectMapper objectMapper;
    
    public AuditLogger(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }
    
    /**
     * 记录订单操作审计日志
     */
    public void logOrderOperation(String operation, String orderId, Long userId, Object details) {
        try {
            AuditLog auditLog = AuditLog.builder()
                    .operation(operation)
                    .resourceType("ORDER")
                    .resourceId(orderId)
                    .userId(userId)
                    .timestamp(LocalDateTime.now())
                    .details(objectMapper.writeValueAsString(details))
                    .build();
            
            logger.info("AUDIT: {}", objectMapper.writeValueAsString(auditLog));
            
        } catch (Exception e) {
            logger.error("Failed to log audit event", e);
        }
    }
}

@Data
@Builder
public class AuditLog {
    private String operation;
    private String resourceType;
    private String resourceId;
    private Long userId;
    private LocalDateTime timestamp;
    private String details;
}

7. 安全性

7.1 服务间认证

// JWT Token工具类
@Component
public class JwtTokenUtil {
    
    @Value("${jwt.secret}")
    private String secret;
    
    @Value("${jwt.expiration}")
    private Long expiration;
    
    /**
     * 生成服务间调用token
     */
    public String generateServiceToken(String serviceId) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("service_id", serviceId);
        claims.put("type", "service");
        
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(serviceId)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expiration))
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }
    
    /**
     * 验证服务token
     */
    public boolean validateServiceToken(String token, String expectedServiceId) {
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
            
            String serviceId = claims.get("service_id", String.class);
            String type = claims.get("type", String.class);
            
            return "service".equals(type) && 
                   expectedServiceId.equals(serviceId) && 
                   !isTokenExpired(claims);
                   
        } catch (Exception e) {
            return false;
        }
    }
    
    private boolean isTokenExpired(Claims claims) {
        return claims.getExpiration().before(new Date());
    }
}

// 服务间调用拦截器
@Component
public class ServiceAuthInterceptor implements HandlerInterceptor {
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) throws Exception {
        
        // 检查是否是服务间调用
        String serviceToken = request.getHeader("X-Service-Token");
        if (serviceToken == null) {
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }
        
        // 验证服务token
        String expectedServiceId = getExpectedServiceId(request);
        if (!jwtTokenUtil.validateServiceToken(serviceToken, expectedServiceId)) {
            response.setStatus(HttpStatus.FORBIDDEN.value());
            return false;
        }
        
        return true;
    }
    
    private String getExpectedServiceId(HttpServletRequest request) {
        // 根据请求路径或其他信息确定期望的服务ID
        String path = request.getRequestURI();
        if (path.startsWith("/api/internal/")) {
            return "order-service"; // 示例
        }
        return null;
    }
}

// Feign客户端添加服务认证
@Component
public class ServiceAuthRequestInterceptor implements RequestInterceptor {
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    
    @Value("${spring.application.name}")
    private String serviceId;
    
    @Override
    public void apply(RequestTemplate template) {
        // 为服务间调用添加认证token
        String serviceToken = jwtTokenUtil.generateServiceToken(serviceId);
        template.header("X-Service-Token", serviceToken);
    }
}

7.2 数据加密

// 敏感数据加密
@Component
public class DataEncryptionService {
    
    private final AESUtil aesUtil;
    
    public DataEncryptionService(@Value("${encryption.key}") String encryptionKey) {
        this.aesUtil = new AESUtil(encryptionKey);
    }
    
    /**
     * 加密敏感字段
     */
    public String encryptSensitiveData(String data) {
        if (data == null || data.isEmpty()) {
            return data;
        }
        
        try {
            return aesUtil.encrypt(data);
        } catch (Exception e) {
            throw new EncryptionException("Failed to encrypt data", e);
        }
    }
    
    /**
     * 解密敏感字段
     */
    public String decryptSensitiveData(String encryptedData) {
        if (encryptedData == null || encryptedData.isEmpty()) {
            return encryptedData;
        }
        
        try {
            return aesUtil.decrypt(encryptedData);
        } catch (Exception e) {
            throw new DecryptionException("Failed to decrypt data", e);
        }
    }
}

// JPA实体加密
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "username")
    private String username;
    
    @Convert(converter = EncryptedStringConverter.class)
    @Column(name = "email")
    private String email;
    
    @Convert(converter = EncryptedStringConverter.class)
    @Column(name = "phone")
    private String phone;
    
    // getter、setter
}

// 加密转换器
@Converter
public class EncryptedStringConverter implements AttributeConverter<String, String> {
    
    @Autowired
    private DataEncryptionService encryptionService;
    
    @Override
    public String convertToDatabaseColumn(String attribute) {
        return encryptionService.encryptSensitiveData(attribute);
    }
    
    @Override
    public String convertToEntityAttribute(String dbData) {
        return encryptionService.decryptSensitiveData(dbData);
    }
}

8. 部署和运维

8.1 容器化部署

# 多阶段构建Dockerfile
FROM openjdk:11-jdk-slim AS builder

WORKDIR /app
COPY pom.xml .
COPY src ./src

# 构建应用
RUN ./mvnw clean package -DskipTests

# 运行时镜像
FROM openjdk:11-jre-slim

# 创建非root用户
RUN groupadd -r appuser && useradd -r -g appuser appuser

# 安装必要的工具
RUN apt-get update && apt-get install -y \
    curl \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# 复制应用文件
COPY --from=builder /app/target/*.jar app.jar

# 设置文件权限
RUN chown -R appuser:appuser /app
USER appuser

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
    CMD curl -f http://localhost:8080/actuator/health || exit 1

# 暴露端口
EXPOSE 8080

# 启动应用
ENTRYPOINT ["java", "-jar", "-Djava.security.egd=file:/dev/./urandom", "app.jar"]
# docker-compose.yml
version: '3.8'

services:
  # 服务发现
  eureka-server:
    image: microservices/eureka-server:latest
    ports:
      - "8761:8761"
    environment:
      - SPRING_PROFILES_ACTIVE=docker
    networks:
      - microservices-network
  
  # API网关
  api-gateway:
    image: microservices/api-gateway:latest
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka-server:8761/eureka
    depends_on:
      - eureka-server
    networks:
      - microservices-network
  
  # 用户服务
  user-service:
    image: microservices/user-service:latest
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - SPRING_DATASOURCE_URL=jdbc:mysql://user-db:3306/user_service
      - EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka-server:8761/eureka
    depends_on:
      - user-db
      - eureka-server
    networks:
      - microservices-network
    deploy:
      replicas: 2
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 256M
  
  # 用户服务数据库
  user-db:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=rootpassword
      - MYSQL_DATABASE=user_service
      - MYSQL_USER=user_service
      - MYSQL_PASSWORD=password
    volumes:
      - user_data:/var/lib/mysql
    networks:
      - microservices-network
  
  # 订单服务
  order-service:
    image: microservices/order-service:latest
    environment:
      - SPRING_PROFILES_ACTIVE=docker
      - SPRING_DATASOURCE_URL=jdbc:mysql://order-db:3306/order_service
      - EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://eureka-server:8761/eureka
      - SPRING_RABBITMQ_HOST=rabbitmq
    depends_on:
      - order-db
      - eureka-server
      - rabbitmq
    networks:
      - microservices-network
    deploy:
      replicas: 3
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 256M
  
  # 订单服务数据库
  order-db:
    image: mysql:8.0
    environment:
      - MYSQL_ROOT_PASSWORD=rootpassword
      - MYSQL_DATABASE=order_service
      - MYSQL_USER=order_service
      - MYSQL_PASSWORD=password
    volumes:
      - order_data:/var/lib/mysql
    networks:
      - microservices-network
  
  # 消息队列
  rabbitmq:
    image: rabbitmq:3-management
    ports:
      - "15672:15672"
    environment:
      - RABBITMQ_DEFAULT_USER=admin
      - RABBITMQ_DEFAULT_PASS=password
    volumes:
      - rabbitmq_data:/var/lib/rabbitmq
    networks:
      - microservices-network
  
  # Redis缓存
  redis:
    image: redis:6-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis_data:/data
    networks:
      - microservices-network
  
  # 监控
  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    networks:
      - microservices-network
  
  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana_data:/var/lib/grafana
    networks:
      - microservices-network
  
  # 链路追踪
  zipkin:
    image: openzipkin/zipkin
    ports:
      - "9411:9411"
    networks:
      - microservices-network

volumes:
  user_data:
  order_data:
  rabbitmq_data:
  redis_data:
  prometheus_data:
  grafana_data:

networks:
  microservices-network:
    driver: bridge

8.2 Kubernetes部署

# user-service-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: user-service
  labels:
    app: user-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app: user-service
  template:
    metadata:
      labels:
        app: user-service
    spec:
      containers:
      - name: user-service
        image: microservices/user-service:1.0.0
        ports:
        - containerPort: 8080
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "kubernetes"
        - name: SPRING_DATASOURCE_URL
          value: "jdbc:mysql://user-db-service:3306/user_service"
        - name: SPRING_DATASOURCE_USERNAME
          valueFrom:
            secretKeyRef:
              name: user-db-secret
              key: username
        - name: SPRING_DATASOURCE_PASSWORD
          valueFrom:
            secretKeyRef:
              name: user-db-secret
              key: password
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: user-service
spec:
  selector:
    app: user-service
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: ClusterIP
---
apiVersion: v1
kind: Secret
metadata:
  name: user-db-secret
type: Opaque
data:
  username: dXNlcl9zZXJ2aWNl  # base64 encoded
  password: cGFzc3dvcmQ=      # base64 encoded
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: microservices-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/rate-limit-window: "1m"
spec:
  rules:
  - host: api.microservices.local
    http:
      paths:
      - path: /api/users
        pathType: Prefix
        backend:
          service:
            name: user-service
            port:
              number: 80
      - path: /api/orders
        pathType: Prefix
        backend:
          service:
            name: order-service
            port:
              number: 80
      - path: /api/payments
        pathType: Prefix
        backend:
          service:
            name: payment-service
            port:
              number: 80

9. 最佳实践总结

9.1 设计原则

  1. 单一职责:每个微服务只负责一个业务领域
  2. 数据独立:每个服务拥有独立的数据存储
  3. API优先:先设计API接口,再实现服务
  4. 故障隔离:服务间故障不应相互影响
  5. 自动化:部署、测试、监控全面自动化

9.2 开发建议

  1. 渐进式迁移:从单体应用逐步拆分为微服务
  2. 领域驱动设计:基于业务领域划分服务边界
  3. 契约测试:确保服务间接口的兼容性
  4. 版本管理:API版本化和向后兼容
  5. 文档维护:保持API文档和架构文档的更新

9.3 运维要点

  1. 监控全覆盖:应用监控、基础设施监控、业务监控
  2. 日志集中化:统一日志收集和分析
  3. 自动化部署:CI/CD流水线和蓝绿部署
  4. 容量规划:基于监控数据进行容量规划
  5. 灾难恢复:制定完善的灾难恢复计划

9.4 团队组织

  1. 跨功能团队:每个团队负责完整的服务生命周期
  2. DevOps文化:开发和运维紧密协作
  3. 知识共享:定期技术分享和最佳实践交流
  4. 持续学习:跟上技术发展趋势

结语

微服务架构是一种强大的架构模式,能够帮助组织构建可扩展、可维护的分布式系统。但同时也带来了复杂性挑战,需要在技术、流程和组织层面做好充分准备。

成功实施微服务架构的关键在于:

  • 明确的业务边界划分
  • 完善的基础设施支撑
  • 强大的监控和运维能力
  • 成熟的团队协作模式

希望本文能够为你的微服务架构实践提供有价值的参考和指导。

返回博客列表
感谢阅读!