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();
}
}
上面是改造後和改造前的代碼,思前想後,還是不敢輕易用於生產,代碼先記錄下,看看是否後續有新的靈感,可以優化成不錯的代碼。