alibaba / Sentinel

A powerful flow control component enabling reliability, resilience and monitoring for microservices. (面向云原生微服务的高可用流控防护组件)
https://sentinelguard.io/
Apache License 2.0
22.44k stars 8.03k forks source link

Proposal about sentinel event design #3451

Open Daydreamer-ia opened 2 months ago

Daydreamer-ia commented 2 months ago

Hi, 社区的老师们好!我是OSPP的参与者。议题是构建统一的 Sentinel 事件体系,我的方案如下,如果有设计不合理或优化点,还望老师们批评指正!

导师:@LearningGp

背景

Sentinel 作为面向分布式、多语言异构化服务架构的流量治理组件,它的可观测体系很大程度上会影响用户对于规则的配置的合理性进而影响到实际的防护效果。Sentinel 中存在很多状态的转换,例如,限流状态的转换、熔断器状态的转换、自适应算法状态的转换、规则状态的转换等。这些状态转换中有些没有事件机制,有些有着独立的事件机制,导致用户没有合适的方式来同时监听、处理这些事件。所以需要构建一个统一的可扩展的事件体系来支撑这些状态转化以及其他功能模块的事件需求。同时在该事件体系的基础上,需要具备对接开源生态的能力。

设计概述

整体设计

image-20240922195627554

SentinelEventListener

事件监听器以集合的方式被维护在 SentinelEventListenerRegistry 当中,负责进行事件的具体处理,主要操作入口为 SentinelEventBusaddListener 静态方法。

public abstract class SentinelEventListener {
    /**
    * 触发事件
    *
    * @param event 事件信息
    */
    void onEvent(SentinelEvent event);
    /**
    * 监听的事件类型
    */
    List<Class<? extends SentinelEvent>> eventType();
    /**
    * 当前监听器是否异步处理该事件
    */
    public Executor executor() {
        return null;
    }
    /**
    * 是否永远处理最新的事件, 忽略过期事件
    */
    public boolean alwaysLast() {
        return false;
    }
    /**
    * 监听器优先级
    * 数字越小, 优先级越高
    */
    public int order() {
        return Integer.MAX_VALUE;
    }
}

SentinelEventListenerRegistry

统一存储事件监听器,定义如何维护和组织监听器逻辑,被组合在 SentinelEventBusSentinelEventMulticaster 中,一个 Sentinel 应用只会有一个 SentinelEventListenerRegistry

public interface SentinelEventListenerRegistry {
    // 初始化事件广播器
    void init(Properties properties);
    // 在应用关闭时进行回调销毁
    void destory();
    // 添加事件监听器
    void addSubscriber(SentinelEventListener listener);
    // 移除事件监听器
    void removeSubscriber(SentinelEventListener listener);
    // 获取监听某个事件的所有监听器
    List<SentinelEventListener> getSentinelEventListener(SentinelEvent event);
}

SentinelEvent

作为事件信息的载体,支持被自定义继承,通过 SentinelEventBus 提供的 publishEvent 静态方法,进行事件发布。

public abstract class SentinelEvent {
    // 事件序号, 用于辨别过期事件
    private static final AtomicLong SEQUENCE = new AtomicLong(0);
    private final long sequence = SEQUENCE.getAndIncrement();
}

SentinelEventMulticaster

事件广播器作为整个事件驱动模型的核心,定义如何回调监听器,通过 SentinelEventMulticasterFactory 事件广播器工厂构建和维护。

public interface SentinelEventMulticaster extends Closeable {
    // 初始化事件广播器
    void init(Properties properties, SentinelEventListenerRegistry registry);
    // 在应用关闭时进行回调销毁
    void destory();
    // 回调监听器, 返回事件是否通知成功
    boolean publish(SentinelEvent event);
}

SentinelEventMulticasterFactory

事件广播器工厂,负责维护事件以及广播器的映射关系。 主要完成的内容有:

public interface SentinelEventMulticasterFactory {
    // 初始化接口
    void init(Properties properties);
    // 销毁接口
    void destory();
    // 获取负责某个事件的广播器
    SentinelEventMulticaster getSentinelEventMulticaster(SentinelEvent event);
    // 添加事件和某个广播器的映射关系
    boolean addSentinelEventMulticaster(Class<? extends SentinelEvent> clazz, SentinelEventMulticaster multicaster);
    // 移除某个事件的广播器
    boolean removeSentinelEventMulticaster(Class<? extends SentinelEvent> clazz);
}

SentinelEventBus

该类作为核心类,负责维护事件类型以及广播器的映射关系,并提供静态方法,用于为外界提供任意位置都可以操作的入口。 主要提供静态方法有:

public class SentinelEventBus {
    // 维护事件-广播器映射关系
    private Map<String, SentinelEventMulticaster> multicaster;
    private static final SentinelEventBus INSTANCE = new SentinelEventBus();
    private SentinelEventBus() {
    // 初始化操作, 构建默认的
    }
    public void publish(SentinelEvent event) {
    ...
    }
    ...
}

SentinelEventFreqLimiter

负责针对事件进行频率控制,防止出现事件爆炸。

public interface SentinelEventFreqLimiter {
    boolean shouldHandle(SentinelEvent event);
}

Sentinel 接入

image-20240922213746630

使用拓展

初期计划支持事件

以下事件在触发后,均会以 json 格式写入 event.log 文件中。

image

Hi, all! I am a participant in OSPP. The topic is to build a unified Sentinel event system. My proposal is as follows. If there are any unreasonable designs or optimization points, I will appreciate it if you can correct them.

Background

As a traffic governance component for distributed and multilingual heterogeneous service architecture, Sentinel's observability system will greatly affect the rationality of users' rule configuration and thus affect the actual protection effect There are many state transitions in Sentinel, such as current limiting state transitions, fuse state transitions, adaptive algorithm state transitions, rule state transitions, etc. Some of these state transitions do not have event mechanisms, while others have independent event mechanisms, resulting in users not having a suitable way to simultaneously monitor and handle these events. So it is necessary to build a unified and scalable event system to support the event requirements of these state transitions and other functional modules. On the basis of this event system, it is necessary to have the ability to connect with the open source ecosystem.

Design Overview

Design Overview

image-20240922195627554

SentinelEventListener

The event listener is maintained as a collection in the SentinelEventListenerRegistry, responsible for the specific processing of events. The main operation entry is the static method addListener of SentinelEventBus.

public abstract class SentinelEventListener {
    /**
    * callback 
    *
    * @param event event
    */
    void onEvent(SentinelEvent event);
    /**
    * event types this listener are listening
    */
    List<Class<? extends SentinelEvent>> eventType();
    /**
    * async handle
    */
    public Executor executor() {
        return null;
    }
    /**
    * Whether to ignore expired event
    */
    public boolean alwaysLast() {
        return false;
    }
    /**
    * Priority
    * The smaller the number, the higher the priority
    */
    public int order() {
        return Integer.MAX_VALUE;
    }
}

SentinelEventListenerRegistry

Storaging event listener, defining how to maintain and organize listener logic, combined in SentinelEventBus and SentinelVentMulticaster, where a SentinelApplication only has one SentinelEventListenerRegistry

public interface SentinelEventListenerRegistry {
    // init ops
    void init(Properties properties);
    // destory ops
    void destory();
    // add mapping
    void addSubscriber(SentinelEventListener listener);
    // remove mapping
    void removeSubscriber(SentinelEventListener listener);
    // get all listeners of event
    List<SentinelEventListener> getSentinelEventListener(SentinelEvent event);
}

SentinelEvent

As a carrier of event information, it supports custom inheritance and publishes events through the publishEvent static method provided by SentinelEventBus.

public abstract class SentinelEvent {
    // used to recognize expired event
    private static final AtomicLong SEQUENCE = new AtomicLong(0);
    private final long sequence = SEQUENCE.getAndIncrement();
}

SentinelEventMulticaster

As the core of the entire event driven model, the event broadcaster defines how to callback listeners and build and maintain them through the SentinelEventMulticasterFactory event broadcaster factory.

public interface SentinelEventMulticaster extends Closeable {
    // init ops
    void init(Properties properties, SentinelEventListenerRegistry registry);
    // destory ops
    void destory();
    // publish event
    boolean publish(SentinelEvent event);
}

SentinelEventMulticasterFactory

The event broadcaster factory is responsible for maintaining the mapping relationship between events and broadcasters. The main completed tasks include:

public interface SentinelEventMulticasterFactory {
    // init ops
    void init(Properties properties);
    // destory ops
    void destory();
    // get multicaster of event
    SentinelEventMulticaster getSentinelEventMulticaster(SentinelEvent event);
    // add mapping
    boolean addSentinelEventMulticaster(Class<? extends SentinelEvent> clazz, SentinelEventMulticaster multicaster);
    // remove mapping
    boolean removeSentinelEventMulticaster(Class<? extends SentinelEvent> clazz);
}

SentinelEventBus

This class serves as the core class, responsible for maintaining the mapping relationship between event types and broadcasters, and providing static methods for providing an entry point that can be operated from any location to the outside world. The main static methods provided are:

public class SentinelEventBus {
    // event and multicaster mapping
    private Map<String, SentinelEventMulticaster> multicaster;
    private static final SentinelEventBus INSTANCE = new SentinelEventBus();
    private SentinelEventBus() {
    // init ops
    }
    public void publish(SentinelEvent event) {
    ...
    }
    ...
}

SentinelEventFreqLimiter

Responsible for frequency control of events to prevent explosions.

public interface SentinelEventFreqLimiter {
    boolean shouldHandle(SentinelEvent event);
}

Adapt to Sentinel

image-20240922213746630

Expansion

Initial plan to support events

After triggering, the following events will be written in JSON format to the 'event. log' file.

image