فهرست منبع

优化请求过滤器

johnclot69 2 ماه پیش
والد
کامیت
67e6984912
1فایلهای تغییر یافته به همراه48 افزوده شده و 17 حذف شده
  1. 48 17
      incubator-core/src/main/java/com/incubator/core/net/ws/RequestFilter.java

+ 48 - 17
incubator-core/src/main/java/com/incubator/core/net/ws/RequestFilter.java

@@ -2,48 +2,79 @@ package com.incubator.core.net.ws;
 
 import com.incubator.common.net.Connection;
 
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.*;
 
 /**
- * 请求过滤器
+ * 请求过滤器(高并发优化版)
+ *
+ * 限制玩家的请求频率,防止过于频繁的请求导致服务过载。
  */
 public class RequestFilter {
 
     // 存储最近的请求时间戳:<请求唯一标识, 上次请求时间>
-    private static final Map<String, Long> requestTimestampMap = new ConcurrentHashMap<>();
+    private static final ConcurrentMap<String, Long> REQUEST_TIMESTAMP_MAP = new ConcurrentHashMap<>();
 
     // 最短间隔时间(单位:毫秒)
     private static final long MIN_REQUEST_INTERVAL = 1000; // 1秒
 
+    // 定期清理任务线程池
+    private static final ScheduledExecutorService CLEANUP_EXECUTOR = Executors.newSingleThreadScheduledExecutor(r -> {
+        Thread thread = new Thread(r);
+        thread.setName("RequestFilter-Cleanup-Thread");
+        thread.setDaemon(true); // 设置为守护线程
+        return thread;
+    });
+
+    // 静态初始化,启动清理任务
+    static {
+        CLEANUP_EXECUTOR.scheduleAtFixedRate(() -> cleanUp(10 * 60 * 1000), 0, 10, TimeUnit.MINUTES);
+    }
+
     /**
      * 检查是否允许处理请求
      *
      * @param conn 当前玩家连接
-     * @param cmd     消息命令号
+     * @param cmd  消息命令号
      * @return true 允许处理,false 拒绝处理
      */
     public static boolean isAllowed(Connection conn, int cmd) {
         String key = generateRequestKey(conn, cmd);
         long now = System.currentTimeMillis();
 
-        // 检查上次请求时间
-        Long lastRequestTime = requestTimestampMap.get(key);
-
-        if (lastRequestTime != null && (now - lastRequestTime < MIN_REQUEST_INTERVAL)) {
-            // 请求过于频繁,拒绝处理
-            return false;
-        }
-
-        // 更新请求时间
-        requestTimestampMap.put(key, now);
-        return true;
+        // 使用 compute 函数原子更新
+        return REQUEST_TIMESTAMP_MAP.compute(key, (k, lastTime) -> {
+            if (lastTime == null || now - lastTime >= MIN_REQUEST_INTERVAL) {
+                return now; // 更新为当前时间
+            }
+            return lastTime; // 保留旧值,表示频率超限
+        }) == now;
     }
 
     /**
      * 生成请求的唯一标识
+     *
+     * @param conn 玩家连接
+     * @param cmd  消息命令号
+     * @return 唯一标识字符串
      */
     private static String generateRequestKey(Connection conn, int cmd) {
-        return conn + ":" + cmd;
+        return conn.getPlayerId() + ":" + cmd;
+    }
+
+    /**
+     * 清理过期的请求记录,防止内存膨胀
+     *
+     * @param expirationTime 清理阈值,单位毫秒
+     */
+    public static void cleanUp(long expirationTime) {
+        long now = System.currentTimeMillis();
+        REQUEST_TIMESTAMP_MAP.entrySet().removeIf(entry -> now - entry.getValue() > expirationTime);
+    }
+
+    /**
+     * 停止清理任务,用于服务关闭时释放资源
+     */
+    public static void shutdown() {
+        CLEANUP_EXECUTOR.shutdownNow();
     }
 }