开始之前先简要阐述一下事件通知的大致流程:
比如现在是一个服务注册的事件client端(也就是你的服务)通过调用nacos服务的接口,这个时候,nacos就会通过触发NotifyCenter的事件发布方法,此后,会有一个对应这个服务注册事件的事件发布者EventPublisher来对当前事件进行一个广播操作,广播给注册上了这个事件发布者的订阅者们(Subscriber)。这里一共出现了三个重要的类,一是消息通知中心NotifyCente,二是消息发布者EventPublisher,三是事件订阅者Subscriber,本篇主要是简要梳理流程,其源码会在后续篇章中剖析

先看看事件通知的核心类:NotifyCenter

  1. // 通过 NotifyCenter 来发布一些消息,如服务注册,服务断线等等
  2. public class NotifyCenter {
  3. // 单例
  4. private static final NotifyCenter INSTANCE = new NotifyCenter();
  5. // key为Event抽象类的子类,我理解为一个事件,
  6. // 这些values均为 DefaultPublisher/NamingEventPublisher 均实现 EventPublisher 和 Closeable (shutdown方法)
  7. private final Map<String, EventPublisher> publisherMap = new ConcurrentHashMap<>(16);
  8. // ignore ..
  9. }

谈谈我对publisherMap的理解:
key:

  • 是事件类的class全限定类名(如com.alibaba.nacos.naming.core.v2.event.client.ClientEvent.ClientDisconnectEvent)

value:

  • 是一个 EventPublisher接口(两个实现DefaultPublisher/NamingEventPublisher的实现
  • 简单来说就是一个发布者

map:

  • k-v 就是一个事件->发布者
  • NotifyCenter 通过 ConcurrentHashMap 来保存一个事件以及发布者来调用该事件所对应的发布者的相关方法
  • 事件我们可以理解为一个事件(虽然是废话),简单的理解比如一个服务注销的事件

接下来详细看看EventPublisher的结构

  1. private final Map<Class<? extends Event>, Set<Subscriber<? extends Event>>> subscribes = new ConcurrentHashMap<>();
  2. private BlockingQueue<Event> queue;

就掏了两个参数出来唠嗑一下
queue:

  • 显而易见,阻塞队列,用来存储事件对象

subscribes:

  • 同样也是一个map
  • key是一个事件的Class
  • value是一个一组订阅了该事件的Set集合,也就是订阅者集合

既然新冒出来了个Subscriber,那么索性看看

  1. public abstract class Subscriber<T extends Event> {
  2. public abstract void onEvent(T event);
  3. // ignore others .....
  4. }

核心方法就是 onEvent 方法

  • 就是订阅者的onEvent方法接受一个事件入参,然后进行它的逻辑处理

刚刚出现的这几个类都离不开一个类,那就是Event

  1. public abstract class Event implements Serializable {
  2. private static final AtomicLong SEQUENCE = new AtomicLong(0);
  3. private final long sequence = SEQUENCE.getAndIncrement();
  4. /**
  5. * 事件序列号,可用于处理事件的序列
  6. * Event sequence number, which can be used to handle the sequence of events.
  7. * @return sequence num, It's best to make sure it's monotone.
  8. */
  9. public long sequence() {
  10. return sequence;
  11. }
  12. }

也就相当于一个标记类,并没有什么具体的实现,其实现包含了这个事件的一些携带信息,比如ClientOperationEvent,里面包含了这个事件的一些信息,在订阅者监听到这个事件的时候,就能交给订阅者进行处理

上面的核心代码尽量留个印象,留意那几个关键类和字段,接下来过一过事件通知的流转过程

事件通知核心流程 - 图1

图画的可能不太好,先简要描述一下吧:

  1. 比如一个服务注册事件,调用NotifyCenter的静态方法开始发布一个事件,想要通过通知中心发布一个服务注册的消息
  2. 该事件对应一些发布者,这时候会去map里面找这个事件的发布者
  3. 这个事件发布者呢,他有一个阻塞队列queue,专门用来存储事件的
  4. 同时这个发布者也是一个线程,作为一个发布者的同时,也是作为一个线程被保存在NotifyCenter的map里面
  5. 发布者这个线程呢,会不断的从queue里面取事件
  6. 发布者取出事件后,会从它内部的一个map里面找到这个事件的所有的订阅者,并判断这个订阅者是需要同步还是异步通知,这里的代码会在事件发布者篇详细阐述!!

至此,NotifyCenter已经光荣的完成了它的事件通知功能
接着细化NotifyCenter,EventPublisher,Subscriber这三个核心大接口