소스 검색

fix : 解决玩家接入线程锁的问题

bilingfeng 1 년 전
부모
커밋
a05884ffa4

+ 1 - 1
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/ManageApplication.java

@@ -23,7 +23,7 @@ public class ManageApplication {
 
     public static void main(String[] args) {
         SpringApplication.run(ManageApplication.class, args);
-        System.out.println("赞象Manage服务启动成功 <调试接入线程锁加日志> ( ´・・)ノ(._.`) \n" +
+        System.out.println("赞象Manage服务启动成功 <解决接入线程锁的问题> ( ´・・)ノ(._.`) \n" +
                 "___  ___  ___   _   _   ___  _____  _____ \n" +
                 "|  \\/  | / _ \\ | \\ | | / _ \\|  __ \\|  ___|\n" +
                 "| .  . |/ /_\\ \\|  \\| |/ /_\\ \\ |  \\/| |__  \n" +

+ 5 - 0
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/pojo/dto/KfWebSocketMsgDTO.java

@@ -55,6 +55,11 @@ public class KfWebSocketMsgDTO {
      */
     private ResultBean result;
 
+    /**
+     * 最新待接入玩家信息
+     */
+    private WaitUserBean lastWaitUser;
+
     /**
      * 游戏列表, 全量不分页
      */

+ 7 - 2
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/service/impl/KfAppletMsgServiceImpl.java

@@ -146,7 +146,7 @@ public class KfAppletMsgServiceImpl implements IKfAppletMsgService {
                     .eq(KfSessionUser::getOpenId, kfAppletMsgDTO.getFromUserName()));
         }
         //消息转发到redis频道
-        this.pushMessage(this.transform(kfRoom, gameApplet.getGameId(), kfRoomMsg, msgContent));
+        this.pushMessage(this.transform(kfRoom, gameApplet.getGameId(), kfAppletMsgDTO.getFromUserName(), kfRoomMsg, msgContent));
     }
 
     private void monitorWordHandle(GameApplet gameApplet, KfAppletMsgDTO kfAppletMsgDTO) {
@@ -243,7 +243,8 @@ public class KfAppletMsgServiceImpl implements IKfAppletMsgService {
         }
     }
 
-    private KfWebSocketMsgDTO transform(KfRoom kfRoom, Long gameId, KfRoomMsg kfRoomMsg, KfWebSocketMsgDTO.MsgContentBean msgContent) {
+    private KfWebSocketMsgDTO transform(KfRoom kfRoom, Long gameId, String openId, KfRoomMsg kfRoomMsg,
+                                        KfWebSocketMsgDTO.MsgContentBean msgContent) {
         //消息类型
         KfWebSocketMsgEnum kfWebSocketMsgEnum = kfRoom == null ? KfWebSocketMsgEnum.WEBSOCKET_MSG_WAIT_LIST
                 : KfWebSocketMsgEnum.WEBSOCKET_MSG_ROOM_MSG;
@@ -256,6 +257,10 @@ public class KfAppletMsgServiceImpl implements IKfAppletMsgService {
         //待接入消息
         if (Objects.equals(kfWebSocketMsgEnum, KfWebSocketMsgEnum.WEBSOCKET_MSG_WAIT_LIST)) {
             List<KfWebSocketMsgDTO.WaitUserBean> waitUserList = kfSessionUserService.getWaitUserList(gameId);
+            KfWebSocketMsgDTO.WaitUserBean waitUserBean = waitUserList.stream()
+                    .filter(waitUser -> Objects.equals(waitUser.getOpenId(), openId))
+                    .findFirst().orElse(null);
+            kfWebSocketMsgDTO.setLastWaitUser(waitUserBean);
             kfWebSocketMsgDTO.setWaitUserList(waitUserList);
         }
         //房间消息

+ 15 - 14
game-module/game-module-manage/src/main/java/com/zanxiang/game/module/manage/websocket/KfMsgWebsocketHandler.java

@@ -4,15 +4,13 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.zanxiang.erp.base.pojo.TokenInfo;
 import com.zanxiang.erp.security.util.SecurityUtil;
 import com.zanxiang.game.module.manage.constant.RedisKeyConstant;
-import com.zanxiang.game.module.manage.enums.KfOperateEnum;
-import com.zanxiang.game.module.manage.enums.KfRoomMsgOwnerEnum;
-import com.zanxiang.game.module.manage.enums.KfRoomMsgTypeEnum;
-import com.zanxiang.game.module.manage.enums.KfWebSocketMsgEnum;
+import com.zanxiang.game.module.manage.enums.*;
 import com.zanxiang.game.module.manage.pojo.dto.KfWebSocketMsgDTO;
 import com.zanxiang.game.module.manage.pojo.params.KfWebSocketMsgParam;
 import com.zanxiang.game.module.manage.service.*;
 import com.zanxiang.game.module.manage.service.api.KfWxApiService;
 import com.zanxiang.game.module.manage.utils.FileUtil;
+import com.zanxiang.game.module.manage.utils.RedisUtil;
 import com.zanxiang.game.module.mybatis.entity.KfRoom;
 import com.zanxiang.game.module.mybatis.entity.KfRoomMsg;
 import com.zanxiang.game.module.mybatis.entity.KfSessionUser;
@@ -33,7 +31,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.concurrent.TimeUnit;
 
 /**
  * @author : lingfeng
@@ -69,6 +66,9 @@ public class KfMsgWebsocketHandler implements WebSocketHandler {
     @Autowired
     private IKfQuickReplyService kfQuickReplyService;
 
+    @Autowired
+    private RedisUtil<String> redisUtil;
+
     @Autowired
     private RedisTemplate<String, String> redisTemplate;
 
@@ -328,11 +328,12 @@ public class KfMsgWebsocketHandler implements WebSocketHandler {
                 .roomList(onlineRoomList)
                 .build());
         //以防锁依然存在, 尝试释放锁, 锁如果不存在, 会抛出异常, 直接捕获不处理
+        String lockKey = RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + kfRoom.getOpenId();
         try {
-            log.error("结束会话释放锁, key : {}", RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + kfRoom.getOpenId());
-            distributedLockComponent.unlock(RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + kfRoom.getOpenId());
+            log.error("结束会话释放锁, key : {}", lockKey);
+            redisUtil.deleteCache(lockKey);
         } catch (Exception e) {
-            log.error("结束会话释放锁异常, key : {}, e : {}", RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + kfRoom.getOpenId(), e.getMessage());
+            log.error("结束会话释放锁异常, key : {}, e : {}", lockKey, e.getMessage());
         }
     }
 
@@ -390,15 +391,15 @@ public class KfMsgWebsocketHandler implements WebSocketHandler {
         //玩家信息, 判断玩家是否已经被接入
         KfSessionUser kfSessionUser = kfSessionUserService.getById(param.getOpenId());
         if (!kfSessionUser.getIsWait()) {
-            this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(), "玩家已被其他客服接入, 非待接入状态"));
+            this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(), "玩家非待接入状态(已被其他客服接入)"));
             return;
         }
         //触发玩家接入线程锁
-        log.error("玩家接入触发线程锁, key : {}", RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + param.getOpenId());
-        if (!distributedLockComponent.doLock(RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + param.getOpenId(),
-                0L, 3L, TimeUnit.MINUTES)) {
-            log.error("玩家接入线程锁, 锁定中, key : {}", RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + param.getOpenId());
-            this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(), "玩家已被其他客服接入"));
+        String lockKey = RedisKeyConstant.KF_MSG_USER_CONNECT_JOIN + param.getOpenId();
+        log.error("玩家接入触发线程锁, key : {}", lockKey);
+        if (!redisUtil.setIfAbsent(lockKey, lockKey, ExpireTimeEnum.FIVE_MIN.getTime())) {
+            log.error("玩家接入锁碰撞, 未接入成功, key : {}", lockKey);
+            this.sendMessage(session, KfWebSocketMsgDTO.fail(param.getWebSocketMsgType(), "玩家非待接入状态,(其他客服已抢先接入)"));
             return;
         }
         //玩家更新为已接入

+ 47 - 15
game-module/game-module-mybatis/src/main/java/com/zanxiang/game/module/mybatis/entity/SendMsgTask.java

@@ -1,8 +1,12 @@
 package com.zanxiang.game.module.mybatis.entity;
 
-import lombok.Data;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
 
-import java.time.LocalDate;
+import java.io.Serializable;
+import java.time.LocalDateTime;
 
 /**
  * @author : ZhangXianyu
@@ -10,41 +14,69 @@ import java.time.LocalDate;
  * @description : 发送消息任务实体类
  */
 @Data
-public class SendMsgTask {
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+@Builder
+@TableName("t_cp_send_msg_task")
+public class SendMsgTask implements Serializable {
+
+    private static final long serialVersionUID = 1L;
 
     /**
-     * 主键任务的ID
+     * 主键id
      */
+    @TableId(value = "id", type = IdType.AUTO)
     private Long id;
+
     /**
-     * 消息的内容
+     * 消息内容
      */
     private String msg;
+
+    /**
+     * 任务人数
+     */
+    private Long roleIdCount;
+
     /**
-     * 任务的名称
+     * 任务名称
      */
     private String taskName;
+
     /**
-     * 任务的条件
+     * 任务条件
      */
     private String taskCondition;
+
     /**
-     * 游戏名称
+     * 游戏id
      */
-    private String gameName;
+    private Long gameId;
+
     /**
-     * 创建人的用户ID
+     * 任务类型
      */
-    private Long createBy;
+    private String type;
+
     /**
-     * 创建时间
+     * 任务状态
      */
-    private LocalDate createTime;
+    private String status;
+
     /**
-     * 角色id列表
+     * 创建人
      */
-    private String roleIds;
+    private Long createBy;
 
+    /**
+     * 创建时间
+     */
+    private LocalDateTime createTime;
 
+    /**
+     * 更新时间
+     */
+    private LocalDateTime updateTime;
 
 }