【架构实战】观察者模式在分布式系统中的应用

一、观察者模式概述

观察者模式(Observer Pattern)是一种行为型设计模式:

核心思想:

  • 定义对象间一对多的依赖关系
  • 当一个对象状态变化时,所有依赖它的对象都会收到通知
  • 实现松耦合,被观察者和观察者可以独立变化

解决的问题:

  • 分布式系统中的事件通知
  • 服务间的异步通信
  • 状态同步问题
  • 业务解耦

二、模式结构

1. 基本结构

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                      观察者模式                                   │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌──────────────────┐                   ┌──────────────────┐    │
│  │    观察者接口     │◀────────────────│   Subject接口    │    │
│  │   (Observer)    │     register     │   (Subject)     │    │
│  └──────────────────┘     remove      └────────┬─────────┘    │
│          △                       notify        │                │
│          │                                     │                │
│          │         ┌──────────────────┐        │                │
│          └────────│  具体观察者1      │        │                │
│                    │ ConcreteObserver │────────┘                │
│                    └──────────────────┘                         │
│                                                                  │
│          ┌──────────────────┐                                  │
│          │  具体观察者2      │                                  │
│          │ ConcreteObserver │                                  │
│          └──────────────────┘                                  │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

2. Java实现

java 复制代码
// 观察者接口
public interface Observer<T> {
    void update(T event);
}

// 被观察者接口
public interface Subject<T> {
    void attach(Observer<T> observer);
    void detach(Observer<T> observer);
    void notify(T event);
}

// 具体被观察者
public class Observable<T> implements Subject<T> {
    
    private final List<Observer<T>> observers = new CopyOnWriteArrayList<>();
    
    @Override
    public void attach(Observer<T> observer) {
        observers.add(observer);
    }
    
    @Override
    public void detach(Observer<T> observer) {
        observers.remove(observer);
    }
    
    @Override
    public void notify(T event) {
        observers.forEach(observer -> {
            try {
                observer.update(event);
            } catch (Exception e) {
                // 观察者执行异常不影响其他观察者
                log.error("观察者执行异常", e);
            }
        });
    }
}

三、分布式观察者模式

1. 事件总线架构

复制代码
┌─────────────────────────────────────────────────────────────────┐
│                      分布式事件总线                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌─────────┐    ┌─────────┐    ┌─────────┐    ┌─────────┐    │
│  │ 服务A   │───▶│  消息   │───▶│ 消息总线 │───▶│ 服务B   │    │
│  │(发布者)│    │ 队列    │    │(Kafka)  │    │(订阅者) │    │
│  └─────────┘    └─────────┘    └─────────┘    └─────────┘    │
│                                              ▲                  │
│  ┌─────────┐    ┌─────────┐                 │                  │
│  │ 服务C   │───▶│  消息   │─────────────────┘                  │
│  │(发布者)│    │  队列    │                                    │
│  └─────────┘    └─────────┘                                    │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

2. Spring事件机制

java 复制代码
// 定义领域事件
public class OrderCreatedEvent extends ApplicationEvent {
    
    private final Order order;
    private final String eventId;
    
    public OrderCreatedEvent(Object source, Order order) {
        super(source);
        this.order = order;
        this.eventId = UUID.randomUUID().toString();
    }
    
    public Order getOrder() {
        return order;
    }
    
    public String getEventId() {
        return eventId;
    }
}

// 发布事件
@Service
public class OrderService {
    
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    
    public Order createOrder(OrderRequest request) {
        Order order = orderRepository.save(createOrder(request));
        
        // 发布事件
        eventPublisher.publishEvent(new OrderCreatedEvent(this, order));
        
        return order;
    }
}

// 监听事件
@Component
public class OrderEventListener {
    
    @Autowired
    private NotificationService notificationService;
    
    @Autowired
    private InventoryService inventoryService;
    
    // 订单创建后发送通知
    @EventListener
    @Async
    public void handleOrderCreated(OrderCreatedEvent event) {
        Order order = event.getOrder();
        
        notificationService.sendOrderCreatedNotification(order.getCustomerId());
    }
    
    // 订单创建后扣减库存
    @EventListener
    @Order(1)
    public void handleOrderCreatedForInventory(OrderCreatedEvent event) {
        Order order = event.getOrder();
        
        for (OrderItem item : order.getItems()) {
            inventoryService.deductStock(item.getProductId(), item.getQuantity());
        }
    }
}

3. 条件监听

java 复制代码
// 条件监听
@Component
public class OrderStatusListener {
    
    // 只监听已支付状态
    @EventListener(condition = "#event.status == 'PAID'")
    public void handlePaidOrder(OrderStatusChangedEvent event) {
        // 触发后续流程
        triggerShippingProcess(event.getOrderId());
    }
    
    // 只监听VIP客户
    @EventListener(condition = "#event.customer.vip == true")
    public void handleVipOrder(OrderCreatedEvent event) {
        // VIP客户特殊处理
        sendVipGift(event.getOrder());
    }
}

四、消息队列实现

1. Kafka事件总线

java 复制代码
// Kafka事件发布
@Service
public class KafkaEventPublisher {
    
    @Autowired
    private KafkaTemplate<String, Object> kafkaTemplate;
    
    public void publish(String topic, DomainEvent event) {
        kafkaTemplate.send(topic, event.getEventId(), event)
            .whenComplete((result, ex) -> {
                if (ex != null) {
                    log.error("事件发布失败: topic={}, eventId={}", topic, event.getEventId(), ex);
                } else {
                    log.info("事件发布成功: topic={}, eventId={}, partition={}", 
                        topic, event.getEventId(), result.getRecordMetadata().partition());
                }
            });
    }
}

// Kafka事件订阅
@Component
public class OrderKafkaListener {
    
    @KafkaListener(topics = "order-events", groupId = "order-service")
    public void handleOrderEvent(ConsumerRecord<String, OrderEvent> record) {
        OrderEvent event = record.value();
        
        log.info("收到订单事件: eventId={}, type={}", event.getEventId(), event.getType());
        
        switch (event) {
            case OrderCreatedEvent created -> handleOrderCreated(created);
            case OrderPaidEvent paid -> handleOrderPaid(paid);
            case OrderCancelledEvent cancelled -> handleOrderCancelled(cancelled);
        }
    }
}

2. RocketMQ事件

java 复制代码
// RocketMQ事务事件
@Service
public class RocketMQTransactionPublisher {
    
    @Autowired
    private TransactionMQProducer producer;
    
    public void publishOrderEvent(Order order) {
        Message message = new Message("order-topic", JSON.toJSONString(order).getBytes());
        
        producer.sendMessageInTransaction(message, (msg, arg) -> {
            // 执行本地事务
            orderRepository.save((Order) arg);
            return LocalTransactionState.COMMIT_MESSAGE;
        }, order);
    }
}

// RocketMQ监听
@Component
public class OrderTransactionListener implements TransactionListener {
    
    @Override
    public LocalTransactionState executeLocalTransaction(Message msg, Object arg) {
        try {
            Order order = JSON.parseObject(new String(msg.getBody()), Order.class);
            orderRepository.save(order);
            return LocalTransactionState.COMMIT_MESSAGE;
        } catch (Exception e) {
            return LocalTransactionState.ROLLBACK_MESSAGE;
        }
    }
    
    @Override
    public LocalTransactionState checkLocalTransaction(MessageExt msg) {
        return LocalTransactionState.COMMIT_MESSAGE;
    }
}

五、观察者模式变体

1. 异步观察者

java 复制代码
// 异步观察者实现
public class AsyncObserver<T> implements Observer<T> {
    
    private final ExecutorService executor;
    private final Observer<T> delegate;
    
    public AsyncObserver(Observer<T> delegate, ExecutorService executor) {
        this.delegate = delegate;
        this.executor = executor;
    }
    
    @Override
    public void update(T event) {
        executor.submit(() -> {
            try {
                delegate.update(event);
            } catch (Exception e) {
                log.error("异步观察者执行异常", e);
            }
        });
    }
}

// 异步事件发布
@Service
public class AsyncEventPublisher {
    
    private final ExecutorService executor = Executors.newCachedThreadPool();
    
    public <T> void publishAsync(DomainEvent event) {
        CompletableFuture.runAsync(() -> publish(event), executor);
    }
}

2. 优先级观察者

java 复制代码
// 优先级观察者
public class PriorityObserver<T> implements Observer<T>, Comparable<PriorityObserver<T>> {
    
    private final int priority;
    private final Observer<T> observer;
    
    public PriorityObserver(Observer<T> observer, int priority) {
        this.observer = observer;
        this.priority = priority;
    }
    
    @Override
    public void update(T event) {
        observer.update(event);
    }
    
    @Override
    public int compareTo(PriorityObserver<T> o) {
        return Integer.compare(o.priority, this.priority); // 优先级高的先执行
    }
}

// 带优先级的被观察者
public class PriorityObservable<T> implements Subject<T> {
    
    private final List<PriorityObserver<T>> observers = new ArrayList<>();
    
    @Override
    public void attach(Observer<T> observer) {
        attach(observer, 0);
    }
    
    public void attach(Observer<T> observer, int priority) {
        observers.add(new PriorityObserver<>(observer, priority));
        observers.sort(null);
    }
    
    @Override
    public void notify(T event) {
        observers.forEach(o -> o.update(event));
    }
}

3. 可撤销观察者

java 复制代码
// 可撤销观察者
public class ObservableWithTimeout<T> implements Subject<T> {
    
    private final List<Observer<T>> observers = new CopyOnWriteArrayList<>();
    private final Map<Observer<T>, Long> attachTimes = new ConcurrentHashMap<>();
    private final long timeoutMs;
    
    public ObservableWithTimeout(long timeoutMs) {
        this.timeoutMs = timeoutMs;
    }
    
    @Override
    public void attach(Observer<T> observer) {
        observers.add(observer);
        attachTimes.put(observer, System.currentTimeMillis());
        
        // 注册超时清理
        scheduleCleanup(observer);
    }
    
    private void scheduleCleanup(Observer<T> observer) {
        CompletableFuture.delayedExecutor(timeoutMs, TimeUnit.MILLISECONDS)
            .execute(() -> {
                Long attachTime = attachTimes.get(observer);
                if (attachTime != null && 
                    System.currentTimeMillis() - attachTime > timeoutMs) {
                    detach(observer);
                    log.warn("观察者超时自动移除");
                }
            });
    }
}

六、实战案例

1. 订单状态变更通知

java 复制代码
// 订单被观察者
@Service
public class OrderSubject {
    
    private final List<OrderObserver> observers = new CopyOnWriteArrayList<>();
    
    public void attach(OrderObserver observer) {
        observers.add(observer);
    }
    
    public void detach(OrderObserver observer) {
        observers.remove(observer);
    }
    
    public void notifyObservers(Order order, OrderEvent event) {
        observers.forEach(observer -> {
            try {
                observer.onOrderEvent(order, event);
            } catch (Exception e) {
                log.error("通知观察者失败", e);
            }
        });
    }
}

// 订单观察者接口
public interface OrderObserver {
    void onOrderEvent(Order order, OrderEvent event);
}

// 库存观察者
@Component
public class InventoryOrderObserver implements OrderObserver {
    
    @Override
    public void onOrderEvent(Order order, OrderEvent event) {
        switch (event) {
            case OrderEvent.CREATED -> handleOrderCreated(order);
            case OrderEvent.PAID -> handleOrderPaid(order);
            case OrderEvent.CANCELLED -> handleOrderCancelled(order);
        }
    }
    
    private void handleOrderCreated(Order order) {
        // 预占库存
        inventoryService.reserveStock(order.getItems());
    }
}

// 通知观察者
@Component
public class NotificationOrderObserver implements OrderObserver {
    
    @Autowired
    private NotificationService notificationService;
    
    @Override
    public void onOrderEvent(Order order, OrderEvent event) {
        switch (event) {
            case OrderEvent.CREATED -> {
                notificationService.notifyCustomer("订单已创建: " + order.getOrderNo());
            }
            case OrderEvent.PAID -> {
                notificationService.notifyCustomer("订单已支付: " + order.getOrderNo());
            }
            case OrderEvent.SHIPPED -> {
                notificationService.notifyCustomer("订单已发货: " + order.getOrderNo());
            }
        }
    }
}

2. 配置变更监听

java 复制代码
// 配置变更监听
@Component
public class ConfigObserver {
    
    private final Map<String, Consumer<String>> listeners = new ConcurrentHashMap<>();
    
    public void register(String key, Consumer<String> listener) {
        listeners.put(key, listener);
    }
    
    public void notifyChange(String key, String newValue) {
        Consumer<String> listener = listeners.get(key);
        if (listener != null) {
            listener.accept(newValue);
        }
    }
}

// 使用示例
@Configuration
public class CacheConfig {
    
    @Autowired
    private ConfigObserver configObserver;
    
    @PostConstruct
    public void init() {
        configObserver.register("cache.ttl", newValue -> {
            // 动态更新缓存TTL
            updateCacheTTL(Integer.parseInt(newValue));
        });
    }
}

七、分布式注意事项

1. 事件幂等

java 复制代码
// 幂等处理
@Component
public class IdempotentEventHandler {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    public boolean isProcessed(String eventId) {
        return Boolean.TRUE.equals(redisTemplate.hasKey("processed:" + eventId));
    }
    
    public void markProcessed(String eventId) {
        redisTemplate.opsForValue().set("processed:" + eventId, "1", 24, TimeUnit.HOURS);
    }
}

// 事件监听器
@Service
public class OrderEventService {
    
    @Autowired
    private IdempotentEventHandler idempotentHandler;
    
    @KafkaListener(topics = "order-events")
    public void handleOrderEvent(OrderEvent event) {
        // 幂等检查
        if (idempotentHandler.isProcessed(event.getEventId())) {
            return;
        }
        
        try {
            processEvent(event);
            idempotentHandler.markProcessed(event.getEventId());
        } catch (Exception e) {
            log.error("处理事件失败", e);
        }
    }
}

2. 事件顺序

java 复制代码
// 保证顺序处理
@Service
public class OrderedEventProcessor {
    
    private final Map<String, AtomicInteger> processedVersions = new ConcurrentHashMap<>();
    
    public void process(OrderEvent event) {
        String key = event.getAggregateId();
        
        AtomicInteger expectedVersion = processedVersions.computeIfAbsent(
            key, k -> new AtomicInteger(0));
        
        synchronized (expectedVersion) {
            if (event.getVersion() != expectedVersion.get() + 1) {
                // 事件顺序不对,等待重试
                throw new OutOfOrderException("期望版本" + (expectedVersion.get() + 1) 
                    + ",实际版本" + event.getVersion());
            }
            
            doProcess(event);
            expectedVersion.incrementAndGet();
        }
    }
}

3. 事件丢失处理

java 复制代码
// 定时对账
@Component
public class EventReconciliation {
    
    @Scheduled(fixedDelay = 60000)
    public void reconcile() {
        // 检查事件处理情况
        List<String> pendingEventIds = eventStore.findPendingEvents();
        
        for (String eventId : pendingEventIds) {
            DomainEvent event = eventStore.findById(eventId);
            if (event != null && isTimeout(event)) {
                // 超时事件重新处理
                reprocessEvent(event);
            }
        }
    }
}

八、总结

观察者模式在分布式系统中的价值:

  • 松耦合:发布者和订阅者解耦
  • 异步通信:非阻塞事件通知
  • 可扩展:方便添加新的观察者
  • 分布式支持:通过消息队列实现

最佳实践:

  1. 做好事件幂等处理
  2. 注意事件顺序问题
  3. 实现超时重试机制
  4. 监控事件处理情况

个人观点,仅供参考

相关推荐
skilllite作者1 小时前
从“记忆”到“项目 Wiki”:我在 SkillLite 里实现了一套 Markdown-only LLM Wiki 自动维护机制
开发语言·jvm·人工智能·后端·架构·rust
littleM2 小时前
深度拆解 HermesAgent(六):研究功能与测试体系
开发语言·人工智能·python·架构·ai编程
车载诊断技术2 小时前
在工作中如何保持奋斗的动力?
网络·架构·汽车·电子电气架构·ecu 诊断 diag
geovindu2 小时前
go: Observer Pattern
开发语言·观察者模式·设计模式·golang
奇逍科技圈2 小时前
开源架构 + BC 一体化:批发零售企业订货系统源码重构增长新路径
后端·架构·开源
littleM2 小时前
深度拆解 HermesAgent(七):CLI、安全与部署实践指南
人工智能·安全·架构
面汤放盐2 小时前
架构对比:单体架构与微服务架构
微服务·云原生·架构
iwS2o90XT2 小时前
微服务架构设计:Spring Cloud Gateway与Nacos集成
微服务·云原生·架构
喜欢流萤吖~3 小时前
分布式事务:微服务的数据一致性之困
分布式·微服务·架构