第一,定义一个实践对象,目的是为了通用
public class InternetEvent implements Serializable {
private static final long serialVersionUID = 6214266858022703945L;
/**
* 消息体
*/
private Object msgBody;
/**
* 消息类型
*/
private String type;
/**
* 重发次数
*/
private int retryCount;
public Object getMsgBody() {
return msgBody;
}
public void setMsgBody(Object msgBody) {
this.msgBody = msgBody;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public int getRetryCount() {
return retryCount;
}
public void setRetryCount(int retryCount) {
this.retryCount = retryCount;
}
public void clear() {
msgBody = null;
retryCount = 0;
}
}
第二,定义事件工厂
public class InternetEventFactory implements EventFactory<InternetEvent> {
@Override
public InternetEvent newInstance() {
return new InternetEvent();
}
}
第三,事件发布者
/**
* @author zhH
* @date 2019/5/5 15:22
*/
@Component(value = "internetEventPublisher")
public class InternetEventPublisher implements DisposableBean {
private static final Logger LOGGER = LoggerFactory.getLogger(InternetEventPublisher.class);
private RingBuffer<InternetEvent> ringBuffer;
private WorkerPool<InternetEvent> workerPool;
private final ThreadPoolTaskExecutor executor;
@Autowired
public InternetEventPublisher(ThreadPoolTaskExecutor executor) {
this.executor = executor;
}
@Autowired private ApplicationContext applicationContext;
/**
* disruptor start.
*
* @param bufferSize this is disruptor buffer size.
*/
public void start(final int bufferSize) {
int consumerSize = executor.getCorePoolSize();
// 创建ringBuffer
ringBuffer = RingBuffer.create(ProducerType.MULTI, new InternetEventFactory(), bufferSize, new SleepingWaitStrategy());
InternetEventHandler[] handlers = new InternetEventHandler[consumerSize];
for(int i = 0 ; i < consumerSize ; i ++){
handlers[i] = applicationContext.getBean(InternetEventHandler.class); }
SequenceBarrier barriers = ringBuffer.newBarrier();
workerPool = new WorkerPool<>(ringBuffer, barriers,
new ExceptionHandler<InternetEvent>() {
@Override
public void handleEventException(Throwable ex, long sequence, InternetEvent event) {
LogUtil.error(LOGGER, () -> "Disruptor handleEventException:" + event.getType() + event.getMsgBody() + ex.getMessage());
LogUtil.logStackTrace(LOGGER,ex);
// 重试
int maxRetry = 3;
if (maxRetry > event.getRetryCount()) {
event.setRetryCount(event.getRetryCount() + 1);
LogUtil.info(LOGGER, () -> event.getType() + ":" + event.getMsgBody() + "处理异常,正在重试,重试次数[" + event.getRetryCount() + "]");
publishEvent(event.getMsgBody(), event.getType(), event.getRetryCount());
}
}
@Override
public void handleOnStartException(Throwable ex) {
LogUtil.error(LOGGER, () -> "Disruptor start exception");
LogUtil.logStackTrace(LOGGER,ex);
}
@Override
public void handleOnShutdownException(Throwable ex) {
LogUtil.error(LOGGER, () -> "Disruptor close Exception ");
LogUtil.logStackTrace(LOGGER,ex);
}
}, handlers);
ringBuffer.addGatingSequences(workerPool.getWorkerSequences());
workerPool.start(executor);
}
/**
* publish disruptor event.
*/
public void publishEvent(final Object msg, final String type,final int retryCount) {
// 获得下一个Event槽的下标
long sequence = ringBuffer.next();
try {
// 给Event填充数据
InternetEvent event = ringBuffer.get(sequence);
event.setRetryCount(retryCount);
event.setType(type);
event.setMsgBody(msg);
} finally {
// 发布Event,激活观察者去消费, 将sequence传递给该消费者
// 注意,最后的 ringBuffer.publish() 方法必须包含在 finally 中以确保必须得到调用;如果某个请求的 sequence 未被提交,将会堵塞后续的发布操作或者其它的 producer。
ringBuffer.publish(sequence);
}
}
@Override
public void destroy() {
workerPool.halt();
executor.shutdown();
}
}
第四,事件处理器,业务真实是在这里触发
@Component
@Scope("prototype")
public class InternetEventHandler implements WorkHandler<InternetEvent> {
private static final Logger LOGGER = LoggerFactory.getLogger(InternetEventHandler.class);
//业务接口注入
@Autowired
private RangeBiz rangeBiz;
@Override
public void onEvent(InternetEvent internetEvent) throws Exception {
String type = internetEvent.getType();
if(StringUtils.isNotEmpty(type)){
LOGGER.info("===================================当前线程:" + Thread.currentThread().getName() + ",开始处理:" + type);
switch (type){
case TEST:
//异步查询
rangeBiz.rangeBiz(internetEvent.getMsgBody().toString());
break;
//异步保存,不同对象可以转换,这就是为啥要定义InternetEvent类的原因
case SAVE:
final Map<String,Object> sMap = (HashMap)internetEvent.getMsgBody();
rangeBiz.splitOperation((List<Object>) sMap.get("data"),(AtomicInteger) sMap.get("successCount"),(AtomicInteger) sMap.get("failCount"));
break;
//其他的可以类似来写
default: break;
}
internetEvent.clear();
LOGGER.info("===================================当前线程:" + Thread.currentThread().getName() + ",处理:" + type + "完成");
}
}
}
第五,业务要发布的队列
@Service("testService")
public class TestService {
@Autowired
private InternetEventPublisher publisher;
public void testPublish(){
//TEST 要和 switch (type){ case TEST: 是一样,就是一个类型
publisher.publishEvent("参数", TEST, 0);
}
}
依赖包
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>3.4.2</version>
</dependency>