事件机制

本文事件的相关机制

框架基于ApplicationEvent定义了MaculaEvent事件

public abstract class MaculaEvent extends ApplicationEvent {

	private static final long serialVersionUID = 1L;
	
	protected Serializable source;
	
	/**
	 * @param source
	 */
	public MaculaEvent(Serializable source) {
		super(source);
		this.source = source;
	}
	
	@Override
	public Serializable getSource() {
		return source;
	}
}

基于MaculaEvent,定义了异步事件 AsyncMaculaEvent

public class AsyncMaculaEvent extends MaculaEvent {

	private static final long serialVersionUID = 1L;
	
	private ApplicationId applicationId;

	/**
	 * @param source
	 */
	public AsyncMaculaEvent(Serializable source) {
		super(source);
		this.applicationId = ApplicationId.current();
	}
	
	public String getInstanceIdentityKey() {
		return applicationId != null ? applicationId.toString() : "NONE";
	}
	
	/**
	 * @return the applicationId
	 */
	public ApplicationId getApplicationId() {
		return applicationId;
	}

	/**
	 * @param applicationId the applicationId to set
	 */
	public void setApplicationId(ApplicationId applicationId) {
		this.applicationId = applicationId;
	}
	
	public boolean isSourceInstance() {
		return isSourceInstance(ApplicationId.current());
	}

	public boolean isSourceInstance(ApplicationId applicationId) {
		return this.getApplicationId() != null && this.getApplicationId().equals(applicationId);
	}

	public boolean isSourceApplication() {
		return isSourceApplication(ApplicationId.current());
	}

	public boolean isSourceApplication(ApplicationId applicationId) {
		return this.getApplicationId() != null && this.getApplicationId().sameGroup(applicationId)
				&& this.getApplicationId().sameApplication(applicationId);
	}
}

MaculaEvent监听到后系统会同步调用其对应的Listener,而AsyncMaculaEvent会另外开启一个线程调用其对应的Listener实现。

基于AsyncMaculaEvent,框架定义了BroadcastEvent和ClusteredEvent, 前者会被同一个应用组中的所有实例接收,而后者只有应用中的一个实例接收,类似消息队列的Topic和Queue。BroadcastEVent框架默认处理,ClusteredEvent的处理见阿里MQ插件的介绍。

Macula框架支持多实例集群模式,一个应用有多个实例组成,多个应用属于一个分组,为了解决同一个应用组的应用之间、应用实例之间的同步和通讯问题,框架通过BroadcastEvent事件广播的方式进行通信,如下配置:

#是否关闭事件广播
#macula.disableBroadcast = true

#事件广播方式,默认是redis,可以配置http、redis
macula.events.transport = redis
  • HTTP通信方式 框架通过您在应用配置中定义的应用及其实例以及他们的内部地址,利用HttpInvoker的方式把事件广播给相应的实例。由于HTTP网络的不可靠,这种方式不能保证100%成功广播所有事件。

  • REDIS订阅方式 利用REDIS的Subpub功能,在实例启动的时候注册到redis的topic上,当需要广播事件是只要向topic发送事件,这种模式需要配置相应的redisTemplate,如下:

<alias name="redisTemplate" alias="transportRedisTemplate" />

这里是共用了Redis,可以单给定义transportRedisTemplate到不同的Redis集群上。