目录
实现方式更优的发布者(NamingEventPublisher)
学习目标: 了解什么是共享发布者,跟DefaultPublisher有什么区别,它有哪些实现类。
DefaultSharePublisher
从代码中可以看出DefaultSharePublisher 的逻辑跟上一节的DefaultPublisher 的区别和联系
区别:
1、 DefaultPublisher 是针对Event类型 而DefaultSharePublisher只针对SlowEvent
2、DefaultPublisher 只能处理单个事件 而DefaultSharePublisher可以管理N个事件
第二点是最核心的区别
联系:DefaultSharePublisher继承自DefaultPublisher, 但不能当DefaultPublisher使用,场景差异很大。
public class DefaultSharePublisher extends DefaultPublisher implements ShardedEventPublisher {
//每个事件类型一个set集合的Subscriber
private final Map<Class<? extends SlowEvent>, Set<Subscriber>> subMappings = new ConcurrentHashMap<>();
//锁再这里有必要吗?大家觉得呢?
private final Lock lock = new ReentrantLock();
@Override
public void addSubscriber(Subscriber subscriber, Class<? extends Event> subscribeType) {
//意味着该类之处理 SlowEvent 事件
Class<? extends SlowEvent> subSlowEventType = (Class<? extends SlowEvent>)
subscribeType;
subscribers.add(subscriber);
lock.lock();
try {
//如果找不到该事件类型的订阅者列表就new一个空集合
//这里大家思考以下如果不加锁是否也可以?
Set<Subscriber> sets = subMappings.get(subSlowEventType);
if (sets == null) {
Set<Subscriber> newSet = new ConcurrentHashSet<Subscriber>();
newSet.add(subscriber);
subMappings.put(subSlowEventType, newSet);
return;
}
sets.add(subscriber);
} finally {
lock.unlock();
}
}
//同添加操作只是这里是删除
@Override
public void removeSubscriber(Subscriber subscriber, Class<? extends Event>
subscribeType) {
Class<? extends SlowEvent> subSlowEventType = (Class<? extends SlowEvent>)
subscribeType;
subscribers.remove(subscriber);
lock.lock();
try {
Set<Subscriber> sets = subMappings.get(subSlowEventType);
if (sets != null) {
sets.remove(subscriber);
}
} finally {
lock.unlock();
}
}
//重写父类的事件处理方法
@Override
public void receiveEvent(Event event) {
final long currentEventSequence = event.sequence();
//该事件的得到订阅者集合
final Class<? extends SlowEvent> slowEventType = (Class<? extends SlowEvent>)
event.getClass();
Set<Subscriber> subscribers = subMappings.get(slowEventType);
if (null == subscribers) {
LOGGER.debug("[NotifyCenter] No subscribers for slow event {}", slowEventType.getName());
return;
}
// 通知集合中每一个订阅者
for (Subscriber subscriber : subscribers) {
// Whether to ignore expiration events
if (subscriber.ignoreExpireEvent() && lastEventSequence >
currentEventSequence) {
continue;
}
//执行父类的通知方法
notifySubscriber(subscriber, event);
}
}
}
uml 类图
实现方式更优的发布者(NamingEventPublisher)
NamingEventPublisher代码是DefaultPublisher 和 DefaultSharedEventPublisher的集合
并且摒弃了DefaultSharedEventPublisher里面一些不太好的写法。
这个类结构功能更清晰。不过NamingEventPublisher处理逻辑中没有了事件顺序号校验。
public class NamingEventPublisher extends Thread implements ShardedEventPublisher {
private static final String THREAD_NAME = "naming.publisher-";
private static final int DEFAULT_WAIT_TIME = 60;
private final Map<Class<? extends Event>, Set<Subscriber<? extends Event>>>
subscribes = new ConcurrentHashMap<>();
private volatile boolean initialized = false;
private volatile boolean shutdown = false;
private int queueMaxSize = -1;
private BlockingQueue<Event> queue;
private String publisherName;
@Override
public void init(Class<? extends Event> type, int bufferSize) {
this.queueMaxSize = bufferSize;
this.queue = new ArrayBlockingQueue<>(bufferSize);
this.publisherName = type.getSimpleName();
super.setName(THREAD_NAME + this.publisherName);
super.setDaemon(true);
super.start();
initialized = true;
}
@Override
public long currentEventSize() {
return this.queue.size();
}
@Override
public void addSubscriber(Subscriber subscriber) {
addSubscriber(subscriber, subscriber.subscribeType());
}
@Override
public void addSubscriber(Subscriber subscriber, Class<? extends Event>
subscribeType) {
subscribes.computeIfAbsent(subscribeType, inputType -> new ConcurrentHashSet<>
());
subscribes.get(subscribeType).add(subscriber);
}
@Override
public void removeSubscriber(Subscriber subscriber) {
removeSubscriber(subscriber, subscriber.subscribeType());
}
@Override
public void removeSubscriber(Subscriber subscriber, Class<? extends Event>
subscribeType) {
subscribes.computeIfPresent(subscribeType, (inputType, subscribers) -> {
subscribers.remove(subscriber);
return subscribers.isEmpty() ? null : subscribers;
});
}
@Override
public boolean publish(Event event) {
checkIsStart();
boolean success = this.queue.offer(event);
if (!success) {
handleEvent(event);
return true;
}
return true;
}
@Override
public void notifySubscriber(Subscriber subscriber, Event event) {
final Runnable job = () -> subscriber.onEvent(event);
final Executor executor = subscriber.executor();
if (executor != null) {
executor.execute(job);
} else {
try {
job.run();
} catch (Throwable e) {
Loggers.EVT_LOG.error("Event callback exception: ", e);
}
}
}
@Override
public void shutdown() throws NacosException {
this.shutdown = true;
this.queue.clear();
}
@Override
public void run() {
try {
waitSubscriberForInit();
handleEvents();
} catch (Exception e) {
...
}
}
private void waitSubscriberForInit() {
for (int waitTimes = DEFAULT_WAIT_TIME; waitTimes > 0; waitTimes--) {
if (shutdown || !subscribes.isEmpty()) {
break;
}
ThreadUtils.sleep(1000L);
}
}
private void handleEvents() {
while (!shutdown) {
try {
final Event event = queue.take();
handleEvent(event);
} catch (InterruptedException e) {
....
}
}
}
private void handleEvent(Event event) {
Class<? extends Event> eventType = event.getClass();
Set<Subscriber<? extends Event>> subscribers = subscribes.get(eventType);
.....
return;
}
for (Subscriber subscriber : subscribers) {
notifySubscriber(subscriber, event);
}
}
void checkIsStart() {
if (!initialized) {
throw new IllegalStateException("Publisher does not start");
}
}
public String getStatus() {
return String.format("Publisher %-30s: shutdown=%5s, queue=%7d/%-7d",
publisherName, shutdown, currentEventSize(), queueMaxSize);
}
}
为什么NamingEventPubliser 别DefaultSharePublisher实现更优秀呢
首先去掉了 lock 的代码。
其次并没有集成DefaultPublisher的鸡肋集成方式。而是重新实现了其中addSubscriber和removeSubscriber 。
总结
本节讲解了两种类型共享发布者实现,并简单比较了2种实现的区别。代码相似度都很高,所以应该很容易理解。