Procházet zdrojové kódy

😎优化高频日志入库性能,升级Furion v4.9.1.58

zuohuaijun před 2 roky
rodič
revize
4e234ce63d

+ 3 - 3
Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj

@@ -21,9 +21,9 @@
     <PackageReference Include="AspNet.Security.OAuth.Gitee" Version="6.0.15" />
     <PackageReference Include="AspNet.Security.OAuth.Weixin" Version="6.0.15" />
     <PackageReference Include="AspNetCoreRateLimit" Version="5.0.0" />
-    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.1.57" />
-    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.1.57" />
-    <PackageReference Include="Furion.Pure" Version="4.9.1.57" />
+    <PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.1.58" />
+    <PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.1.58" />
+    <PackageReference Include="Furion.Pure" Version="4.9.1.58" />
     <PackageReference Include="IPTools.China" Version="1.6.0" />
     <PackageReference Include="Lazy.Captcha.Core" Version="2.0.6" />
     <PackageReference Include="Magicodes.IE.Excel" Version="2.7.5.1" />

+ 12 - 17
Admin.NET/Admin.NET.Core/Logging/DatabaseLoggingWriter.cs

@@ -12,23 +12,19 @@ namespace Admin.NET.Core;
 public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
 {
     private readonly IServiceScope _serviceScope;
-    private readonly SqlSugarRepository<SysLogVis> _sysLogVisRep; // 访问日志
-    private readonly SqlSugarRepository<SysLogOp> _sysLogOpRep; // 操作日志
-    private readonly SqlSugarRepository<SysLogEx> _sysLogExRep; // 异常日志
+    private readonly ISqlSugarClient _db;
     private readonly SysConfigService _sysConfigService; // 参数配置服务
     private readonly ILogger<DatabaseLoggingWriter> _logger; // 日志组件
 
     public DatabaseLoggingWriter(IServiceScopeFactory scopeFactory)
     {
         _serviceScope = scopeFactory.CreateScope();
-        _sysLogVisRep = _serviceScope.ServiceProvider.GetRequiredService<SqlSugarRepository<SysLogVis>>();
-        _sysLogOpRep = _serviceScope.ServiceProvider.GetRequiredService<SqlSugarRepository<SysLogOp>>();
-        _sysLogExRep = _serviceScope.ServiceProvider.GetRequiredService<SqlSugarRepository<SysLogEx>>();
+        _db = _serviceScope.ServiceProvider.GetRequiredService<ISqlSugarClient>();
         _sysConfigService = _serviceScope.ServiceProvider.GetRequiredService<SysConfigService>();
         _logger = _serviceScope.ServiceProvider.GetRequiredService<ILogger<DatabaseLoggingWriter>>();
     }
 
-    public async void Write(LogMessage logMsg, bool flush)
+    public async Task WriteAsync(LogMessage logMsg, bool flush)
     {
         var jsonStr = logMsg.Context?.Get("loggingMonitor")?.ToString();
         if (jsonStr == null) return;
@@ -67,7 +63,7 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
             // 记录异常日志并发送邮件
             if (logMsg.Exception != null || loggingMonitor.exception != null)
             {
-                await _sysLogExRep.InsertAsync(new SysLogEx
+                await _db.Insertable(new SysLogEx
                 {
                     ControllerName = loggingMonitor.controllerName,
                     ActionName = loggingMonitor.actionTypeName,
@@ -95,18 +91,17 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
                     CreateUserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
                     TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : long.Parse(tenantId),
                     LogLevel = logMsg.LogLevel
-                });
+                }).ExecuteCommandAsync();
 
                 // 将异常日志发送到邮件
                 await App.GetRequiredService<IEventPublisher>().PublishAsync("Send:ErrorMail", loggingMonitor.exception);
-
                 return;
             }
 
-            // 记录访问日志-登录
+            // 记录访问日志-登录退
             if (loggingMonitor.actionName == "userInfo" || loggingMonitor.actionName == "logout")
             {
-                await _sysLogVisRep.InsertAsync(new SysLogVis
+                await _db.Insertable(new SysLogVis
                 {
                     ControllerName = loggingMonitor.controllerName,
                     ActionName = loggingMonitor.actionTypeName,
@@ -125,15 +120,14 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
                     CreateUserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
                     TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : long.Parse(tenantId),
                     LogLevel = logMsg.LogLevel
-                });
-
+                }).ExecuteCommandAsync();
                 return;
             }
 
             // 记录操作日志
             var enabledSysOpLog = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysOpLog);
             if (!enabledSysOpLog) return;
-            await _sysLogOpRep.InsertAsync(new SysLogOp
+            await _db.Insertable(new SysLogOp
             {
                 ControllerName = loggingMonitor.controllerName,
                 ActionName = loggingMonitor.actionTypeName,
@@ -161,7 +155,9 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
                 CreateUserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
                 TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : long.Parse(tenantId),
                 LogLevel = logMsg.LogLevel
-            });
+            }).ExecuteCommandAsync();
+
+            await Task.Delay(50); // 延迟 0.05 秒写入数据库,有效减少高频写入数据库导致死锁问题
         }
         catch (Exception ex)
         {
@@ -186,7 +182,6 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable
         {
             // 不做处理
         }
-
         return ("未知", 0, 0);
     }
 

+ 16 - 14
Admin.NET/Admin.NET.Core/Logging/ElasticSearchLoggingWriter.cs

@@ -9,18 +9,20 @@ namespace Admin.NET.Core;
 /// <summary>
 /// ES日志写入器
 /// </summary>
-public class ElasticSearchLoggingWriter : IDatabaseLoggingWriter
+public class ElasticSearchLoggingWriter : IDatabaseLoggingWriter, IDisposable
 {
+    private readonly IServiceScope _serviceScope;
     private readonly ElasticClient _esClient;
     private readonly SysConfigService _sysConfigService;
 
-    public ElasticSearchLoggingWriter(ElasticClient esClient, SysConfigService sysConfigService)
+    public ElasticSearchLoggingWriter(IServiceScopeFactory scopeFactory)
     {
-        _esClient = esClient;
-        _sysConfigService = sysConfigService;
+        _serviceScope = scopeFactory.CreateScope();
+        _esClient = _serviceScope.ServiceProvider.GetRequiredService<ElasticClient>();
+        _sysConfigService = _serviceScope.ServiceProvider.GetRequiredService<SysConfigService>();
     }
 
-    public async void Write(LogMessage logMsg, bool flush)
+    public async Task WriteAsync(LogMessage logMsg, bool flush)
     {
         // 是否启用操作日志
         var sysOpLogEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysOpLog);
@@ -29,12 +31,10 @@ public class ElasticSearchLoggingWriter : IDatabaseLoggingWriter
         var jsonStr = logMsg.Context.Get("loggingMonitor").ToString();
         var loggingMonitor = JSON.Deserialize<dynamic>(jsonStr);
 
-        // 不记录登录出日志
+        // 不记录登录退出日志
         if (loggingMonitor.actionName == "userInfo" || loggingMonitor.actionName == "logout")
             return;
 
-        #region 处理操作日志
-
         // 获取当前操作者
         string account = "", realName = "", userId = "", tenantId = "";
         if (loggingMonitor.authorizationClaims != null)
@@ -54,9 +54,6 @@ public class ElasticSearchLoggingWriter : IDatabaseLoggingWriter
 
         string remoteIPv4 = loggingMonitor.remoteIPv4;
         (string ipLocation, double? longitude, double? latitude) = DatabaseLoggingWriter.GetIpAddress(remoteIPv4);
-        //var client = Parser.GetDefault().Parse(loggingMonitor.userAgent.ToString());
-        //var browser = $"{client.UA.Family} {client.UA.Major}.{client.UA.Minor} / {client.Device.Family}";
-        //var os = $"{client.OS.Family} {client.OS.Major} {client.OS.Minor}";
 
         var sysLogOp = new SysLogOp
         {
@@ -87,9 +84,14 @@ public class ElasticSearchLoggingWriter : IDatabaseLoggingWriter
             CreateUserId = string.IsNullOrWhiteSpace(userId) ? 0 : long.Parse(userId),
             TenantId = string.IsNullOrWhiteSpace(tenantId) ? 0 : long.Parse(tenantId)
         };
-
-        #endregion 处理操作日志
-
         await _esClient.IndexDocumentAsync(sysLogOp);
     }
+
+    /// <summary>
+    /// 释放服务作用域
+    /// </summary>
+    public void Dispose()
+    {
+        _serviceScope.Dispose();
+    }
 }

+ 0 - 1
Admin.NET/Admin.NET.Core/Service/DataBase/SysDatabaseService.cs

@@ -450,7 +450,6 @@ public class SysDatabaseService : IDynamicApiController, ITransient
     /// <returns></returns>
     [HttpPost, NonUnify]
     [DisplayName("备份数据库(PostgreSQL)")]
-
     public async Task<IActionResult> BackupDatabase()
     {
         if (_db.CurrentConnectionConfig.DbType != SqlSugar.DbType.PostgreSQL)