Bladeren bron

refactor(消费服务): 消费机获取token接口增加了redis分布式锁

luo.yibo@datuai.com 11 maanden geleden
bovenliggende
commit
f70a7821eb

+ 53 - 17
ruoyi-server/ruoyi-server-consume/src/main/java/org/dromara/server/consume/business/TermBusiness.java

@@ -11,6 +11,7 @@ import org.dromara.common.core.config.DefaultConfig;
 import org.dromara.common.core.constant.DefaultConstants;
 import org.dromara.common.core.domain.R;
 import org.dromara.common.core.enums.SystemUseTypeEnum;
+import org.dromara.common.core.exception.ServiceException;
 import org.dromara.common.core.utils.StringUtils;
 import org.dromara.common.redis.utils.RedisUtils;
 import org.dromara.server.consume.cache.TokenManager;
@@ -22,9 +23,11 @@ import org.dromara.server.consume.domain.vo.yc.TermToken;
 import org.dromara.server.consume.service.IXfTermService;
 import org.dromara.system.api.RemoteUserService;
 import org.dromara.system.api.domain.vo.RemoteUserVo;
+import org.redisson.api.RLock;
 import org.springframework.stereotype.Service;
 
 import java.text.MessageFormat;
+import java.time.Duration;
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
 import java.util.Date;
@@ -32,6 +35,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
 
 /**
  * @ClassName TermBusiness
@@ -110,24 +114,30 @@ public class TermBusiness {
 
     public R<TermToken> getTermTokenNew(Long termNo, String admin, String pwd){
         String strTermNo = String.valueOf(termNo);
-        String cacheName = StringUtils.format("{}:term_token", defaultConfig.getTenantId());
-        TermToken termToken =  RedisUtils.getCacheMapValue(cacheName, strTermNo);
-        if(ObjectUtil.isEmpty(termToken)|| termToken.getExpireTime() < new Date().getTime()){
-            LocalDateTime ldt = LocalDateTime.of(2000, 1, 1, 0, 0, 0);
-            Date minDate = Date.from(ldt.toInstant(ZoneOffset.of("+8")));
-
-            LocalDateTime now = LocalDateTime.now();
-            LocalDateTime expireTime = now.plusHours(4);
-
-            RemoteXfTermVo remoteVo = remoteTermService.queryByNo(termNo, defaultConfig.getTenantId());
-            if (ObjectUtil.isEmpty(remoteVo)) {
-                return R.fail(MessageFormat.format("机号为[{0}]的设备不存在", termNo), null);
+        String tenantId = defaultConfig.getTenantId();
+        String cacheName = StringUtils.format("{}:term_token:{}", tenantId, termNo);
+        TermToken termToken =  RedisUtils.getCacheObject(cacheName);
+        if(ObjectUtil.isEmpty(termToken)|| termToken.getExpireTime() < System.currentTimeMillis()) {
+            String lockKey = "LOCK:" + cacheName + ":" + strTermNo;
+            RLock lock = RedisUtils.getClient().getLock(lockKey);
+            try {
+                // 尝试加锁,等待2秒,锁自动释放时间10秒
+                if (lock.tryLock(2, 10, TimeUnit.SECONDS)) {
+                    // 双重检查(Double-Check)
+                    termToken = RedisUtils.getCacheObject(cacheName);
+                    if (ObjectUtil.isEmpty(termToken) || termToken.getExpireTime() < System.currentTimeMillis()) {
+                        // 创建新token
+                        termToken = createAndSaveToken(termNo, admin, strTermNo, cacheName);
+                    }
+                }
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                log.error("获取锁中断", e);
+            } finally {
+                if (lock.isLocked() && lock.isHeldByCurrentThread()) {
+                    lock.unlock();
+                }
             }
-
-            termToken = new TermToken(strTermNo, UUID.randomUUID().toString(), admin, new Date().getTime(), minDate.getTime(),
-                                      Date.from(expireTime.toInstant(ZoneOffset.of("+8"))).getTime(), remoteVo.getRoomName());
-
-            RedisUtils.setCacheMapValue(cacheName, strTermNo, termToken);
         }
         return R.ok(MessageFormat.format("获取token成功,设备编号[{0}],账号[{1}]", termNo, admin), termToken);
     }
@@ -267,4 +277,30 @@ public class TermBusiness {
         return termInfo;
     }
 
+    private TermToken createAndSaveToken(Long termNo, String admin, String strTermNo, String cacheName) {
+        // 设备查询
+        RemoteXfTermVo remoteVo = remoteTermService.queryByNo(termNo, defaultConfig.getTenantId());
+        if (ObjectUtil.isEmpty(remoteVo)) {
+            throw new ServiceException(MessageFormat.format("机号为[{0}]的设备不存在", termNo));
+        }
+
+        // 创建token(简化时间处理)
+        long now = System.currentTimeMillis();
+        long expireTime = now + TimeUnit.HOURS.toMillis(4); // 4小时后过期
+
+        TermToken newToken = new TermToken(
+            strTermNo,
+            UUID.randomUUID().toString(),
+            admin,
+            now,
+            Date.from(LocalDateTime.of(2000, 1, 1, 0, 0).toInstant(ZoneOffset.of("+8"))).getTime(),
+            expireTime,
+            remoteVo.getRoomName()
+        );
+
+        // 写入Redis
+        RedisUtils.setCacheObject(cacheName, newToken, Duration.ofHours(4));
+        return newToken;
+    }
+
 }