架构设计--事件驱动架构设计与实现(05)

系列导读:本篇将深入讲解事件驱动架构的核心概念、设计模式与最佳实践。


文章目录

    • 一、事件驱动概述
      • [1.1 什么是事件驱动架构?](#1.1 什么是事件驱动架构?)
      • [1.2 架构对比](#1.2 架构对比)
    • 二、核心概念
      • [2.1 事件定义](#2.1 事件定义)
      • [2.2 事件流](#2.2 事件流)
    • 三、事件模式
      • [3.1 事件通知](#3.1 事件通知)
      • [3.2 事件溯源](#3.2 事件溯源)
      • [3.3 CQRS](#3.3 CQRS)
    • 四、技术选型
      • [4.1 消息中间件对比](#4.1 消息中间件对比)
      • [4.2 选型建议](#4.2 选型建议)
    • 五、代码实战
      • [5.1 Spring Event](#5.1 Spring Event)
      • [5.2 Kafka 集成](#5.2 Kafka 集成)
    • 总结

一、事件驱动概述

1.1 什么是事件驱动架构?

事件驱动架构是一种以事件为核心进行系统通信的架构模式。

复制代码
┌─────────────────────────────────────────────────────────────┐
│                    事件驱动特征                              │
├─────────────────────────────────────────────────────────────┤
│  📢 松耦合:生产者和消费者互不依赖                           │
│  ⚡ 异步处理:提高系统响应速度                               │
│  🔄 可扩展:易于添加新的事件消费者                           │
│  📊 可追溯:事件日志便于审计和回放                           │
└─────────────────────────────────────────────────────────────┘

1.2 架构对比

模式 说明
同步调用 请求-响应模式,强耦合
异步消息 生产者-消费者模式,松耦合
事件驱动 发布-订阅模式,完全解耦

二、核心概念

2.1 事件定义

java 复制代码
// 事件基类
public abstract class DomainEvent {
    private final String eventId;
    private final LocalDateTime occurredOn;
    
    protected DomainEvent() {
        this.eventId = UUID.randomUUID().toString();
        this.occurredOn = LocalDateTime.now();
    }
}

// 订单创建事件
public class OrderCreatedEvent extends DomainEvent {
    private final String orderId;
    private final String customerId;
    private final BigDecimal totalAmount;
    
    public OrderCreatedEvent(String orderId, String customerId, BigDecimal totalAmount) {
        super();
        this.orderId = orderId;
        this.customerId = customerId;
        this.totalAmount = totalAmount;
    }
}

2.2 事件流

复制代码
┌─────────┐    事件    ┌─────────┐    事件    ┌─────────┐
│ 生产者   │ ────────► │  通道   │ ────────► │ 消费者   │
└─────────┘           └─────────┘           └─────────┘
                           │
                           ▼
                      ┌─────────┐
                      │  存储   │
                      └─────────┘

三、事件模式

3.1 事件通知

java 复制代码
// 简单事件通知
@Service
public class OrderService {
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    public void createOrder(Order order) {
        // 业务逻辑
        orderRepository.save(order);
        
        // 发布事件
        eventPublisher.publishEvent(new OrderCreatedEvent(order));
    }
}

// 事件监听
@Component
public class NotificationListener {
    
    @EventListener
    public void onOrderCreated(OrderCreatedEvent event) {
        // 发送通知
        notificationService.send(event.getCustomerId(), "订单创建成功");
    }
}

3.2 事件溯源

java 复制代码
// 事件存储
public class EventStore {
    
    public void append(String aggregateId, List<DomainEvent> events) {
        events.forEach(event -> {
            EventEntry entry = new EventEntry(
                aggregateId,
                event.getClass().getName(),
                JSON.toJSONString(event),
                LocalDateTime.now()
            );
            eventRepository.save(entry);
        });
    }
    
    public List<DomainEvent> loadEvents(String aggregateId) {
        return eventRepository.findByAggregateId(aggregateId)
            .stream()
            .map(this::deserialize)
            .collect(Collectors.toList());
    }
}

// 聚合重建
public class Order {
    
    public static Order fromEvents(List<DomainEvent> events) {
        Order order = new Order();
        events.forEach(order::apply);
        return order;
    }
    
    private void apply(DomainEvent event) {
        if (event instanceof OrderCreatedEvent) {
            applyOrderCreated((OrderCreatedEvent) event);
        } else if (event instanceof OrderItemAddedEvent) {
            applyOrderItemAdded((OrderItemAddedEvent) event);
        }
    }
}

3.3 CQRS

复制代码
┌─────────────────────────────────────────────────────────────┐
│                    CQRS 架构                                │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Command Side (写)          Query Side (读)                │
│  ┌─────────┐                ┌─────────┐                    │
│  │ Command │                │  Query  │                    │
│  │ Handler │                │ Handler │                    │
│  └────┬────┘                └────┬────┘                    │
│       │                          │                         │
│       ▼                          ▼                         │
│  ┌─────────┐                ┌─────────┐                    │
│  │  Write  │                │  Read   │                    │
│  │  Model  │                │  Model  │                    │
│  └────┬────┘                └────┬────┘                    │
│       │                          │                         │
│       ▼                          ▼                         │
│  ┌─────────┐                ┌─────────┐                    │
│  │ Write DB│                │ Read DB │                    │
│  └─────────┘                └─────────┘                    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

四、技术选型

4.1 消息中间件对比

中间件 吞吐量 延迟 适用场景
Kafka 百万级 ms级 日志、大数据
RabbitMQ 万级 μs级 业务消息
RocketMQ 十万级 ms级 金融、交易
Pulsar 百万级 ms级 云原生

4.2 选型建议

复制代码
高吞吐、大数据 → Kafka
低延迟、可靠性 → RabbitMQ
金融级、事务 → RocketMQ
云原生、多租户 → Pulsar

五、代码实战

5.1 Spring Event

java 复制代码
// 事件定义
public class OrderPaidEvent extends ApplicationEvent {
    private final String orderId;
    private final BigDecimal amount;
    
    public OrderPaidEvent(Object source, String orderId, BigDecimal amount) {
        super(source);
        this.orderId = orderId;
        this.amount = amount;
    }
}

// 事件发布
@Service
public class OrderService {
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    public void payOrder(String orderId, BigDecimal amount) {
        // 业务逻辑
        orderRepository.updateStatus(orderId, OrderStatus.PAID);
        
        // 发布事件
        eventPublisher.publishEvent(new OrderPaidEvent(this, orderId, amount));
    }
}

// 事件监听
@Component
public class OrderEventListener {
    
    @EventListener
    @Async
    public void onOrderPaid(OrderPaidEvent event) {
        // 更新积分
        pointsService.addPoints(event.getOrderId(), event.getAmount());
        
        // 发送通知
        notificationService.sendOrderPaidNotification(event.getOrderId());
    }
}

5.2 Kafka 集成

java 复制代码
// 生产者配置
@Configuration
public class KafkaProducerConfig {
    
    @Bean
    public ProducerFactory<String, String> producerFactory() {
        Map<String, Object> config = new HashMap<>();
        config.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        config.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        config.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        return new DefaultKafkaProducerFactory<>(config);
    }
    
    @Bean
    public KafkaTemplate<String, String> kafkaTemplate() {
        return new KafkaTemplate<>(producerFactory());
    }
}

// 消费者配置
@Configuration
@EnableKafka
public class KafkaConsumerConfig {
    
    @Bean
    public ConsumerFactory<String, String> consumerFactory() {
        Map<String, Object> config = new HashMap<>();
        config.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
        config.put(ConsumerConfig.GROUP_ID_CONFIG, "order-group");
        config.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        config.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        return new DefaultKafkaConsumerFactory<>(config);
    }
}

// 消息发送
@Service
public class OrderEventPublisher {
    
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    
    public void publishOrderCreated(Order order) {
        String message = JSON.toJSONString(order);
        kafkaTemplate.send("order-created", order.getId(), message);
    }
}

// 消息消费
@Component
public class OrderEventConsumer {
    
    @KafkaListener(topics = "order-created", groupId = "inventory-group")
    public void handleOrderCreated(String message) {
        Order order = JSON.parseObject(message, Order.class);
        inventoryService.reserveStock(order);
    }
}

总结

事件驱动概述 :定义、特征、优势

核心概念 :事件、通道、存储

事件模式 :通知、溯源、CQRS

技术选型 :Kafka、RabbitMQ、RocketMQ

代码实战:Spring Event、Kafka 集成

本系列完结


作者 :刘~浪地球
系列 :架构设计(五)
更新时间:2026-04-10

相关推荐
G311354227310 小时前
如何用 QClaw 龙虾做一个规律作息健康助理 Agent
大数据·人工智能·ai·云计算
木雷坞10 小时前
K8s GPU 推理服务 ImagePullBackOff 排查与预热
云原生·容器·kubernetes·gpu算力
TG_yunshuguoji12 小时前
阿里云代理商:DeepSeek V4 vs GPT 系列 阿里云上的成本与性能新平衡
人工智能·阿里云·云计算·ai智能体·deepseek v4
byoass12 小时前
企业云盘数据备份与恢复策略:定时备份增量备份异地容灾实战
网络·安全·云计算
**蓝桉**12 小时前
阿里云存储服务
阿里云·云计算
AOwhisky14 小时前
Kubernetes调度与服务暴露:从“定时任务”到“服务发现”的完全指南
linux·运维·云原生·容器·kubernetes·服务发现
许彰午14 小时前
从双11到某省政务平台:信息系统架构的本质思考
系统架构·政务
Cyber4K14 小时前
【Kubernetes专项】温故而知新,重温技术原理(6)
云原生·容器·kubernetes
qq_4352879215 小时前
第7章 巫妖并起:中心化调度 vs 裸机硬件的架构对决?天庭与巫族的系统之争
架构·系统架构·天庭·巫族·中心化调度·裸机硬件·洪荒神话
ZStack开发者社区15 小时前
ZStack dGPU:让虚拟机里的 GPU 也能按需切分
云计算·gpu算力