Quellcode durchsuchen

!856 分布式环境下,增加机器码设置扩展类
Merge pull request !856 from 适可而止/next

zuohuaijun vor 2 Jahren
Ursprung
Commit
eceba45254

+ 2 - 1
Admin.NET/Admin.NET.Application/Configuration/App.json

@@ -33,8 +33,9 @@
     "SignalRSupport": true // 启用 SignalR 跨域支持
   },
   "SnowId": {
+    "CachePrefix": "adminnet:workerId:",
     "WorkerId": 1, // 机器码 全局唯一
-    "WorkerIdBitLength": 1, // 机器码位长 默认值6,取值范围 [1, 19]
+    "WorkerIdBitLength": 2, // 机器码位长 默认值6,取值范围 [1, 19]
     "SeqBitLength": 6 // 序列数位长 默认值6,取值范围 [3, 21](建议不小于4,值越大性能越高、Id位数也更长)
   },
   "Cryptogram": {

+ 119 - 0
Admin.NET/Admin.NET.Core/Extension/YitIdHelperExtension.cs

@@ -0,0 +1,119 @@
+using Microsoft.Extensions.Hosting;
+
+namespace Admin.NET.Core;
+
+/// <summary>
+/// YitIdHelper 自动获取WorkId拓展
+/// </summary>
+public static class YitIdHelperExtension
+{
+    private const int MinWorkId = 0;
+    private const int MaxWorkId = 63;
+
+    private const string MainLockName = "IdGen:WorkerId:Lock";
+    private const string MainValueKey = "IdGen:WorkerId:Value";
+
+    private static readonly List<string> _workIds = new();
+    private static SnowIdOptions _options;
+
+    public static void AddYitIdHelper(this IServiceCollection services, SnowIdOptions options)
+    {
+        _options = options;
+
+        // 排除开发环境和Windows服务器
+        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || App.WebHostEnvironment.IsDevelopment())
+        {
+            YitIdHelper.SetIdGenerator(_options);
+            return;
+        }
+
+        var maxLength = Math.Pow(2, _options.WorkerIdBitLength.ParseToDouble());
+
+        for (int i = 0; i < maxLength; i++)
+        {
+            _workIds.Add(i.ToString());
+        }
+
+        Random ran = new();
+        int milliseconds = ran.Next(10, 1000);
+        Thread.Sleep(milliseconds);
+
+        SetWorkId();
+    }
+
+    private static void SetWorkId()
+    {
+        var lockName = $"{_options.CachePrefix}{MainLockName}";
+        var valueKey = $"{_options.CachePrefix}{MainValueKey}"; ;
+
+        var client = App.GetService<ICache>();
+        var redisLock = client.AcquireLock(lockName, 10000, 15000, true);
+        var keys = client.Keys.Where(o => o.Contains($"{_options.CachePrefix}{valueKey}:*"));
+
+        var tempWorkIds = _workIds;
+        foreach (var key in keys)
+        {
+            var tempWorkId = key[key.LastIndexOf(":", StringComparison.Ordinal)..];
+            tempWorkIds.Remove(tempWorkId);
+        }
+
+        try
+        {
+            string workIdKey = "";
+            foreach (var item in tempWorkIds)
+            {
+                string workIdStr = "";
+
+                workIdStr = item;
+                workIdKey = $"{valueKey}:{workIdStr}";
+                var exist = client.Get<bool>(workIdKey);
+
+                if (exist)
+                {
+                    workIdKey = "";
+                    continue;
+                }
+
+                Console.WriteLine($"###########当前应用WorkId:【{workIdStr}】###########");
+
+                long workId = workIdStr.ParseToLong();
+
+                if (workId is < MinWorkId or > MaxWorkId)
+                    continue;
+
+                // 设置雪花Id算法机器码
+                YitIdHelper.SetIdGenerator(new IdGeneratorOptions
+                {
+                    WorkerId = (ushort)workId,
+                    WorkerIdBitLength = _options.WorkerIdBitLength,
+                    SeqBitLength = _options.SeqBitLength
+                });
+
+                client.Set(workIdKey, true, TimeSpan.FromSeconds(15));
+
+                break;
+            }
+
+            if (string.IsNullOrWhiteSpace(workIdKey)) throw Oops.Oh("未设置有效的机器码,启动失败");
+
+            // 开一个任务设置当前workId过期时间
+            Task.Run(() =>
+            {
+                while (true)
+                {
+                    client.SetExpire(workIdKey, TimeSpan.FromSeconds(15));
+                    //Task.Delay(5000);
+                    Thread.Sleep(10000);
+                }
+            });
+        }
+        catch (Exception e)
+        {
+            throw Oops.Oh($"{e.Message};{e.StackTrace};{e.StackTrace}");
+        }
+        finally
+        {
+            redisLock?.Dispose();
+        }
+    }
+}

+ 4 - 0
Admin.NET/Admin.NET.Core/Option/SnowIdOptions.cs

@@ -14,4 +14,8 @@ namespace Admin.NET.Core;
 /// </summary>
 public sealed class SnowIdOptions : IdGeneratorOptions, IConfigurableOptions
 {
+    /// <summary>
+    /// 缓存前缀
+    /// </summary>
+    public string CachePrefix { get; set; }
 }

+ 3 - 0
Admin.NET/Admin.NET.Web.Core/Startup.cs

@@ -144,6 +144,9 @@ public class Startup : AppStartup
         // 验证码
         services.AddCaptcha();
 
+        // 分布式环境-机器码设置
+        services.AddYitIdHelper(App.GetOptions<SnowIdOptions>());
+
         // 控制台logo
         services.AddConsoleLogo();
     }