Parcourir la source

修改pdd调度逻辑

dodo hold il y a 1 an
Parent
commit
b83fbdde49

+ 5 - 0
molilian.api/Controllers/admin/PddUnionController.cs

@@ -156,6 +156,11 @@ namespace molilian.api.Controllers
                            .Add("last_time", DateTime.Now)
                            .Where("id=@id", new { id })
                            .Update();
+
+                    if (bVal && ("status".Equals(name) || "enable_parse".Equals(name)))
+                    {
+                        PddPoolCore.InitializeNewAccountUsage(id);
+                    }
                     break;
                 case "time_range":
                     int.TryParse(val, out int iVal);

Fichier diff supprimé car celui-ci est trop grand
+ 0 - 0
molilian.api/Properties/PublishProfiles/latest.pubxml.user


+ 1 - 1
molilian.core/Core/log/pdd.cs

@@ -152,7 +152,7 @@ namespace molilian.core
                 {
                     PddPoolCore.Disabled(response.accountId, response.accountName, response.reason);
                 }
-                if ("没有匹配账号".Equals(response.reason))
+                if (response.reason.Contains("没有匹配账号"))
                 {
                     PddPoolCore.AccountExhausted();
                 }

+ 0 - 1
molilian.core/Core/log/taobao.cs

@@ -40,7 +40,6 @@ namespace molilian.core
                             }
                         }
 
-
                         ////每日分表
                         //if (save_dailys_log)
                         {

+ 113 - 41
molilian.core/Core/pdd/PddPoolCore.cs

@@ -29,10 +29,7 @@ namespace molilian.core
         private static Dictionary<string, decimal> _incomeAmt = new();
         private static ConcurrentDictionary<int, DateTime> _suspend = new();
 
-        // 添加本地内存统计 - 线程安全
-        private static readonly ConcurrentDictionary<string, int> _dailyUsage = new();
-        private static volatile string _currentDay = DateTime.Now.ToString("yyyyMMdd");
-        private static readonly object _dayResetLock = new object(); // 专用于日期重置的锁
+        // 移除本地内存统计,改用 Redis 存储
 
         private static SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
 
@@ -58,73 +55,140 @@ namespace molilian.core
             }
 
             return list.Where(e => IsMatch(e, mode, accountid))
-                .OrderBy(account => GetCurrentDayUsage(account.id))
+                .OrderBy(account => GetCurrentDayUsageFromRedis(account.id))
                 .ThenBy(account => account.id) // 相同使用次数时按ID排序,确保稳定性
                 .FirstOrDefault();
         }
 
-        private static int GetCurrentDayUsage(int accountId)
+        private static int GetCurrentDayUsageFromRedis(int accountId)
         {
-            CheckAndResetDailyStats();
-            string currentDay = _currentDay; // 获取当前快照,避免在构建key过程中被修改
-            string key = $"{accountId}_{currentDay}";
-            return _dailyUsage.GetOrAdd(key, 0);
+            try
+            {
+                var today = DateTime.Now.ToString("yyyyMMdd");
+                string key = $"pdd_daily_usage:{accountId}:{today}";
+                return RedisHelper.Get<int>(key);
+            }
+            catch (Exception)
+            {
+                return 0;
+            }
         }
 
-        private static void CheckAndResetDailyStats()
+        internal static void UpdateAccountUsage(int accountId)
         {
-            var today = DateTime.Now.ToString("yyyyMMdd");
+            try
+            {
+                var today = DateTime.Now.ToString("yyyyMMdd");
+                string key = $"pdd_daily_usage:{accountId}:{today}";
 
-            // 使用volatile读取,如果日期相同则直接返回,避免锁开销
-            if (today == _currentDay) return;
+                // 递增计数并设置24小时过期时间
+                RedisHelper.IncrBy(key);
+                RedisHelper.Expire(key, 86400); // 24小时后自动过期
+            }
+            catch (Exception ex)
+            {
+                // 记录错误但不影响主流程
+                Console.WriteLine($"Failed to update account usage for {accountId}: {ex.Message}");
+            }
+        }
 
-            // 只有在日期不同时才尝试获取锁
-            lock (_dayResetLock)
+        /// <summary>
+        /// 获取当前所有账号的平均使用次数
+        /// </summary>
+        private static int GetAverageUsageCount()
+        {
+            try
             {
-                // 双重检查:再次验证日期是否需要重置
-                if (today != _currentDay)
-                {
-                    // 清空所有统计数据
-                    _dailyUsage.Clear();
+                var activeAccounts = List()?.Where(a => a.enable_parse).ToList();
+                if (activeAccounts == null || !activeAccounts.Any()) return 0;
 
-                    // 原子性更新当前日期(volatile写入)
-                    _currentDay = today;
+                var today = DateTime.Now.ToString("yyyyMMdd");
+                var totalUsage = 0;
+                var validCount = 0;
 
-                    // 可选:记录日期切换日志
-                    Console.WriteLine($"Daily stats reset for date: {today}");
+                foreach (var account in activeAccounts)
+                {
+                    var usage = GetCurrentDayUsageFromRedis(account.id);
+                    totalUsage += usage;
+                    validCount++;
                 }
+
+                return validCount > 0 ? totalUsage / validCount : 0;
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"Failed to get average usage count: {ex.Message}");
+                return 0;
             }
         }
 
-
-        internal static void UpdateAccountUsage(int accountId)
+        /// <summary>
+        /// 为新上线的账号设置平均使用次数,避免流量集中
+        /// </summary>
+        public static void InitializeNewAccountUsage(int accountId)
         {
-            CheckAndResetDailyStats();
-            string currentDay = _currentDay; // 获取当前快照,确保一致性
-            string key = $"{accountId}_{currentDay}";
+            try
+            {
+                var today = DateTime.Now.ToString("yyyyMMdd");
+                string key = $"pdd_daily_usage:{accountId}:{today}";
 
-            // 使用AddOrUpdate确保原子性递增
-            _dailyUsage.AddOrUpdate(key, 1, (k, oldValue) => oldValue + 1);
-        }
+                // 检查该账号今天是否已有使用记录
+                var currentUsage = RedisHelper.Get<int>(key);
+                if (currentUsage > 0) return; // 已有记录,不需要初始化
 
+                // 获取平均使用次数
+                var averageUsage = GetAverageUsageCount();
+                if (averageUsage > 0)
+                {
+                    // 设置为平均值,避免新账号因为使用次数为0而被优先选择
+                    RedisHelper.Set(key, averageUsage, 86400);
+                    Console.WriteLine($"Initialized account {accountId} with average usage: {averageUsage}");
+                }
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"Failed to initialize new account usage for {accountId}: {ex.Message}");
+            }
+        }
         /// <summary>
-        /// 获取当前统计信息(用于监控和调试)
+        /// 获取当前统计信息(用于监控和调试)- 改为从Redis获取
         /// </summary>
         internal static Dictionary<string, int> GetCurrentUsageSnapshot()
         {
-            CheckAndResetDailyStats();
-            return new Dictionary<string, int>(_dailyUsage);
+            try
+            {
+                var today = DateTime.Now.ToString("yyyyMMdd");
+                var pattern = $"pdd_daily_usage:*:{today}";
+
+                // 注意:这里只是示例,实际实现可能需要根据Redis客户端API调整
+                // 生产环境中应该避免使用KEYS命令,可以考虑其他方案
+                var result = new Dictionary<string, int>();
+                // TODO: 实现Redis pattern匹配获取所有相关keys
+                return result;
+            }
+            catch (Exception)
+            {
+                return new Dictionary<string, int>();
+            }
         }
 
         /// <summary>
-        /// 强制清理统计数据(仅用于测试或紧急情况)
+        /// 强制清理统计数据(仅用于测试或紧急情况)- Redis版本
         /// </summary>
         internal static void ForceClearStats()
         {
-            lock (_dayResetLock)
+            try
             {
-                _dailyUsage.Clear();
-                Console.WriteLine("Force cleared daily usage stats");
+                var today = DateTime.Now.ToString("yyyyMMdd");
+                var pattern = $"pdd_daily_usage:*:{today}";
+
+                // TODO: 实现Redis批量删除相关keys
+                // 生产环境中需要谨慎使用
+                Console.WriteLine("Force clear stats - Redis keys will auto-expire in 24h");
+            }
+            catch (Exception ex)
+            {
+                Console.WriteLine($"Failed to force clear stats: {ex.Message}");
             }
         }
 
@@ -364,7 +428,12 @@ namespace molilian.core
                     .Add("login_time", DateTime.Now)
                     .Where("id=@id", new { exist.id })
                     .Update();
-                if (status) _ = List(true);
+                if (status)
+                {
+                    _ = List(true);
+                    // 为重新上线的账号初始化使用次数
+                    InitializeNewAccountUsage(exist.id);
+                }
             }
             else
             {
@@ -382,6 +451,9 @@ namespace molilian.core
                     .Add("login_time", DateTime.Now)
                     .Add("status", 0)
                     .Create();
+
+                // 为新创建的账号初始化使用次数(如果将来会启用的话)
+                // InitializeNewAccountUsage(accountId); // 暂不调用,因为新创建的账号status=0
             }
 
             NotifyCore.Notify(new NifyMessage

+ 1 - 1
molilian.core/Plus/pdd/Crawler.cs

@@ -44,7 +44,7 @@ namespace molilian.core
             string cookies = _account.cookies.Trim();
 
 #if DEBUG
-            cookies = "DDJB_PASS_ID=bedd7aa97aff1edfe392ad8d2c8f1dc5; DDJB_LOGIN_SCENE=0";
+            //cookies = "DDJB_PASS_ID=bedd7aa97aff1edfe392ad8d2c8f1dc5; DDJB_LOGIN_SCENE=0";
 #endif
 
             string useragent = ProviderFakeUserAgent.RandomComputer;

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff