4. Disruptor高级应用

核心链路

核心链路特点:至关重要且业务复杂。

实现方式:

  1. 传统的完全解耦模式
  2. 模板模式

解决手段:
1 领域模型的高度抽象
2 寻找更好的框架帮助我们进行编码

image.png

使用框架:
1 有限状态机框架,例如Spring-StateMachine
2 使用Disruptor

1. 并行计算 - 串、并行操作

public class Handler1 implements EventHandler, WorkHandler{

    //EventHandler
    public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {
        this.onEvent(event);
    }

    //WorkHandler
    public void onEvent(Trade event) throws Exception {
        System.err.println("handler 1 : SET NAME");
        Thread.sleep(1000);
        event.setName("H1");
    }
}
public class Handler2 implements EventHandler {

    public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {
        System.err.println("handler 2 : SET ID");
        Thread.sleep(2000);
        event.setId(UUID.randomUUID().toString());
    }

}
public class Handler3 implements EventHandler {

    public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {
        System.err.println("handler 3 : NAME: " 
                                + event.getName() 
                                + ", ID: " 
                                + event.getId()
                                + ", PRICE: " 
                                + event.getPrice()
                                + " INSTANCE : " + event.toString());
    }
}
public class Handler4 implements EventHandler {

    public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {
        System.err.println("handler 4 : SET PRICE");
        Thread.sleep(1000);
        event.setPrice(17.0);
    }

}
public class Handler5 implements EventHandler {

    public void onEvent(Trade event, long sequence, boolean endOfBatch) throws Exception {
        System.err.println("handler 5 : GET PRICE: " +  event.getPrice());
        Thread.sleep(1000);
        event.setPrice(event.getPrice() + 3.0);
    }

}
@Data
public class Trade {
    private String id;
    private String name;
    private double price;
    private AtomicInteger count = new AtomicInteger(0);

}
public class TradePublisher implements Runnable {


    private final CountDownLatch latch;
    private final Disruptor tradeDisruptor;
    private  static int PUBLISH_COUNT = 1 ;

    public TradePublisher(CountDownLatch latch, Disruptor tradeDisruptor) {
        this.latch = latch;
        this.tradeDisruptor = tradeDisruptor;
    }


    @Override
    public void run() {

        TradeEventTranslator eventTranslator = new TradeEventTranslator();

        for (int i = 0; i < PUBLISH_COUNT; i++) {
            //新的提交任务的方式
            tradeDisruptor.publishEvent(eventTranslator);
        }
        latch.countDown();
    }
}


class TradeEventTranslator implements EventTranslator {

    private Random random = new Random();
    @Override
    public void translateTo(Trade event, long sequence) {
      this.generateTrade(event);
    }

    private void generateTrade(Trade event) {
        event.setPrice(random.nextDouble() * 9999);
    }
}
public class Main {
    public static void main(String[] args) throws InterruptedException {

        //构建一个线程池用于提交我们的任务
        ExecutorService executorService = Executors.newFixedThreadPool(4);


        ThreadFactory springThreadFactory = new CustomizableThreadFactory("springThread-pool-");
        //1.构建Disruptor
        Disruptor disruptor = new Disruptor(
                new EventFactory() {
                    @Override
                    public Trade newInstance() {
                        return new Trade();
                    }
                },
                1024 * 1024,
                springThreadFactory,
                ProducerType.SINGLE,
                new BusySpinWaitStrategy());
        //2.把消费者设置到Disruptor 中 handleEventWith
        //2.1 串行操作:
        disruptor
                .handleEventsWith(new Handler1())
                .handleEventsWith(new Handler2())
                .handleEventsWith(new Handler3());

        //3 启动disruptor

        RingBuffer ringBuffer = disruptor.start();
        CountDownLatch latch = new CountDownLatch(1);

        long begin = System.currentTimeMillis();
        executorService.submit(new TradePublisher(latch,disruptor));
        latch.await();
        disruptor.shutdown();
        executorService.shutdown();

        System.err.println("总耗时: "+ (System.currentTimeMillis() - begin));
    }
}
串行操作
        //2.1 串行操作:
        disruptor
                .handleEventsWith(new Handler1())
                .handleEventsWith(new Handler2())
                .handleEventsWith(new Handler3());

输出

handler 1 : SET NAME
handler 2 : SET ID
handler 3 : NAME: H1, ID: 3eb26617-35bc-4c92-a5d2-53ff9687c6fa, PRICE: 5642.4427235749445 INSTANCE : Trade(id=3eb26617-35bc-4c92-a5d2-53ff9687c6fa, name=H1, price=5642.4427235749445, count=0)
总耗时: 4001
并行操作
写法1:
        disruptor.handleEventsWith(new Handler1());
        disruptor.handleEventsWith(new Handler2());
        disruptor.handleEventsWith(new Handler3());
写法2:
disruptor.handleEventsWith(new Handler1(),new Handler2(),new Handler3());
handler 2 : SET ID
handler 1 : SET NAME
handler 3 : NAME: null, ID: null, PRICE: 1758.6579432027424 INSTANCE : Trade(id=null, name=null, price=1758.6579432027424, count=0)
总耗时: 2755
并行计算-多边形高端操作
Disruptor可以实现串并行同时编码:
image.png
菱形操作1
        //2.3 菱形操作:
        disruptor.handleEventsWith(new Handler1(),new Handler2())
                 .handleEventsWith(new Handler3())
        ;
菱形操作2
        EventHandlerGroup ehGroup = disruptor.handleEventsWith(new Handler1(),new Handler2());
        ehGroup.then(new Handler3());
handler 2 : SET ID
handler 1 : SET NAME
handler 3 : NAME: H1, ID: 4736b028-db54-4846-96c5-912636371d5c, PRICE: 3087.9481405738047 INSTANCE : Trade(id=4736b028-db54-4846-96c5-912636371d5c, name=H1, price=3087.9481405738047, count=0)
总耗时: 3710
六边形操作
六边形操作
        //2.4 六边形操作
        Handler1 h1 = new Handler1();
        Handler2 h2 = new Handler2();
        Handler3 h3 = new Handler3();
        Handler4 h4 = new Handler4();
        Handler5 h5 = new Handler5();

        disruptor.handleEventsWith(h1,h4);

        disruptor.after(h1).handleEventsWith(h2);
        disruptor.after(h4).handleEventsWith(h5);
        disruptor.after(h2,h5).handleEventsWith(h3);
handler 1 : SET NAME
handler 4 : SET PRICE
handler 2 : SET ID
handler 5 : GET PRICE: 17.0
handler 3 : NAME: H1, ID: 82999385-8527-4927-8599-efaf50e547e9, PRICE: 20.0 INSTANCE : Trade(id=82999385-8527-4927-8599-efaf50e547e9, name=H1, price=20.0, count=0)
总耗时: 4079

2. 多生产者多消费者

public class Consumer implements WorkHandler {

    private String comsumerId;
    
    private static AtomicInteger count = new AtomicInteger(0);
    
    private Random random = new Random();
    
    public Consumer(String comsumerId) {
        this.comsumerId = comsumerId;
    }

    public void onEvent(Order event) throws Exception {
        Thread.sleep(1 * random.nextInt(5));
        System.err.println("当前消费者: " + this.comsumerId + ", 消费信息ID: " + event.getId());
        count.incrementAndGet();
    }
    
    public int getCount(){
        return count.get();
    }
    

}
public class Producer {
    
    private RingBuffer ringBuffer;
    
    public Producer(RingBuffer ringBuffer) {
        this.ringBuffer = ringBuffer;
    }

    public void sendData(String uuid) {
        long sequence = ringBuffer.next();
        try {
            Order order = ringBuffer.get(sequence);
            order.setId(uuid);
        } finally {
            ringBuffer.publish(sequence);
        }
    }

}
public class Order {

    private String id;
    private String name;
    private double price;

    public Order() {
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
}
public class Main {

    public static void main(String[] args) throws InterruptedException {

        //1 创建RingBuffer
        RingBuffer ringBuffer =
                RingBuffer.create(ProducerType.MULTI,
                        new EventFactory() {
                            public Order newInstance() {
                                return new Order();
                            }
                        },
                        1024 * 1024,
                        new YieldingWaitStrategy());

        //2 通过ringBuffer 创建一个屏障
        SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();

        //3 创建多个消费者数组:
        Consumer[] consumers = new Consumer[10];
        for (int i = 0; i < consumers.length; i++) {
            consumers[i] = new Consumer("C" + i);
        }

        //4 构建多消费者工作池
        WorkerPool workerPool = new WorkerPool(
                ringBuffer,
                sequenceBarrier,
                new EventExceptionHandler(),
                consumers);

        //5 设置多个消费者的sequence序号 用于单独统计消费进度, 并且设置到ringbuffer中
        ringBuffer.addGatingSequences(workerPool.getWorkerSequences());

        //6 启动workerPool
        workerPool
                .start(Executors.newFixedThreadPool(5));

        final CountDownLatch latch = new CountDownLatch(1);

        for (int i = 0; i < 100; i++) {
            final Producer producer = new Producer(ringBuffer);
            new Thread(new Runnable() {
                public void run() {
                    try {
                        latch.await();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    for (int j = 0; j < 100; j++) {
                        producer.sendData(UUID.randomUUID().toString());
                    }
                }
            }).start();
        }

        Thread.sleep(2000);
        System.err.println("----------线程创建完毕,开始生产数据----------");
        latch.countDown();

        Thread.sleep(10000);

        System.err.println("任务总数:" + consumers[2].getCount());
    }

    static class EventExceptionHandler implements ExceptionHandler {
        public void handleEventException(Throwable ex, long sequence, Order event) {
        }

        public void handleOnStartException(Throwable ex) {
        }

        public void handleOnShutdownException(Throwable ex) {
        }
    }


}
----------线程创建完毕,开始生产数据----------
当前消费者: C2,消费信息ID:72081cd6-3d25-4bb2-ab17-a3973e2b2080
当前消费者: C6,消费信息ID:e9906f6d-2f9f-4e18-9837-60772e1ddc96
当前消费者: C4,消费信息ID:806dd8a1-7570-41f9-a490-a5568e5c99ab
当前消费者: C6,消费信息ID:c7b603bd-acd5-4791-a55b-5f4a01327e00
......省略
当前消费者: C6,消费信息ID:4f1875b5-38dc-489c-a2b3-a0c6a8fadbeb
当前消费者: C3,消费信息ID:7aa0e84c-21a9-405b-8d26-89deb9c514da
当前消费者: C1,消费信息ID:487d731b-e55a-4ba2-8454-ea221387d39e
任务总数:10000
特别感谢:

阿神

你可能感兴趣的:(4. Disruptor高级应用)