فهرست منبع

feat(淘宝账号): 新增 cis_limit 请求间隔(N 毫秒 1 次)

- tk_pool 新增 cis_limit 字段(毫秒,0 不限),与 qps_limit 同时生效
- 间隔不满足时归还已占用的 QPS 名额并尝试其他账号
- 隐藏号未提交上游时同时归还 QPS 与请求间隔名额
- 后台更新接口支持 cis_limit

需执行:ALTER TABLE tk_pool ADD COLUMN cis_limit INT NOT NULL DEFAULT 0 AFTER qps_limit;
dodo hold 1 هفته پیش
والد
کامیت
9166dfd764

+ 2 - 1
molilian.api/Controllers/admin/TaobaoController.cs

@@ -105,8 +105,9 @@ namespace molilian.api.Controllers
                     break;
                 case "time_range":
                 case "qps_limit":
+                case "cis_limit":
                     int.TryParse(val, out int iVal);
-                    if ("qps_limit".Equals(name) && iVal < 0) iVal = 0;
+                    if (("qps_limit".Equals(name) || "cis_limit".Equals(name)) && iVal < 0) iVal = 0;
                     result = new DBContext.Table("tk_pool")
                            .Add(name, iVal)
                            .Add("last_time", DateTime.Now)

+ 22 - 10
molilian.core/Core/taoke/TkPoolCore.cs

@@ -185,27 +185,39 @@ namespace molilian.core
             return null;
         }
 
+        private static readonly TimeSpan QpsWindow = TimeSpan.FromSeconds(1);
+
         private static bool TryAcquireQps(TkPoolDTO account)
         {
             if (account == null) return false;
 
-            return SpecialBusinessRateLimiter.TryAcquire(
-                $"tk_pool_qps:{account.id}",
-                account.qps_limit,
-                TimeSpan.FromSeconds(1));
+            long acquiredSinceTicks = DateTime.UtcNow.Ticks;
+            if (!SpecialBusinessRateLimiter.TryAcquire($"tk_pool_qps:{account.id}", account.qps_limit, QpsWindow))
+                return false;
+
+            // cis_limit:N 毫秒内只允许 1 次;未满足间隔时归还刚占用的 QPS 名额
+            if (account.cis_limit > 0 &&
+                !SpecialBusinessRateLimiter.TryAcquire($"tk_pool_cis:{account.id}", 1, TimeSpan.FromMilliseconds(account.cis_limit)))
+            {
+                if (account.qps_limit > 0)
+                    SpecialBusinessRateLimiter.Release($"tk_pool_qps:{account.id}", QpsWindow, acquiredSinceTicks);
+                return false;
+            }
+            return true;
         }
 
         /// <summary>
-        /// 归还分配账号时占用的 QPS 名额(转链未提交到 endpoint 时调用)
+        /// 归还分配账号时占用的 QPS / 请求间隔名额(转链未提交到 endpoint 时调用)
         /// </summary>
         public static void ReleaseQps(TkPoolDTO account, long acquiredSinceTicks)
         {
-            if (account == null || account.qps_limit <= 0) return;
+            if (account == null) return;
+
+            if (account.qps_limit > 0)
+                SpecialBusinessRateLimiter.Release($"tk_pool_qps:{account.id}", QpsWindow, acquiredSinceTicks);
 
-            SpecialBusinessRateLimiter.Release(
-                $"tk_pool_qps:{account.id}",
-                TimeSpan.FromSeconds(1),
-                acquiredSinceTicks);
+            if (account.cis_limit > 0)
+                SpecialBusinessRateLimiter.Release($"tk_pool_cis:{account.id}", TimeSpan.FromMilliseconds(account.cis_limit), acquiredSinceTicks);
         }
 
         private static async Task<bool> FilterNodesAsync(TkPoolDTO item, TkAction action)

+ 4 - 0
molilian.core/DTO/alimama/TkPoolDTO.cs

@@ -37,6 +37,10 @@
         public int current_daily_calls { get; set; } = 0;
         public int time_range { get; set; } = 0;
         public int qps_limit { get; set; } = 0;
+        /// <summary>
+        /// 请求间隔(毫秒),N 毫秒内只允许 1 次,0 表示不限制
+        /// </summary>
+        public int cis_limit { get; set; } = 0;
 
 
         public decimal draw_balance { get; set; } = 0;