123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- package com.fdkankan.contro.service.impl;
- import cn.hutool.core.collection.CollUtil;
- import cn.hutool.core.util.StrUtil;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import com.fdkankan.common.constant.CommonStatus;
- import com.fdkankan.common.constant.ErrorCode;
- import com.fdkankan.common.exception.BusinessException;
- import com.fdkankan.common.util.RandomUtil;
- import com.fdkankan.contro.entity.CameraType;
- import com.fdkankan.contro.entity.Scene3dNum;
- import com.fdkankan.contro.enums.CameraTypeEnum;
- import com.fdkankan.contro.mapper.IScene3dNumMapper;
- import com.fdkankan.contro.service.ICameraTypeService;
- import com.fdkankan.contro.service.IScene3dNumService;
- //import com.fdkankan.dingtalk.DingTalkSendUtils;
- import com.fdkankan.redis.constant.RedisKey;
- import com.fdkankan.redis.constant.RedisLockKey;
- import com.fdkankan.redis.util.RedisLockUtil;
- import com.fdkankan.redis.util.RedisUtil;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.cloud.context.config.annotation.RefreshScope;
- import org.springframework.stereotype.Service;
- import org.springframework.util.CollectionUtils;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Objects;
- import java.util.Set;
- import java.util.concurrent.CompletableFuture;
- import java.util.stream.Collectors;
- /**
- * <p>
- * 八目场景编码表 服务实现类
- * </p>
- *
- * @author dengsixing
- * @since 2021-12-23
- */
- @RefreshScope
- @Slf4j
- @Service
- 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
- private RedisUtil redisUtil;
- @Autowired
- private RedisLockUtil redisLockUtil;
- @Value("${scene.num.cachePageSize:500}")
- private int cachePageSize;
- @Value("${scene.num.threshold:1000}")
- private int threshold;
- @Value("${scene.num.prefix}")
- private String numPrefix;
- @Value("${scene.num.batchSize:100}")
- private int batchSize;
- @Value("${main.url}")
- private String mainUrl;
- // @Autowired
- // private DingTalkSendUtils dingTalkSendUtils;
- @Autowired
- private ICameraTypeService cameraTypeService;
- @Override
- public String generateSceneNum(Integer cameraType) throws Exception {
- // 从缓存中获取
- String sceneNum = redisUtil.lLeftPop(RedisKey.FDKANKAN_SCENE_NUMS);
- if(Objects.nonNull(sceneNum)){
- 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;
- }
- // 分布式加锁
- 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);
- this.updateUsedStatus(nums);
- }
- log.info("场景码加载缓存完成");
- } catch (Exception e) {
- log.error("场景码加载缓存失败", e);
- } finally {
- redisLockUtil.unlockLua(RedisLockKey.LOCK_FDKANKAN_SCENE_NUMS);
- }
- }
- private String addPrefix(String num,Integer camType){
- if(camType == null){
- return num;
- }
- CameraType cameraType = cameraTypeService.getByCamType(camType);
- if(Objects.isNull(cameraType)){
- return num;
- }
- return cameraType.getScenePrefix() + num;
- }
- @Override
- public void batchCreateSceneNum(boolean force) {
- 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++){//分批生成,每批次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();
- }
- }
- }
- private Set<String> turnCreateSceneNum(int cnt){
- Set<String> numSet = new HashSet<>();
- for(int i = 0; i < cnt; i++){
- numSet.add(numPrefix + RandomUtil.generateShortUuid());
- }
- return numSet;
- }
- @Override
- public List<String> findSceneNum(int pageSize) {
- return baseMapper.findSceneNum(pageSize);
- }
- @Override
- public void updateUsedStatus(List<String> nums) {
- baseMapper.updateUsedStatus(nums);
- }
- }
|