背景
在某些特定的场景下,某些服务总有独立于主链路,而又必须去做的事(简称为下游链路):比如
- 场景A:往数据库中插入一条数据之后,下游链路需要同步的去处理消费(在同一应用中,就不考虑kafka等MQ了);
- 场景B:系统中需要打印大量的log,log打印操作比较耗时但是在主链路中又高频次;
场景A和场景B中,显然当前主链路是不关注下游链路的处理结果的,需要立即返回。好处主要有:
- 降低系统RT值;
- 业务解耦合:避免下游链路影响上游
在线上环境,显然不能采用随时创建一个线程的方式来执行,从而需要一个全局线程池来操作,故而AsyncEventBus应运而生。
关键类,代码举例
- Event:事件主体,提交和消费的数据载体
@Data
@AllArgsConstructor
public class MyEvent {
private String name;
private Integer age;
}
- Listener:消费者,实际消费Event的地方
- 实现EventListener接口
- 接收到消息时,被调用的方法用@Subscribe注解
@Slf4j
public class MyEventListener implements EventListener {
/**
* 收到每条消息,实际上执行的方法:注意,需要这两个注解
*
* @param event
*/
@Subscribe
@AllowConcurrentEvents
public void listen(MyEvent event) {
try {
Thread.sleep(100);
log.info(" deal event " + " " + JSON.toJSONString(event));
} catch (Exception e) {
log.error(" listen error " , e);
}
}
}
- EventBus:控制中心
public class MyAsyncEventBus extends AsyncEventBus {
/**
* 在xml中实例化bean时,会调用此构造方法,将自定义的线程池交由AsyncEventBus使用
*
* @param executor
*/
public MyAsyncEventBus(Executor executor) {
super(executor);
}
/**
* 在xml中实例化bean时,会调用此方法将自定义的Listener注册进AsyncEventBus
*
* @param eventListeners
*/
public synchronized void setEventListeners(Set<EventListener> eventListeners) {
if (eventListeners != null) {
for (EventListener eventListener : eventListeners) {
// 调用父类AsyncEventBus的register方法,将Listeners注册进EventBus中
this.register(eventListener);
}
}
}
/**
* 业务方调用此方法来提交事件,由AsyncEventBus分发至各个Listener,执行业务代码
*
* @param event
*/
@Override
public void post(Object event) {
try {
super.post(event);
} catch (Exception e) {
e.printStackTrace();
}
}
}
- XML 方式配置bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi=