Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal about sentinel event design #3451

Open
Daydreamer-ia opened this issue Sep 23, 2024 · 0 comments
Open

Proposal about sentinel event design #3451

Daydreamer-ia opened this issue Sep 23, 2024 · 0 comments

Comments

@Daydreamer-ia
Copy link

Daydreamer-ia commented Sep 23, 2024

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

导师:@LearningGp

背景

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

设计概述

整体设计

image-20240922195627554

  • SentinelEventBus :提供使用整个事件模型的操作入口
    • 该类开放纯静态接口,例如发布事件、注册监听器、注册事件发布器等,便于任意位置操作
  • SentinelEventMulticasterFactory :事件广播器工厂接口,负责维护事件以及广播器的映射关系 (事件隔离实现)
  • SentinelEventMulticaster :事件广播器接口,负责定义在事件发生如何广播进行回调
  • SentinelEventListenerRegistry :事件监听器的存储接口,统一管理和维护监听器 (定义如何管理和组织存储)
  • SentinelEvent :事件基础抽象类,用于传递事件信息
  • SentinelEventListener :事件监听器接口,负责监听事件进行自定义逻辑
  • SentinelEventFreqLimiter:针对事件维度进行频率控制,防止事件爆炸

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 接入

  • 初始化工作,依赖 InitFunc 初始化接口完成
    • 注册 SentinelEventFreqLimiter 频率控制器
    • 注册默认支持的监听器(将发生事件写入到类似 metric.log 的文件,并支持限制文件数量和大小)
  • 事件埋点工作,依赖新增的 EventSlot 完成
    • 针对 block 事件进行埋点

image-20240922213746630

使用拓展

  • SentinelEventMulticasterFactory:可重新定义如何存取广播器逻辑,支持 SPI
    • 目前仅以事件类型和广播器简单维护,找不到时返回默认实现
  • SentinelEventListenerRegistry:可定义如何存取监听器逻辑,支持 SPI
    • 目前仅以事件类型和监听器列表简单维护
  • SentinelEventMulticaster:可重新定义如何进行事件广播/回调行为,通过接口实现并在 SentinelEventBus 注册
    • 目前仅以生产-消费模式,消费放入广播器队列内的事件(分实时消费和定时消费两个实现)
  • SentinelEvent:可拓展更多异构的事件类型,通过继承完成
  • SentinelEventListener:通过继承的方式拓展更多事件的监听器

初期计划支持事件

以下事件在触发后,均会以 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

  • SentinelEventBus: Provides an operational entry point for using the entire event model
    • This type of open pure static interface, such as publishing events, registering listeners, registering event publishers, etc., is easy to operate from any location
  • SentinelEventMulticasterFactory: an event broadcaster factory interface responsible for maintaining the mapping relationship between events and broadcasters (event isolation implementation)
  • SentinelEventMulticaster: an event broadcaster interface responsible for defining how to broadcast callbacks when an event occurs
  • SentinelEventListenerRegistry: The storage interface for event listeners, which provides unified management and maintenance of listeners (defining how to manage and organize storage)
  • SentinelEvent: an event based abstract class used to pass event information
  • SentinelEventListener: an event listener interface responsible for listening to events and customizing logic
  • SentinelEventFreqLimiter: Frequency control for event dimensions to prevent event explosions

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:

  • Customize the mapping relationship between events and broadcasters, which supports isolation control of events (such as aggregating multiple event types into the same broadcaster)
  • Support customizing callback logic based on event granularity
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:

  • Add listeners;
  • Remove the listener;
  • Increase the mapping relationship between event broadcasters and events;
  • Delete the mapping relationship between event broadcasters and events;
  • Publish events;
  • Add/cover event frequency controller;
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

  • Initialization work is completed by relying on the InitFunc initialization interface
    • Register the SentinelEventFreqLimiter frequency controller
    • Register default supported listeners (write events to a file similar to 'metric. log' and support limiting the number and size of files)
  • Event tracking work relies on the newly added 'EventSlot' to complete
    • Burial points for 'block' events

image-20240922213746630

Expansion

  • SentinelEventMulticasterFactory: Can redefine how to access broadcaster logic, supports SPI`
    • At present, it is only maintained based on event types and broadcasters, and if it cannot be found, it will return to the default implementation
  • SentinelEventListenerRegistry: can define how to access listener logic, supports SPI`
    -Currently, it is only maintained with simple event types and listener lists
  • SentinelEventMulticaster: Redefine how to perform event broadcast/callback behavior, implemented through an interface and registered in SentinelEventBus
    • At present, only the production consumption mode is used to consume events placed in the broadcaster queue (implemented in two ways: real-time consumption and timed consumption)
  • SentinelEvent: can expand to more heterogeneous event types, completed through inheritance
  • SentinelEventListener: Extend listeners for more events through inheritance

Initial plan to support events

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

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant