核心链路
核心链路特点:至关重要且业务复杂。
实现方式:
- 传统的完全解耦模式
- 模板模式
解决手段:
1 领域模型的高度抽象
2 寻找更好的框架帮助我们进行编码
使用框架:
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可以实现串并行同时编码:
菱形操作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
特别感谢:
阿神