Sofa之EventBus

    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來實現的。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章