1、表設(shè)計
CREATE TABLE `b_log_access` (
`fid` varchar(64) NOT NULL COMMENT '主鍵',
`request_name` varchar(100) DEFAULT NULL COMMENT '請求名稱',
`request_url` varchar(200) DEFAULT NULL COMMENT '請求地址',
`request_parameter` longtext COMMENT '請求參數(shù)',
`request_type` varchar(50) DEFAULT NULL COMMENT '請求模塊類型',
`request_result` longtext COMMENT '請求返回結(jié)果',
`request_appid` varchar(100) DEFAULT NULL COMMENT '請求應(yīng)用id',
`request_key` varchar(100) DEFAULT NULL COMMENT '請求應(yīng)用key例如密碼等',
`request_secret` varchar(1000) DEFAULT NULL COMMENT '請求參數(shù)密鑰',
`request_id` varchar(200) DEFAULT NULL COMMENT '請求關(guān)鍵id例如訂單號等',
`return_status` varchar(20) DEFAULT '200' COMMENT '請求返回狀態(tài)結(jié)果,默認:200成功',
`is_repeat` int(2) DEFAULT '0' COMMENT '失敗是否重復(fù)請求安疗;0:否沧烈,1:是',
`repeat_times` int(11) DEFAULT '0' COMMENT '針對請求失敗重復(fù)請求次數(shù)',
`is_remove` int(2) DEFAULT '0' COMMENT '請求成功是否根據(jù)移除時間自動移除; 0:否;1:是',
`remove_seconds` int(11) DEFAULT '10' COMMENT '根據(jù)最后更新時間自動移除時間晌纫,單位(s)',
`create_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創(chuàng)建時間',
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
`last_modifyer` varchar(64) DEFAULT 'N' COMMENT '記錄最后修改人 關(guān)聯(lián)b_user.fid',
`creater` varchar(64) DEFAULT 'N' COMMENT '記錄創(chuàng)建人 關(guān)聯(lián)b_user.fid',
`client_id` varchar(64) DEFAULT 'N' COMMENT '記錄所屬租戶 關(guān)聯(lián)b_client.fid',
PRIMARY KEY (`fid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;
2、邏輯構(gòu)思
1永丝、 數(shù)據(jù)異步插入 b_log_access表 的方法缸匪;
2、每10s執(zhí)行(請求失敗重復(fù)請求类溢、請求成功超時的請求)
3凌蔬、查詢請求失敗的請求列表、查詢請求成功的請求列表
4闯冷、超時時間算法函數(shù)
3砂心、代碼
package cn.ivg.service.impl;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import cn.invengo.common.utils.FastJsonUtils;
import cn.ivg.cscm.log.model.entity.LogAccessWithBLOBs;
import cn.ivg.cscm.log.service.IRepLogAccessService;
import cn.ivg.framework.comp.idGen.IdGenUtil;
import cn.ivg.model.LogAccessEx;
import cn.ivg.service.ILogAccessService;
import cn.ivg.service.RepeatCallback;
@Service
public class LogAccessServiceImpl implements ILogAccessService, InitializingBean {
static Logger log = LoggerFactory.getLogger(LogAccessServiceImpl.class);
/**
* 失敗重復(fù)執(zhí)行調(diào)用緩存類
*/
private Map<String, RepeatCallback> callbackMap = new ConcurrentHashMap<>();
/**
* 請求日志調(diào)度守護線程
*/
private Timer logAccessTimeSchedule = new Timer("Log_access_schedule");
@Autowired
private IRepLogAccessService repLogAccessService;
@Autowired
private Executor taskExecutor;
@Autowired
private IdGenUtil idGenUtil;
@Override
public void AsynRecordAccessLog(LogAccessEx record, boolean isprint) {
// TODO Auto-generated method stub
if (isprint) {
log.info(FastJsonUtils.toJSONString(record));
}
taskExecutor.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
record.setCreateDate(new Date());
record.setFid(idGenUtil.getId());
record.setLastUpdate(new Date());
repLogAccessService.insertSelective(record);
}
});
}
@Override
public void RegisterRepeatCallback(String requestType, RepeatCallback callback) {
// TODO Auto-generated method stub
if(Objects.isNull(callbackMap.get(requestType))){
callbackMap.put(requestType, callback);
}
}
@Override
public void afterPropertiesSet() throws Exception {
// 10秒執(zhí)行一次請求及移除
logAccessTimeSchedule.schedule(new DealAccessLogTask(), 10 * 1000, 10 * 1000);
}
@Override
public List<LogAccessWithBLOBs> repeatCallList() {
// TODO Auto-generated method stub
LogAccessWithBLOBs record = new LogAccessWithBLOBs();
record.setIsRepeat(Constant.REPEAT_OK);
record.setReturnStatus(Constant.STATUS_ERRO);
return repLogAccessService.select(record);
}
@Override
public List<LogAccessWithBLOBs> removeList() {
// TODO Auto-generated method stub
LogAccessWithBLOBs record = new LogAccessWithBLOBs();
record.setIsRemove(Constant.REMOVE_OK);
record.setReturnStatus(Constant.STATUS_OK);
return repLogAccessService.select(record);
}
@Override
public long diffNow(Date date) {
// TODO Auto-generated method stub
return System.currentTimeMillis() - date.getTime();
}
/**
* 分類處理請求日志任務(wù)
*
* @author tao.tang
* @date 2019/01/23
*/
class DealAccessLogTask extends TimerTask {
@Override
public void run() {
try {
// 失敗請求重復(fù)請求
List<LogAccessWithBLOBs> repeatList = repeatCallList();
for (LogAccessWithBLOBs repeat : repeatList) {
if (ObjectUtils.isEmpty(callbackMap.get(repeat.getRequestType()))) {
continue;
}
LogAccessEx repeatParam = new LogAccessEx();
BeanUtils.copyProperties(repeat, repeatParam);
//根據(jù)請求次數(shù)延長下一次重復(fù)調(diào)用時間
if (diffNow(repeatParam.getLastUpdate()) > repeatParam.getRepeatTimes() * Constant.REPEAT_BASE) {
repLogAccessService
.updateByPrimaryKeySelective(callbackMap.get(repeat.getRequestType()).excute(repeatParam));
}
}
// 處理已請求成功超時記錄
List<LogAccessWithBLOBs> removeList = removeList();
for (LogAccessWithBLOBs remove : removeList) {
//超時移除日志
if (diffNow(remove.getLastUpdate()) > remove.getRemoveSeconds() * 1000) {
repLogAccessService.deleteByPrimaryKey(remove.getFid());
}
}
} catch (Exception e) {
log.error("定時器Log_access_schedule執(zhí)行異常", e);
}
}
}
}