可以看到,数据源有两个,一个是 DB,另一个是消息队列。主要的流程都是,数据源发送到 Disruptor 框架的 ringBuffer 里,通过 Disruptor 自带的队列监听机制,触发放入 ringBuffer 里 Event 对应的 EventHandler 的 onEvent 方法,在 onEvent 方法完成具体的撮合逻辑。
1、从 DB 来的数据源
程序启动时,直接从数据库捞数据,实现 springboot 的一个启动类
@Component
public class DataLoaderCmdRunner implements CommandLineRunner {
@Autowired
private EntrustOrderMapper entrustOrderMapper ;
@Autowired
private DisruptorTemplate disruptorTemplate ;
/**
* 项目启动完毕后会执行该方法
* @param args
* @throws Exception
*/
@Override
public void run(String... args) throws Exception {
List<EntrustOrder> entrustOrders = entrustOrderMapper.selectList(
new LambdaQueryWrapper<EntrustOrder>()
.eq(EntrustOrder::getStatus, 0)
.orderByAsc(EntrustOrder::getCreated)
);
if(CollectionUtils.isEmpty(entrustOrders)){
return;
}
StopWatch stopWatch = new StopWatch() ;
stopWatch.start();
for (EntrustOrder entrustOrder : entrustOrders) {
disruptorTemplate.onData(BeanUtils.entrustOrder2Order(entrustOrder));
}
stopWatch.stop();
long lastTaskTimeMillis = stopWatch.getLastTaskTimeMillis();
System.out.println("总条数:+"+entrustOrders.size()+" ,总共耗时:"+lastTaskTimeMillis+"ms");
}
}
可以看到 disruptorTemplate.onData 就是具体的往 ringBuffer 里塞数据,塞的 Event 实际的类型就是 OrderEvent
public void onData(Order input) {
ringBuffer.publishEvent(TRANSLATOR, input);
}
private static final EventTranslatorOneArg<OrderEvent, Order> TRANSLATOR = new EventTranslatorOneArg<OrderEvent, Order>() {
public void translateTo(OrderEvent event, long sequence, Order input) {
event.setSource(input);
}
};
然后我们找到 OrderEventHandler implements EventHandler 的 onEvent 里,最终通过 match策略完成一个撮合,整个流程就是这样。
@Override
public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {
// 从ringbuffer 里面接收了某个数据
Order order = (Order)event.getSource();
if(!order.getSymbol().equals(symbol)){ // 我们接收到了一个不属于我们处理的数据,我们不处理
return;
}
// log.info("开始接收订单事件============>{}", event);
MatchServiceFactory.getMatchService(MatchStrategy.LIMIT_PRICE).match(orderBooks ,order);
/// 处理逻辑是啥?
// log.info("处理完成我们的订单事件===================>{}", event);
}
值得注意的是,我们往容器中注入了一个什么样的 ringBuffer,com.bjsxt.disruptor.DisruptorAutoConfiguration#ringBuffer
public RingBuffer<OrderEvent> ringBuffer(
EventFactory<OrderEvent> eventFactory,
ThreadFactory threadFactory,
WaitStrategy waitStrategy,
EventHandler<OrderEvent>[] eventHandlers
)
可以看到一个重要的构造参数 eventHandlers,这个数组就是所有可以监听 这个 ringBuffer 的 handler,我们往容器中注入的是根据配置文件里的交易对注入的3个
@Bean("eventHandlers")
public EventHandler<OrderEvent>[] eventHandlers() {
Map<String, MatchEngineProperties.CoinScale> symbols = matchEngineProperties.getSymbols();
Set<Map.Entry<String, MatchEngineProperties.CoinScale>> entries = symbols.entrySet();
EventHandler<OrderEvent>[] eventHandlers = new EventHandler[symbols.size()];
int i = 0;
for (Map.Entry<String, MatchEngineProperties.CoinScale> entry : entries) {
String symbol = entry.getKey();
MatchEngineProperties.CoinScale value = entry.getValue();
OrderBooks orderBooks = null;
if (value != null) {
orderBooks = new OrderBooks(symbol, value.getCoinScale(), value.getBaseCoinScale());
} else {
orderBooks = new OrderBooks(symbol);
}
eventHandlers[i++] = new OrderEventHandler(orderBooks);
}
return eventHandlers;
}
# 去 nacos-server 里面拉取 match-service-dev.yaml
match:
symbols:
BTCGCN:
coinScale: 8
baseCoinScale: 8
ETHGCN:
coinScale: 8
baseCoinScale: 8
FOFTGCN:
coinScale: 8
baseCoinScale: 8
2、通过 rockmq 发送数据源的数据流转
在交易系统中,创建委托单后,直接往 rockmq 中发送消息,撮合系统监听这个消息,将消息放到 ringbuffer 中
com.bjsxt.service.impl.EntrustOrderServiceImpl#createEntrustOrder
撮合系统监听,发送到 ringBuffer
@Service
@Slf4j
public class MessageConsumerListener {
@Autowired
private DisruptorTemplate disruptorTemplate;
@StreamListener("order_in")
public void handleMessage(EntrustOrder entrustOrder) {
Order order = null;
if (entrustOrder.getStatus() == 2) { // 该单需要取消
order = new Order();
order.setOrderId(entrustOrder.getId().toString());
order.setCancelOrder(true);
} else {
order = BeanUtils.entrustOrder2Order(entrustOrder);
}
log.info("接收到了委托单:{}", order);
disruptorTemplate.onData(order);
}
}