消息队列disruptor项目中应用

第一,定义一个实践对象,目的是为了通用
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>

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值