Sofa版本5.6.1
如下List-1,是否enable即是否開啓eventBus是全局配置RpcConfig來控制的
事件event的subscribe是通過Map<Event,Set<Subscribe>>來存儲的
註冊一個訂閱者時,通過在map中新增<event,Subscribe>來實現
List-1
public class EventBus {
private static final Logger LOGGER = LoggerFactory.getLogger(EventBus.class);
/**
* 是否允許攜帶上下文附件,關閉後只能傳遞"."開頭的key,"_" 開頭的Key將不被保持和傳遞。<br>
* 在性能測試等場景可能關閉此傳遞功能。
*/
private static final boolean EVENT_BUS_ENABLE = RpcConfigs.getBooleanValue(RpcOptions.EVENT_BUS_ENABLE);
/**
* 是否開啓事件總線功能
*
* @return 是否開啓事件總線功能
*/
public static boolean isEnable() {
return EVENT_BUS_ENABLE;
}
/**
* 是否開啓事件總線功能
*
* @param eventClass 事件類型
* @return 是否開啓事件總線功能
*/
public static boolean isEnable(Class<? extends Event> eventClass) {
return EVENT_BUS_ENABLE && CommonUtils.isNotEmpty(SUBSCRIBER_MAP.get(eventClass));
}
/**
* 某中事件的訂閱者
*/
private final static ConcurrentMap<Class<? extends Event>, CopyOnWriteArraySet<Subscriber>> SUBSCRIBER_MAP = new ConcurrentHashMap<Class<? extends Event>, CopyOnWriteArraySet<Subscriber>>();
/**
* 註冊一個訂閱者
*
* @param eventClass 事件類型
* @param subscriber 訂閱者
*/
public static void register(Class<? extends Event> eventClass, Subscriber subscriber) {
CopyOnWriteArraySet<Subscriber> set = SUBSCRIBER_MAP.get(eventClass);
if (set == null) {
set = new CopyOnWriteArraySet<Subscriber>();
CopyOnWriteArraySet<Subscriber> old = SUBSCRIBER_MAP.putIfAbsent(eventClass, set);
if (old != null) {
set = old;
}
}
set.add(subscriber);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Register subscriber: {} of event: {}.", subscriber, eventClass);
}
}
/**
* 反註冊一個訂閱者
*
* @param eventClass 事件類型
* @param subscriber 訂閱者
*/
public static void unRegister(Class<? extends Event> eventClass, Subscriber subscriber) {
CopyOnWriteArraySet<Subscriber> set = SUBSCRIBER_MAP.get(eventClass);
if (set != null) {
set.remove(subscriber);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("UnRegister subscriber: {} of event: {}.", subscriber, eventClass);
}
}
}
通過event獲取subscribe集合,遍歷subscribe集合,首先判斷是否是異步的,如果不是則直接調用subscriber.event,如果是異步的,那麼在線程池中執行,如果線程池隊列滿了,則拋出reject異常。
List-2
public static void post(final Event event) {
if (!isEnable()) {
return;
}
CopyOnWriteArraySet<Subscriber> subscribers = SUBSCRIBER_MAP.get(event.getClass());
if (CommonUtils.isNotEmpty(subscribers)) {
for (final Subscriber subscriber : subscribers) {
if (subscriber.isSync()) {
handleEvent(subscriber, event);
} else { // 異步
final RpcInternalContext context = RpcInternalContext.peekContext();
final ThreadPoolExecutor asyncThreadPool = AsyncRuntime.getAsyncThreadPool();
try {
asyncThreadPool.execute(
new Runnable() {
@Override
public void run() {
try {
RpcInternalContext.setContext(context);
handleEvent(subscriber, event);
} finally {
RpcInternalContext.removeContext();
}
}
});
} catch (RejectedExecutionException e) {
LOGGER
.warn("This queue is full when post event to async execute, queue size is " +
asyncThreadPool.getQueue().size() +
", please optimize this async thread pool of eventbus.");
}
}
}
}
}
private static void handleEvent(final Subscriber subscriber, final Event event) {
try {
subscriber.onEvent(event);
} catch (Throwable e) {
if (LOGGER.isWarnEnabled()) {
LOGGER.warn("Handle " + event.getClass() + " error", e);
}
}
}
像統計請求,或者其他tracer或者metrics都是通過EventBus來實現的。