AidopInstanceIdentity.cs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. using System.Diagnostics;
  2. using System.Reflection;
  3. namespace Admin.NET.Plugin.AiDOP.Infrastructure;
  4. /// <summary>
  5. /// 本进程在 ETL 执行机注册表(<c>ado_etl_instance</c>)中的身份。
  6. ///
  7. /// <para><b>为什么要进程级唯一</b>:同一台机器可能同时跑多个后端进程(开发时的
  8. /// <c>dotnet run</c> + 已发布的服务),它们连的是同一个库。若只用机器名做标识,
  9. /// 两个进程会抢同一行注册记录,指派给谁都说不清。故标识取
  10. /// <c>机器名:进程ID:启动时间</c> 三段,进程重启后必然产生新行。</para>
  11. ///
  12. /// <para><b>为什么用启动时间而不是随机 GUID</b>:运维要在页面上认出「这是哪台、什么时候起的」。
  13. /// GUID 每次重启都变且不可读,排障时无法和服务器上的进程对上。</para>
  14. ///
  15. /// <para>静态只读,进程生命周期内不变,可在任意线程反复读取。</para>
  16. /// </summary>
  17. public static class AidopInstanceIdentity
  18. {
  19. static AidopInstanceIdentity()
  20. {
  21. MachineName = SafeGet(() => Environment.MachineName, "unknown-host");
  22. ProcessId = SafeGet(() => Environment.ProcessId, 0);
  23. StartedAt = SafeGet(() => Process.GetCurrentProcess().StartTime, DateTime.Now);
  24. AppVersion = SafeGet(
  25. () => Assembly.GetEntryAssembly()?.GetName().Version?.ToString(),
  26. null);
  27. // 长度受 ado_etl_instance.instance_id 的 200 字符约束;机器名过长时截断,
  28. // 进程ID + 启动时间仍能保证同机不同进程互不覆盖。
  29. var host = MachineName.Length > 120 ? MachineName[..120] : MachineName;
  30. InstanceId = $"{host}:{ProcessId}:{StartedAt:yyyyMMddHHmmss}";
  31. }
  32. /// <summary>注册表主键语义列,形如 <c>DESKTOP-ABC:12345:20260925071200</c>。</summary>
  33. public static string InstanceId { get; }
  34. public static string MachineName { get; }
  35. public static int ProcessId { get; }
  36. /// <summary>本进程启动时间。取不到时退化为静态构造时刻,不影响唯一性。</summary>
  37. public static DateTime StartedAt { get; }
  38. /// <summary>入口程序集版本,仅供页面展示与排障;取不到为 null。</summary>
  39. public static string AppVersion { get; }
  40. /// <summary>
  41. /// 身份计算不得成为启动故障点:容器内取进程启动时间、受限环境取机器名都可能抛异常,
  42. /// 一旦抛出会让整个插件装配失败,而这里拿到的只是展示用信息。
  43. /// </summary>
  44. private static T SafeGet<T>(Func<T> get, T fallback)
  45. {
  46. try { return get(); }
  47. catch { return fallback; }
  48. }
  49. }