Spring Boot整合LMAX Disruptor
参考文章:https://www.yuque.com/simonalong/jishu/qhdcb2
依赖
1 2 3 4 5 <dependency > <groupId > com.lmax</groupId > <artifactId > disruptor</artifactId > <version > 3.4.2</version > </dependency >
实例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 public class EventInfoServiceImpl { private Disruptor<EventInfoAndBack> applyDisruptor; private RingBuffer<EventInfoAndBack> applyQueue; @GrpcClient("grpc-server") private EventInfoServiceGrpc.EventInfoServiceFutureStub eventInfoServiceFutureStub; public EventInfoServiceImpl () { ThreadPoolExecutor executor = new ThreadPoolExecutor (7 , 7 , 1 , TimeUnit.SECONDS, new ArrayBlockingQueue <>(1 )); this .applyDisruptor = DisruptorBuilder.newInstance(EventInfoAndBack.class).setRingBufferSize(1024 ).setEventFactory(new EventInfoFactory ()).setExecutor(executor).setProducerType(ProducerType.MULTI).setWaitStrategy(new BlockingWaitStrategy ()).build(); this .applyDisruptor.handleEventsWithWorkerPool(new EventInfoWorkHandler ("1" ),new EventInfoWorkHandler ("2" ),new EventInfoWorkHandler ("3" )); this .applyDisruptor.handleEventsWith(new EventInfoHandler ("1" ), new EventInfoHandler ("2" )); this .applyDisruptor.handleEventsWithWorkerPool(new EventInfoWorkHandler ("4" ),new EventInfoWorkHandler ("5" )); this .applyDisruptor.setDefaultExceptionHandler(new FatalExceptionHandler ()); applyQueue = applyDisruptor.start(); } public EventInfoResponse sendEventInfoMessage (String data) { EventInfoMessage eventInfoMessage = EventInfoMessage.newBuilder().setMsg(data).build(); AtomicReference<EventInfoResponse> eventInfoResponse = new AtomicReference <>(); for (int i = 0 ; i < 10 ; i++) { applyQueue.publishEvent((event, sequence) -> { event.eventInfoMessage = eventInfoMessage; event.back = eventInfoResponse::set; }); } while (eventInfoResponse.get() == null ){ } return eventInfoResponse.get(); } private class EventInfoAndBack { EventInfoMessage eventInfoMessage; Back<EventInfoResponse> back; public EventInfoMessage getEventInfoMessage () { return eventInfoMessage; } public void setEventInfoMessage (EventInfoMessage eventInfoMessage) { this .eventInfoMessage = eventInfoMessage; } public Back<EventInfoResponse> getBack () { return back; } public void setBack (Back<EventInfoResponse> back) { this .back = back; } } private class EventInfoFactory implements EventFactory <EventInfoAndBack> { @Override public EventInfoAndBack newInstance () { return new EventInfoAndBack (); } } private class EventInfoHandler implements EventHandler <EventInfoAndBack> { private String str; public EventInfoHandler (String str) { this .str = str; } @Override public void onEvent (EventInfoAndBack eventInfo, long l, boolean b) throws Exception { System.out.println("event-" +str+":" +Thread.currentThread().getName()); ListenableFuture<EventInfoResponse> response = eventInfoServiceFutureStub.sendMessageEvent(eventInfo.getEventInfoMessage()); eventInfo.back.run(response.get()); } } private class EventInfoWorkHandler implements WorkHandler <EventInfoAndBack> { private String str; public EventInfoWorkHandler (String str) { this .str = str; } @Override public void onEvent (EventInfoAndBack eventInfo) throws Exception { System.out.println("work-" +str+":" +Thread.currentThread().getName()); ListenableFuture<EventInfoResponse> response = eventInfoServiceFutureStub.sendMessageEvent(eventInfo.getEventInfoMessage()); eventInfo.back.run(response.get()); } } private interface Back <T> { void run (T t) ; } }
Disruptor的几个重要的参数:
ringBufferSize:可以理解为环的大小,也就是队列最大容量
eventFactory:参数工厂,需要实现com.lmax.disruptor.EventFactory接口,Disruptor维护对象的生产工厂,队列中的对象通过这个工厂获取
executor:java.util.concurrent.Executor执行器,具体消费者的执行器,Disruptor默认实现了com.lmax.disruptor.dsl.BasicExecutor类,如果只传入线程工厂,就会使用此类,也可以使用其他的执行器,比如代码中使用的就是线程池
producerType:生产模式,由com.lmax.disruptor.dsl.ProducerType枚举控制
SINGLE:单生产者模式,com.lmax.disruptor.SingleProducerSequencer,适用于单线程
MULTI:多生产者模式,对应com.lmax.disruptor.MultiProducerSequencer,适用于多线程,主要区别在于,多生产者模式会使用到cas获取下一个序列,可以无锁解决并发问题,单生产者模式在多线程下可能会出现序列冲突问题
waitStrategy:等待策略,com.lmax.disruptor.WaitStrategy接口控制,即消费者在没有事件需要处理时,如和等待新事件,下面是几个实现类,从上到下,更加轻量
BlockingWaitStrategy:阻塞等待,有新的事件,会被唤醒,调用java.util.concurrent.locks.Condition#await()方法
SleepingWaitStrategy:自旋让渡 加休眠等待,每自旋一段时间,就会尝试调用Thread.yield方法让渡cpu资源,再休眠一段时间再自旋等待
YieldingWaitStrategy:自旋让渡,每自旋一段时间,就会尝试调用Thread.yield方法让渡cpu资源,但不会像上者一样休眠等待
BusySpinWaitStrategy:自旋等待,只会不断自旋,不会让渡cpu资源,更不会等待
上面几个参数,大部分其实是RingBuffer类的参数,具体可参考是Disruptor类的构造方法
Disruptor几个重要的方法
handleEventsWith(EventHandler<? super T>… handlers):配置Disruptor的事件处理类,我们编写的事件处理类需要实现EventHandler接口,可以通过此方法一次配置多个事件处理者,也可以多次调用这个方法配置,无论如何配置的,当生产者推送一个事件,所有事件处理者都会收到并处理
handleEventsWithWorkerPool(WorkHandler… workHandlers):配置Disruptor工作处理类,工作处理类与事件处理类的区别在于,通过调用一次handleEventsWithWorkerPool方法配置的多个WorkHandler,而已理解为一个工作组,当有事件推送时,一个工作组中只有一个工作处理者能接收到事件
setDefaultExceptionHandler(ExceptionHandler<? super T> exceptionHandler):配置异常处理类,Disruptor提供了几个默认的实现类,也可以自己实现