|
@@ -1,5 +1,6 @@
|
|
package com.fdkankan.contro.service.impl;
|
|
package com.fdkankan.contro.service.impl;
|
|
|
|
|
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
import cn.hutool.core.util.StrUtil;
|
|
import cn.hutool.core.util.StrUtil;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
@@ -11,6 +12,7 @@ import com.fdkankan.contro.entity.Scene3dNum;
|
|
import com.fdkankan.contro.enums.CameraTypeEnum;
|
|
import com.fdkankan.contro.enums.CameraTypeEnum;
|
|
import com.fdkankan.contro.mapper.IScene3dNumMapper;
|
|
import com.fdkankan.contro.mapper.IScene3dNumMapper;
|
|
import com.fdkankan.contro.service.IScene3dNumService;
|
|
import com.fdkankan.contro.service.IScene3dNumService;
|
|
|
|
+import com.fdkankan.dingtalk.DingTalkSendUtils;
|
|
import com.fdkankan.redis.constant.RedisKey;
|
|
import com.fdkankan.redis.constant.RedisKey;
|
|
import com.fdkankan.redis.constant.RedisLockKey;
|
|
import com.fdkankan.redis.constant.RedisLockKey;
|
|
import com.fdkankan.redis.util.RedisLockUtil;
|
|
import com.fdkankan.redis.util.RedisLockUtil;
|
|
@@ -18,6 +20,7 @@ import com.fdkankan.redis.util.RedisUtil;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
|
+import org.springframework.cloud.context.config.annotation.RefreshScope;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.util.CollectionUtils;
|
|
import org.springframework.util.CollectionUtils;
|
|
|
|
|
|
@@ -36,10 +39,16 @@ import java.util.stream.Collectors;
|
|
* @author dengsixing
|
|
* @author dengsixing
|
|
* @since 2021-12-23
|
|
* @since 2021-12-23
|
|
*/
|
|
*/
|
|
|
|
+@RefreshScope
|
|
@Slf4j
|
|
@Slf4j
|
|
@Service
|
|
@Service
|
|
public class Scene3dNumServiceImpl extends ServiceImpl<IScene3dNumMapper, Scene3dNum> implements IScene3dNumService {
|
|
public class Scene3dNumServiceImpl extends ServiceImpl<IScene3dNumMapper, Scene3dNum> implements IScene3dNumService {
|
|
|
|
|
|
|
|
+ public static final String DINGTALK_MSG_PATTERN =
|
|
|
|
+ "**环境**: %s\n\n" +
|
|
|
|
+ "**标题**: %s\n\n" +
|
|
|
|
+ "**告警信息**: %s\n\n";
|
|
|
|
+
|
|
@Autowired
|
|
@Autowired
|
|
private RedisUtil redisUtil;
|
|
private RedisUtil redisUtil;
|
|
@Autowired
|
|
@Autowired
|
|
@@ -47,54 +56,71 @@ public class Scene3dNumServiceImpl extends ServiceImpl<IScene3dNumMapper, Scene3
|
|
|
|
|
|
@Value("${scene.num.cachePageSize:500}")
|
|
@Value("${scene.num.cachePageSize:500}")
|
|
private int cachePageSize;
|
|
private int cachePageSize;
|
|
- @Value("${scene.num.threshold:10000}")
|
|
|
|
|
|
+ @Value("${scene.num.threshold:1000}")
|
|
private int threshold;
|
|
private int threshold;
|
|
- @Value("${scene.num.prefix:V4-}")
|
|
|
|
|
|
+ @Value("${scene.num.prefix}")
|
|
private String numPrefix;
|
|
private String numPrefix;
|
|
@Value("${scene.num.batchSize:100}")
|
|
@Value("${scene.num.batchSize:100}")
|
|
private int batchSize;
|
|
private int batchSize;
|
|
|
|
+ @Value("${main.url}")
|
|
|
|
+ private String mainUrl;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private DingTalkSendUtils dingTalkSendUtils;
|
|
|
|
|
|
@Override
|
|
@Override
|
|
- public String generateSceneNum(Integer cameraType){
|
|
|
|
|
|
+ public String generateSceneNum(Integer cameraType) throws Exception {
|
|
// 从缓存中获取
|
|
// 从缓存中获取
|
|
String sceneNum = redisUtil.lLeftPop(RedisKey.FDKANKAN_SCENE_NUMS);
|
|
String sceneNum = redisUtil.lLeftPop(RedisKey.FDKANKAN_SCENE_NUMS);
|
|
if(Objects.nonNull(sceneNum)){
|
|
if(Objects.nonNull(sceneNum)){
|
|
return addPrefix(sceneNum,cameraType);
|
|
return addPrefix(sceneNum,cameraType);
|
|
}
|
|
}
|
|
|
|
+ //为了防止场景量暴增导致定时任务来还不急处理,如果上面redis获取不到,需要调用一下生成场景码方法
|
|
|
|
+ log.warn("定时任务没有生成足够的场景码,此处实时调用批量生成场景码程序");
|
|
|
|
+ this.generateSceneNumHandler();
|
|
|
|
+ Thread.sleep(5000L);
|
|
|
|
+ // 从缓存中获取
|
|
|
|
+ sceneNum = redisUtil.lLeftPop(RedisKey.FDKANKAN_SCENE_NUMS);
|
|
|
|
+ if(Objects.isNull(sceneNum)){
|
|
|
|
+ String content = String.format(this.DINGTALK_MSG_PATTERN, mainUrl, "场景码穷尽告警", "场景计算获取场景码失败");
|
|
|
|
+ dingTalkSendUtils.sendActioncardMsgToDingRobot(content, "场景码穷尽告警");
|
|
|
|
+ throw new Exception("场景计算获取场景码失败");
|
|
|
|
+ }
|
|
|
|
+ return addPrefix(sceneNum,cameraType);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void generateSceneNumHandler() {
|
|
|
|
+ boolean lock = redisLockUtil.lock(RedisLockKey.LOCK_FDKANKAN_SCENE_NUMS, RedisKey.EXPIRE_TIME_30_MINUTE);
|
|
|
|
+ if(!lock){
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
// 分布式加锁
|
|
// 分布式加锁
|
|
- boolean lock = redisLockUtil.lock(RedisLockKey.LOCK_FDKANKAN_SCENE_NUMS, RedisKey.EXPIRE_TIME_10_MINUTE);
|
|
|
|
- if (lock) {
|
|
|
|
- try {
|
|
|
|
- log.info("开始加载场景码缓存");
|
|
|
|
- List<String> nums = this.findSceneNum(cachePageSize);
|
|
|
|
- if(CollectionUtils.isEmpty(nums)){
|
|
|
|
- batchCreateSceneNum(true);
|
|
|
|
- nums = this.findSceneNum(cachePageSize);
|
|
|
|
- }else{
|
|
|
|
- CompletableFuture.runAsync(() -> batchCreateSceneNum(false));
|
|
|
|
- }
|
|
|
|
|
|
+ try {
|
|
|
|
+ //检查mysql码池中是否有足够的未使用场景,不够时,需要创建一批
|
|
|
|
+ batchCreateSceneNum(false);
|
|
|
|
+
|
|
|
|
+ //检查redis中场景码是否少于指定缓存数量,少于时,需要从码池中获取
|
|
|
|
+ long redisCnt = redisUtil.lGetSize(RedisKey.FDKANKAN_SCENE_NUMS);
|
|
|
|
+ if(redisCnt >= cachePageSize){
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ log.info("开始加载场景码缓存");
|
|
|
|
+ List<String> nums = this.findSceneNum(cachePageSize);
|
|
|
|
+ if(CollUtil.isEmpty(nums) || nums.size() < cachePageSize){
|
|
|
|
+ String content = String.format(this.DINGTALK_MSG_PATTERN, mainUrl, "场景码穷尽告警", "场景码表中未使用状态少于" + cachePageSize);
|
|
|
|
+ dingTalkSendUtils.sendActioncardMsgToDingRobot(content, "场景码穷尽告警");
|
|
|
|
+ }
|
|
|
|
+ if(CollUtil.isNotEmpty(nums)){
|
|
redisUtil.lRightPushAll(RedisKey.FDKANKAN_SCENE_NUMS, nums);
|
|
redisUtil.lRightPushAll(RedisKey.FDKANKAN_SCENE_NUMS, nums);
|
|
this.updateUsedStatus(nums);
|
|
this.updateUsedStatus(nums);
|
|
- log.info("场景码加载缓存完成");
|
|
|
|
- } catch (Exception e) {
|
|
|
|
- log.error("场景码加载缓存失败", e);
|
|
|
|
- } finally {
|
|
|
|
- redisLockUtil.unlockLua(RedisLockKey.LOCK_FDKANKAN_SCENE_NUMS);
|
|
|
|
}
|
|
}
|
|
- }else{
|
|
|
|
- // 等待2秒加载缓存
|
|
|
|
- try {
|
|
|
|
- Thread.sleep(2000);
|
|
|
|
- } catch (InterruptedException e) {
|
|
|
|
- e.printStackTrace();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- sceneNum = redisUtil.lLeftPop(RedisKey.FDKANKAN_SCENE_NUMS);
|
|
|
|
- if(StrUtil.isEmpty(sceneNum)){
|
|
|
|
- log.error("场景码加载失败");
|
|
|
|
- throw new BusinessException(ErrorCode.FAILURE_CODE_5053);
|
|
|
|
|
|
+ log.info("场景码加载缓存完成");
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("场景码加载缓存失败", e);
|
|
|
|
+ } finally {
|
|
|
|
+ redisLockUtil.unlockLua(RedisLockKey.LOCK_FDKANKAN_SCENE_NUMS);
|
|
}
|
|
}
|
|
- return addPrefix(sceneNum,cameraType);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
private static String addPrefix( String num,Integer cameraType){
|
|
private static String addPrefix( String num,Integer cameraType){
|
|
@@ -106,35 +132,26 @@ public class Scene3dNumServiceImpl extends ServiceImpl<IScene3dNumMapper, Scene3
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public void batchCreateSceneNum(boolean force) {
|
|
public void batchCreateSceneNum(boolean force) {
|
|
- String lockKey = String.format(RedisLockKey.LOCK_BATCH_CREATE_NUM);
|
|
|
|
- boolean lock = redisLockUtil.lock(lockKey, RedisKey.EXPIRE_TIME_10_MINUTE);
|
|
|
|
- if(!lock){
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- try {
|
|
|
|
- if (!force) {
|
|
|
|
- long count = this.count(new LambdaQueryWrapper<Scene3dNum>().eq(Scene3dNum::getUsed, CommonStatus.NO.code()));
|
|
|
|
- if (count > threshold) {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ if (!force) {
|
|
|
|
+ long count = this.count(new LambdaQueryWrapper<Scene3dNum>().eq(Scene3dNum::getUsed, CommonStatus.NO.code()));
|
|
|
|
+ if (count > threshold) {
|
|
|
|
+ return;
|
|
}
|
|
}
|
|
- int batchCnt = threshold / batchSize + (threshold % batchSize > 0 ? 1 : 0);
|
|
|
|
- for (int i = 0; i < batchCnt; i++){
|
|
|
|
- Set<String> numSet = this.turnCreateSceneNum(batchSize);
|
|
|
|
- List<Scene3dNum> scene3dNumList = numSet.parallelStream().map(num -> {
|
|
|
|
- Scene3dNum scene3dNum = new Scene3dNum();
|
|
|
|
- scene3dNum.setNum(num);
|
|
|
|
- return scene3dNum;
|
|
|
|
- }).collect(Collectors.toList());
|
|
|
|
- try{
|
|
|
|
- this.saveBatch(scene3dNumList);
|
|
|
|
- }catch (Exception e){
|
|
|
|
- log.error("场景码插入异常!");
|
|
|
|
- e.printStackTrace();
|
|
|
|
- }
|
|
|
|
|
|
+ }
|
|
|
|
+ int batchCnt = threshold / batchSize + (threshold % batchSize > 0 ? 1 : 0);//批次数
|
|
|
|
+ for (int i = 0; i < batchCnt; i++){//分批生成,每批次batchSize个
|
|
|
|
+ Set<String> numSet = this.turnCreateSceneNum(batchSize);
|
|
|
|
+ List<Scene3dNum> scene3dNumList = numSet.parallelStream().map(num -> {
|
|
|
|
+ Scene3dNum scene3dNum = new Scene3dNum();
|
|
|
|
+ scene3dNum.setCode(num);
|
|
|
|
+ return scene3dNum;
|
|
|
|
+ }).collect(Collectors.toList());
|
|
|
|
+ try{
|
|
|
|
+ this.saveBatch(scene3dNumList);
|
|
|
|
+ }catch (Exception e){
|
|
|
|
+ log.error("场景码插入异常!");
|
|
|
|
+ e.printStackTrace();
|
|
}
|
|
}
|
|
- }finally {
|
|
|
|
- redisLockUtil.unlockLua(lockKey);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|