RxJava的一次業務嘗試


 public ResultDTO makeStrategy(MakeDecisionDTO makeDecisionDTO) {
        final long current = System.currentTimeMillis();
        final String request = JSON.toJSONString(makeDecisionDTO);
        CatMonitor catMonitor = new CatMonitor();
        ResultDTO result = new ResultDTO();

        // 獲取路由Topic
        String routingTopic = routingTopic(makeDecisionDTO);
        String keys = makeDecisionDTO.getSerialNo();
        // 根據serialNo和路由隊列組合key查詢redis緩存
        String combinationKey = PREFIX_EXIST_CASHE_DECISION + keys + ":" + routingTopic;

        Maybe<ResultDTO> resultDTOMaybe = Maybe
                .create((MaybeOnSubscribe<MakeDecisionDTO>) emitter -> {
                    if (!emitter.isDisposed()) {
                        emitter.onSuccess(makeDecisionDTO);
                    }
                })
                .doOnSubscribe((disposable) -> {
                    logger.info("{},收到請求,{}", Constants.API_MAKE_DECISION, request);
                    catMonitor.start(Constants.MSG_RISK_SERVICE_EXTERNAL, Constants.MSG_RISK_SERVICE_MAKE_DECISION);

                    // 驗證productCode和sceneCode
                    validateMakeDecisionDTO(makeDecisionDTO);

                })
                .doAfterSuccess(makeDecision ->
                        // 接收決策後續處理
                        afterReceiveDecision(makeDecisionDTO, keys, combinationKey)
                )
                .doFinally(() -> {
                    String response = JSON.toJSONString(result);
                    long cost = System.currentTimeMillis() - current;
                    try {
                        keepApiLogThreadPool.execute(() -> {
                            ApiRequestLogDO apiLogDO = new ApiRequestLogDO();
                            apiLogDO.setName("makeStrategy");
                            apiLogDO.setType(Constants.API_LOG_TYPE_REQ);
                            apiLogDO.setUserId(makeDecisionDTO.getUserId());
                            apiLogDO.setSerialNo(makeDecisionDTO.getSerialNo());
                            apiLogDO.setProductCode(makeDecisionDTO.getProductCode());
                            apiLogDO.setSceneCode(makeDecisionDTO.getSceneCode());
                            apiLogDO.setRequest(request);
                            apiLogDO.setContent(JSON.toJSONString(makeDecisionDTO));
                            apiLogDO.setResponse(response);
                            apiLogDO.setCreateTime(new Date(current));
                            apiLogDO.setUpdateTime(new Date(System.currentTimeMillis()));
                            apiLogDO.setCostTime(cost);
                            apiRequestLogMapper.save(apiLogDO);
                        });
                    } catch (RejectedExecutionException e) {
                        logger.error("RejectedExecutionException happen in {}:serialNo:{}", Constants.API_MAKE_DECISION, makeDecisionDTO.getSerialNo());
                    }
                    logger.info("{},執行完成,{},{},{},{},{},{},{}",
                            Constants.API_MAKE_DECISION,
                            makeDecisionDTO.getUserId(),
                            makeDecisionDTO.getProductCode(),
                            makeDecisionDTO.getSceneCode(),
                            result.getSerialNo(),
                            result.getCode(),
                            result.getMessage(),
                            cost);
                    catMonitor.complete();
                })
                .map(makeDecision -> {
                    // 獲取對應的處理器
                    RCBusiness rcBusiness = rcBusinessMapper.get(makeDecisionDTO.getProductCode(), makeDecisionDTO.getSceneCode());
                    if (rcBusiness == null) {
                        String errMsg = new StringJoiner(STR_COMMA)
                                .add(Constants.API_MAKE_DECISION)
                                .add("接口不存在")
                                .add(makeDecisionDTO.getSerialNo())
                                .toString();
                        result.setCode(CodeEnum.ILLEGAL_PARAMETERS);
                        result.setSerialNo(makeDecisionDTO.getSerialNo());
                        logger.error(errMsg);
                        catMonitor.error(errMsg);
                        return result;
                    }
                    // 必要參數驗證
                    rcBusiness.validate(makeDecisionDTO);
                    // 生成事件信息,後續爲生成serialNo做數據補全
                    rcBusiness.analysisEventInfo(makeDecisionDTO);
                    // 生成風控唯一標識serialNo
                    rcBusiness.analysisSerialNo(makeDecisionDTO);
                    // 如果查詢有結果,表示是重複請求
                    if (redisCacheTargetManager.existKey(combinationKey, true)) {
                        logger.info("repeated requests,{}", makeDecisionDTO.getSerialNo());
                        result.setCode(CodeEnum.DUPLICATE_REQUEST);
                        result.setSerialNo(makeDecisionDTO.getSerialNo());
                        catMonitor.success();
                        return result;
                    }
                    makeDecisionDTO.setCurrent(current);
                    int delayLevel = needWait(makeDecisionDTO);
                    // 發送MQ的消息體
                    String content = JSON.toJSONString(makeDecisionDTO);
                    if (delayLevel == DECISION_NO_DELAY_LEVEL) {
                        produce.syncProducer(content, TAGS, keys, routingTopic);
                    } else {
                        produce.syncProducer(content, TAGS, keys, delayLevel, routingTopic);
                    }
                    logger.info("{},放入隊列等待執行,{},{}",
                            Constants.API_MAKE_DECISION,
                            content,
                            delayLevel);
                    result.setCode(CodeEnum.SUCCESS);
                    result.setSerialNo(makeDecisionDTO.getSerialNo());
                    catMonitor.success();
                    return result;
                });
        resultDTOMaybe.subscribe(resultDTO ->
                        logger.info("resultDTO is {}", resultDTO)
                , e -> {
                    if (e instanceof InterruptedException) {
                        result.setCode(CodeEnum.UNKNOWN_EXCEPTION);
                        String errMsg = new StringJoiner(STR_COMMA)
                                .add(Constants.API_MAKE_DECISION)
                                .add("發生中斷")
                                .add(makeDecisionDTO.getSerialNo())
                                .toString();
                        logger.error(errMsg, e);
                        catMonitor.exception(InterruptedException.class.cast(e), errMsg);
                        Thread.currentThread().interrupt();
                    } else if (e instanceof RemotingException || e instanceof MQClientException || e instanceof MQBrokerException) {
                        result.setCode(CodeEnum.UNKNOWN_EXCEPTION);
                        String errMsg = new StringJoiner(STR_COMMA)
                                .add(Constants.API_MAKE_DECISION)
                                .add("未知異常")
                                .add(makeDecisionDTO.getSerialNo())
                                .toString();
                        catMonitor.exception(Exception.class.cast(e), errMsg);
                        logger.error(errMsg, e);
                    } else if (e instanceof ServiceException) {
                        result.setCode(((ServiceException) e).getCode());
                        result.setMessage(e.getMessage());
                        String errMsg = new StringJoiner(STR_COMMA)
                                .add(Constants.API_MAKE_DECISION)
                                .add(e.getMessage())
                                .add(makeDecisionDTO.getSerialNo())
                                .toString();
                        catMonitor.exception(ServiceException.class.cast(e), errMsg);
                        logger.error(errMsg, e);
                    }
                });
        // 返回指定結果
        return resultDTOMaybe.blockingGet();
    }

 public ResultDTO makeStrategy(MakeDecisionDTO makeDecisionDTO) {

        final long current = System.currentTimeMillis();
        final String request = JSON.toJSONString(makeDecisionDTO);
        logger.info("{},收到請求,{}", Constants.API_MAKE_DECISION, request);

        CatMonitor catMonitor = new CatMonitor();
        ResultDTO result = new ResultDTO();
        try {
            catMonitor.start(Constants.MSG_RISK_SERVICE_EXTERNAL, Constants.MSG_RISK_SERVICE_MAKE_DECISION);
            // 驗證productCode和sceneCode
            validateMakeDecisionDTO(makeDecisionDTO);
            // 獲取對應的處理器
            RCBusiness rcBusiness = rcBusinessMapper.get(makeDecisionDTO.getProductCode(), makeDecisionDTO.getSceneCode());
            if (rcBusiness == null) {
                String errMsg = new StringJoiner(STR_COMMA)
                        .add(Constants.API_MAKE_DECISION)
                        .add("接口不存在")
                        .add(makeDecisionDTO.getSerialNo())
                        .toString();
                result.setCode(CodeEnum.ILLEGAL_PARAMETERS);
                result.setSerialNo(makeDecisionDTO.getSerialNo());
                logger.error(errMsg);
                catMonitor.error(errMsg);
                return result;
            }

            // 必要參數驗證
            rcBusiness.validate(makeDecisionDTO);
            // 生成事件信息,後續爲生成serialNo做數據補全
            rcBusiness.analysisEventInfo(makeDecisionDTO);
            // 生成風控唯一標識serialNo
            rcBusiness.analysisSerialNo(makeDecisionDTO);

            // 獲取路由Topic
            String routingTopic = routingTopic(makeDecisionDTO);
            String keys = makeDecisionDTO.getSerialNo();
            // 根據serialNo和路由隊列組合key查詢redis緩存
            String combinationKey = PREFIX_EXIST_CASHE_DECISION + keys + ":" + routingTopic;

            // 如果查詢有結果,表示是重複請求
            if (redisCacheTargetManager.existKey(combinationKey, true)) {
                logger.info("repeated requests,{}", makeDecisionDTO.getSerialNo());
                result.setCode(CodeEnum.DUPLICATE_REQUEST);
                result.setSerialNo(makeDecisionDTO.getSerialNo());
                catMonitor.success();
                return result;
            }

            makeDecisionDTO.setCurrent(current);
            int delayLevel = needWait(makeDecisionDTO);

            // 發送MQ的消息體
            String content = JSON.toJSONString(makeDecisionDTO);
            if (delayLevel == DECISION_NO_DELAY_LEVEL) {
                produce.syncProducer(content, TAGS, keys, routingTopic);
            } else {
                produce.syncProducer(content, TAGS, keys, delayLevel, routingTopic);
            }

            logger.info("{},放入隊列等待執行,{},{}",
                    Constants.API_MAKE_DECISION,
                    content,
                    delayLevel);

            result.setCode(CodeEnum.SUCCESS);
            result.setSerialNo(makeDecisionDTO.getSerialNo());
            catMonitor.success();

            afterReceiveDecision(makeDecisionDTO, keys, combinationKey);
            return result;
        } catch (InterruptedException e) {
            result.setCode(CodeEnum.UNKNOWN_EXCEPTION);
            String errMsg = new StringJoiner(STR_COMMA)
                    .add(Constants.API_MAKE_DECISION)
                    .add("發生中斷")
                    .add(makeDecisionDTO.getSerialNo())
                    .toString();
            logger.error(errMsg, e);
            catMonitor.exception(e, errMsg);
            Thread.currentThread().interrupt();
            return result;
        } catch (RemotingException | MQClientException | MQBrokerException e) {
            result.setCode(CodeEnum.UNKNOWN_EXCEPTION);
            String errMsg = new StringJoiner(STR_COMMA)
                    .add(Constants.API_MAKE_DECISION)
                    .add("未知異常")
                    .add(makeDecisionDTO.getSerialNo())
                    .toString();
            catMonitor.exception(e, errMsg);
            logger.error(errMsg, e);
            return result;
        } catch (ServiceException e) {
            result.setCode(e.getCode());
            result.setMessage(e.getMessage());
            String errMsg = new StringJoiner(STR_COMMA)
                    .add(Constants.API_MAKE_DECISION)
                    .add(e.getMessage())
                    .add(makeDecisionDTO.getSerialNo())
                    .toString();
            catMonitor.exception(e, errMsg);
            logger.error(errMsg, e);
            return result;
        } finally {
            String response = JSON.toJSONString(result);
            long cost = System.currentTimeMillis() - current;
            try {
                keepApiLogThreadPool.execute(() -> {
                    ApiRequestLogDO apiLogDO = new ApiRequestLogDO();
                    apiLogDO.setName("makeStrategy");
                    apiLogDO.setType(Constants.API_LOG_TYPE_REQ);
                    apiLogDO.setUserId(makeDecisionDTO.getUserId());
                    apiLogDO.setSerialNo(makeDecisionDTO.getSerialNo());
                    apiLogDO.setProductCode(makeDecisionDTO.getProductCode());
                    apiLogDO.setSceneCode(makeDecisionDTO.getSceneCode());
                    apiLogDO.setRequest(request);
                    apiLogDO.setContent(JSON.toJSONString(makeDecisionDTO));
                    apiLogDO.setResponse(response);
                    apiLogDO.setCreateTime(new Date(current));
                    apiLogDO.setUpdateTime(new Date(System.currentTimeMillis()));
                    apiLogDO.setCostTime(cost);
                    apiRequestLogMapper.save(apiLogDO);
                });
            } catch (RejectedExecutionException e) {
                logger.error("RejectedExecutionException happen in {}:serialNo:{}", Constants.API_MAKE_DECISION, makeDecisionDTO.getSerialNo());
            }
            logger.info("{},執行完成,{},{},{},{},{},{},{}",
                    Constants.API_MAKE_DECISION,
                    makeDecisionDTO.getUserId(),
                    makeDecisionDTO.getProductCode(),
                    makeDecisionDTO.getSceneCode(),
                    result.getSerialNo(),
                    result.getCode(),
                    result.getMessage(),
                    cost);
            catMonitor.complete();
        }
    }

上面是改造後和改造前的代碼,思前想後,還是不敢輕易用於生產,代碼先記錄下,看看是否後續有新的靈感,可以優化成不錯的代碼。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章