common-event-ao
- 事件中心核心服务,集成事件接入-事件加工-事件分发
1.事件过滤能力(Filter)
1.1.接入步骤
- 先引入common-event-ao-stub
<dependency>
<groupId>com.hooware.cc.fucomm-event-ao</groupId>
<artifactId>common-event-ao-stub</artifactId>
<version>1.0.1</version>
</dependency>
2.实现SPI过滤接口
1.com.hooware.cc.common.event.ao.spi.IEventSpiFilter
3.实现类添加@EventSPI注解
1.SPI注解:com.hooware.cc.common.event.ao.spi.EventSPI
2.同时指定自己对应的渠道com.hooware.cc.common.event.ao.spi.EventChannelTypeEnum
3.自行根据自己的业务完成实现该接口过滤的业务逻辑(确保性能和兜底)
4.提供自己实现类的包及类路径
1.事件中心添加下游实现的SPI包依赖maven坐标;
2.在META-INF/spring.factories中添加实现类路径
- 默认事件过滤SPI实现示例
package com.hooware.cc.common.event.ao.infrastructure.spi;
import com.hooware.cc.common.event.ao.spi.EventSPI;
import com.hooware.cc.common.event.ao.spi.EventSpiFilterRequest;
import com.hooware.cc.common.event.ao.spi.IEventSpiFilter;
@EventSPI(DefaultEventSpiFilter.NAME)
public class DefaultEventSpiFilter implements IEventSpiFilter {
public static final String NAME = "default";
@Override
public boolean doFilter(EventSpiFilterRequest request) {
// default默认放行不过滤
return true;
}
}
1.2.核心逻辑
- 事件过滤采用责任链模式完成事件的链式加工(短路链式,某个实现类如果拦截则会直接返回,后续过滤器不会参与逻辑处理)
事件过滤UML类图
-
SPI相关能力包路径:com.hooware.cc.common.event.ao.spi
1.事件过滤SPI接口: IEventSpiFilter;
2.接口基础Req请求:EventSpiFilterRequest;
3.事件过滤SPI注解:EventSPI;
4.事件核心过滤器:SpiEventFilter
5.META-INF/spring.factories文件
- IEventSpiFilter: 定义SPI事件过滤器接口,用户下游自行实现决定是否需要过滤事件中心的接受到的事件, 如不过滤则会投递到该下游渠道, 如过滤则直接拦截
package com.hooware.cc.common.event.ao.spi;
/**
* SPI事件过滤器接口, 用户下游差异性实现决策是否需要过滤事件中心的接受到的事件, 如不过滤则会投递到该下游渠道, 如需要过滤则直接拦截
*/
public interface IEventSpiFilter {
/**
* 过滤事件中心的接受到的事件, 如不过滤则会投递到该下游渠道, 如需要过滤则直接拦截
*
* @param request 标准请求体
* @return bool值, true: 需要过滤, false: 无需过滤
*/
boolean doFilter(EventSpiFilterRequest request);
}
- EventSpiFilterRequest:SPI事件过滤器接口基础请求,包含基础用户、资产及事件源报文字段
package com.hooware.cc.common.event.ao.spi;
import lombok.Data;
import lombok.experimental.Accessors;
/**
* SPI扩展filter请求结构
*/
@Data
@Accessors(chain = true)
public class EventSpiFilterRequest {
/**
* 用户唯一标识uin
*/
private String uin;
/**
* 用户唯一标识userId
*/
private String userId;
/**
* 账号唯一标识tradeId
*/
private String tradeId;
/**
* 基金代码fundCode
*/
private String fundCode;
/**
* 原始事件源Json数据串, 如api接口请求则为request串
*/
private String eventData;
}
- EventSPI:事件过滤SPI注解,下游实现类需加该注解并指明对应渠道EventChannelTypeEnum,否则会被过滤掉而不被执行
package com.hooware.cc.common.event.ao.spi;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface EventSPI {
/**
* 表示插件名称,为空表示从配置文件解析插件名称。支持配置文件和该注解同时配置插件名称,优先使用配置文件中配置的名称。
*
* @return 插件名称
*/
String value() default "";
/**
* 下游渠道设置, 用于筛选执行
*
* @return 下游渠道
*/
EventChannelTypeEnum channel() default EventChannelTypeEnum.UNKNOWN;
}
- SpiEventFilter:事件核心过滤器实现,使用Spring的spring.factories方式实现SPI机制
package com.hooware.cc.common.event.ao.domain.dispatch.filter.impl;
import com.hooware.cc.common.event.ao.application.dto.StandardDispatchEventDTO;
import com.hooware.cc.common.event.ao.domain.dispatch.filter.IEventFilter;
import com.hooware.cc.common.event.ao.domain.dispatch.filter.IEventFilterChain;
import com.hooware.cc.common.event.ao.spi.EventSPI;
import com.hooware.cc.common.event.ao.spi.EventSpiFilterRequest;
import com.hooware.cc.common.event.ao.spi.IEventSpiFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* spi机制加载外部实现, todo 下游可能存在性能瓶颈, 待后续实际情况优化
*/
@Slf4j
@Service
@Order(0)
public class SpiEventFilter implements IEventFilter, InitializingBean {
/**
* spi加载列表
*/
private List<IEventSpiFilter> spiFilters;
@Override
public void afterPropertiesSet() throws Exception {
// 加载所有的spi扩展点
// ServiceLoader<IEventSpiFilter> spiFilters = ServiceLoader.load(IEventSpiFilter.class);
spiFilters = SpringFactoriesLoader.loadFactories(IEventSpiFilter.class,
Thread.currentThread().getContextClassLoader());
}
@Override
public boolean doFilter(StandardDispatchEventDTO dispatchEventDTO, IEventFilterChain chain) {
// 构建下游请求request
EventSpiFilterRequest request = this.buildRequest(dispatchEventDTO);
for (IEventSpiFilter spiFilter : spiFilters) {
EventSPI eventSPI = AnnotatedElementUtils.findMergedAnnotation(spiFilter.getClass(), EventSPI.class);
// 校验spi加载渠道, 非该渠道不参与过滤
if (eventSPI == null || !eventSPI.channel().equals(
dispatchEventDTO.getDispatchConfig().getEventChannel().getChannelType())) {
continue;
}
// 进行spi过滤执行
if (!spiFilter.doFilter(request)) {
return false;
}
}
return true;
}
private EventSpiFilterRequest buildRequest(StandardDispatchEventDTO dispatchEventDTO) {
return new EventSpiFilterRequest().setUin(dispatchEventDTO.getUin())
.setUserId(dispatchEventDTO.getUserId())
.setFundCode(dispatchEventDTO.getFundCode())
.setTradeId(dispatchEventDTO.getTradeId())
.setEventData(dispatchEventDTO.getEventData());
}
}
- spring.factories: Spring采用的是spring.factories方式实现SPI机制,下游实现类需在此处指定用于加载,路径为"META-INF/spring.factories"
com.hooware.cc.common.event.ao.spi.IEventSpiFilter = \
com.hooware.cc.common.event.ao.infrastructure.spi.DefaultEventSpiFilter
2.事件加工能力(Handler)
- 事件加工也采用责任链模式完成事件的链式加工(完全链式,每个实现类均会加工处理)
事件加工UML类图
1.事件加工接口IEventHandler:
2.事件处理工厂EventHandleFactory:
3.实际加工实现类:DefaultEventHandler,GroovyScriptEventHandler,UserInfoEventHandler
- 事件加工接口IEventHandler:顶层事件加工接口,基于源事件和分发事件DTO和分发配置Entity进行链式加工
package com.hooware.cc.common.event.ao.domain.process.handler;
import com.hooware.cc.common.event.ao.application.dto.StandardDispatchEventDTO;
import com.hooware.cc.common.event.ao.application.dto.StandardSourceEventDTO;
import com.hooware.cc.common.event.ao.domain.manage.entity.EventDispatchConfigEntity;
public interface IEventHandler {
/**
* 事件加工链式处理
*
* @param sourceEvent 原始标准事件源
* @param dispatchEvent 分发标准事件
* @param config 事件分配配置,包含加工脚本
*/
void handle(StandardSourceEventDTO sourceEvent, StandardDispatchEventDTO dispatchEvent,
EventDispatchConfigEntity config);
}
- 事件处理工厂EventHandleFactory:用于串起所有的事件IEventHandler实现类,按照@Order优先级顺序加工处理(可能经过差异性加工后需要进行过滤掉)
package com.hooware.cc.common.event.ao.domain.process.handler;
import com.hooware.cc.common.event.ao.application.dto.StandardDispatchEventDTO;
import com.hooware.cc.common.event.ao.application.dto.StandardSourceEventDTO;
import com.hooware.cc.common.event.ao.domain.manage.entity.EventDispatchConfigEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 事件执行策略工厂, todo 下游处理可能存在性能问题
*/
@Slf4j
@Service
public class EventHandleFactory {
private final List<IEventHandler> eventHandlerList;
@Autowired
public EventHandleFactory(List<IEventHandler> eventHandlerList) {
this.eventHandlerList = eventHandlerList;
}
public void handle(StandardSourceEventDTO sourceEvent, StandardDispatchEventDTO dispatchEvent,
EventDispatchConfigEntity config) {
// 按照@Order优先级顺序处理事件源和事件结果
for (IEventHandler eventHandler : eventHandlerList) {
// 链式处理事件
eventHandler.handle(sourceEvent, dispatchEvent, config);
}
}
}
- 实际加工实现类:DefaultEventHandler(最高优先级,进行默认的StandardDispatchEventDTO封装处理), GroovyScriptEventHandler(提供Grrovy脚本定制化加工能力), UserInfoEventHandler(用户信息加工,如补全用户的uin,userId等信息)
- 实际加工参照实现类: DefaultEventHandler,GroovyScriptEventHandler,UserInfoEventHandler
3.事件分发能力(Dispatcher)
- NBF事件中心架构设计与实现: https://baijiahao.baidu.com/s?id=1728248806634929518&wfr=spider
Q.E.D.