架构设计--事件驱动架构设计与实现(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

相关推荐
鬼先生_sir2 小时前
Zookeeper:从入门到精通
分布式·zookeeper·云原生
Luke~2 小时前
阿里云计算巢已上架!3分钟部署 Loki AI 事故分析引擎,SRE 复盘时间直接砍掉 80%
人工智能·阿里云·云计算·loki·devops·aiops·sre
Database_Cool_2 小时前
基于PolarDB Mem0 为 OpenClaw 构建高效记忆系统(阿里云开发者)
阿里云·云计算
marsh02062 小时前
31 openclaw微服务架构实践:构建分布式系统
微服务·ai·云原生·架构·编程·技术
开心码农1号3 小时前
k8s中service和ingress的区别和使用
云原生·容器·kubernetes
面汤放盐3 小时前
《企业IT架构转型之道:阿里巴巴中台战略思想与架构实战》从业务痛点到架构革命,企业转型的底层逻辑(精华解读)
系统架构
光电大美美-见合八方中国芯5 小时前
用于无色波分复用光网络的 10.7 Gb/s 反射式电吸收调制器与半导体光放大器单片集成
网络·后端·ai·云计算·wpf·信息与通信·模块测试
wb1896 小时前
NoSQL数据库Redis集群重习
数据库·redis·笔记·云计算·nosql
AI精钢6 小时前
为何智能体需要 Dreaming 来优化记忆?
人工智能·云原生·aigc