订单派单调度

注意阅读策略模式和责任链模式的代码。

进入ordersDispatchService.dispatch(id)方法:

代码如下:

  1. 通过定时任务,每分钟执行一次dispatchDistributeJob()方法,代码如下:

    
    
    import javax.annotation.Resource;
    import java.util.Set;
    import java.util.concurrent.Executor;
    
    import static com.jzo2o.orders.base.constants.RedisConstants.RedisKey.DISPATCH_LIST;
    
    /**
     * 派单分发xxl-job定时任务
     */
    @Component
    @Slf4j
    public class DispatchJobHandler {
    
    
        @Resource
        private RedisTemplate redisTemplate;
    
        @Resource(name = "dispatchExecutor")
        private Executor dispatchExecutor;
    
    
    //    @Resource
    //    private DispatchDistributeServiceImpl owner;
    
        @Resource
        private IOrdersDispatchService ordersDispatchService;
    
        @Resource
        private OrdersDispatchMapper ordersDispatchMapper;
        /**
         * 派单分发任务
         */
        @XxlJob("dispatch")
        public void dispatchDistributeJob(){
            while (true) {
                Set<Long> ordersDispatchIds = redisTemplate.opsForZSet().rangeByScore(DISPATCH_LIST, 0, DateUtils.getCurrentTime(), 0, 100);
                log.info("ordersDispatchIds:{}", ordersDispatchIds);
                if (CollUtils.isEmpty(ordersDispatchIds)) {
                    log.debug("当前没有可以派单数据");
                    return;
                }
    
                for (Long ordersDispatchId : ordersDispatchIds) {
                    dispatch(ordersDispatchId);
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    
        //由于一个订单3分钟处理一次,所以加锁控制3分钟内只加入线程池一次
        @Lock(formatter = RedisConstants.RedisFormatter.JSONDISPATCHLIST,time = 180)
        public void dispatch(Long id) {
            dispatchExecutor.execute(() -> {
                ordersDispatchService.dispatch(id);
            });
        }
    
    
    
    }
    public void dispatch(Long id) {
            // 1.数据准备
            // 1.1.获取订单信息
            OrdersDispatch ordersDispatch = ordersDispatchService.getById(id);
            if (ordersDispatch == null) {
                // 订单不在直接删除
                redisTemplate.opsForZSet().remove(DISPATCH_LIST, id);
                return;
            }
    
            // 1.3.服务时间,格式yyyyMMddHH
            int serveTime = ServeTimeUtils.getServeTimeInt(ordersDispatch.getServeStartTime());
            // 1.4.区域调度配置
            ConfigRegionInnerResDTO configRegionInnerResDTO = regionApi.findConfigRegionByCityCode(ordersDispatch.getCityCode());
            // 1.5.获取派单规则
            DispatchStrategyEnum dispatchStrategyEnum = DispatchStrategyEnum.of(configRegionInnerResDTO.getDispatchStrategy());
    
    
            // 2.修改下次执行时间(默认3分钟),防止重复执行
            ConfigRegionInnerResDTO configRegion = regionApi.findConfigRegionByCityCode(ordersDispatch.getCityCode());
            redisTemplate.opsForZSet().incrementScore(DISPATCH_LIST, id, configRegion.getDispatchPerRoundInterval());
            // 2.获取派单人员或机构
            // 2.1.获取派单服务人员列表
            List<ServeProviderDTO> serveProvidersOfServe = searchDispatchInfo(ordersDispatch.getCityCode(),
                    ordersDispatch.getServeItemId(),
                    100,
                    serveTime,
                    dispatchStrategyEnum,
                    ordersDispatch.getLon(),
                    ordersDispatch.getLat(),
                    10);
            // 2.3.机构和服务人员列表合并,如果为空当前派单失败
            log.info("派单筛选前数据,id:{},{}",id, serveProvidersOfServe);
            if (CollUtils.isEmpty(serveProvidersOfServe)) {
                log.info("id:{}匹配不到人",id);
                return;
            }
    
            // 3.派单过规则策略
            // 3.1.获取派单策略
            IDispatchStrategy dispatchStrategy = dispatchStrategyManager.get(dispatchStrategyEnum);
            // 3.2.过派单策略,并返回一个派单服务人员或机构
            ServeProviderDTO serveProvider = dispatchStrategy.getPrecedenceServeProvider(serveProvidersOfServe);
            log.info("id:{},serveProvider : {}",id, JsonUtils.toJsonStr(serveProvider));
    
    //        // 4.机器抢单
            OrderSeizeReqDTO orderSeizeReqDTO = new OrderSeizeReqDTO();
            orderSeizeReqDTO.setSeizeId(id);
            orderSeizeReqDTO.setServeProviderId(serveProvider.getId());
            orderSeizeReqDTO.setServeProviderType(serveProvider.getServeProviderType());
            ordersSeizeApi.machineSeize(orderSeizeReqDTO);
        }

  2. 首先通过redisTemplate.opsForZSet().rangeByScore()方法取出派单池中的一批订单

  3. 调用 dispatch(Long id)方法通过线程池执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值