From 5bf354952207230350053422d4135c9d44683984 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 1 Dec 2024 20:12:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E6=95=B0=E8=BF=87=E5=A4=9A=E5=AF=BC=E8=87=B4?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=B4=A9=E6=BA=83=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Controllers/ManagementController.cs | 27 +++++++++ src/Models/Db.cs | 77 +++++++++++++++++++++++++ src/Program.cs | 30 +++++----- src/Services/DatabaseGateService.cs | 73 ++++++++++++++++++++++- src/Services/LocalCacheManager.cs | 4 +- 5 files changed, 193 insertions(+), 18 deletions(-) diff --git a/src/Controllers/ManagementController.cs b/src/Controllers/ManagementController.cs index 346e172..47e3268 100644 --- a/src/Controllers/ManagementController.cs +++ b/src/Controllers/ManagementController.cs @@ -358,5 +358,32 @@ namespace iFileProxy.Controllers }); } } + + /// + /// 获取数据库连接池状态 + /// + [HttpGet("GetConnectionPoolInfo")] + public async Task> GetConnectionPoolInfo() + { + try + { + var poolInfo = await _dbGateService.GetConnectionPoolInfoAsync(); + return Ok(new CommonRsp + { + Retcode = 0, + Message = "success", + Data = poolInfo + }); + } + catch (Exception ex) + { + _logger.Error($"获取连接池信息失败: {ex.Message}"); + return Ok(new CommonRsp + { + Retcode = 1, + Message = "获取连接池信息失败" + }); + } + } } } diff --git a/src/Models/Db.cs b/src/Models/Db.cs index 9be3a12..3b8a46e 100644 --- a/src/Models/Db.cs +++ b/src/Models/Db.cs @@ -106,4 +106,81 @@ namespace iFileProxy.Models public static string iFileProxy = "iFileProxy_Db"; } + + /// + /// 数据库连接池信息 + /// + public class ConnectionPoolInfo + { + /// + /// 当前总连接数 + /// + public long TotalConnections { get; set; } + + /// + /// 活跃连接数 + /// + public long ActiveConnections { get; set; } + + /// + /// 空闲连接数 + /// + public long SleepingConnections { get; set; } + + /// + /// 连接池最大连接数 + /// + public int MaxPoolSize { get; set; } + + /// + /// 连接详情列表 + /// + public List Connections { get; set; } = []; + } + + /// + /// MySQL 进程列表信息 + /// + public class ProcessListInfo + { + /// + /// 连接ID + /// + public long Id { get; set; } + + /// + /// 用户名 + /// + public string User { get; set; } = string.Empty; + + /// + /// 主机信息 + /// + public string Host { get; set; } = string.Empty; + + /// + /// 数据库名 + /// + public string Db { get; set; } = string.Empty; + + /// + /// 命令类型 + /// + public string Command { get; set; } = string.Empty; + + /// + /// 执行时间(秒) + /// + public long Time { get; set; } + + /// + /// 连接状态 + /// + public string State { get; set; } = string.Empty; + + /// + /// 执行的SQL + /// + public string Info { get; set; } = string.Empty; + } } diff --git a/src/Program.cs b/src/Program.cs index babdb49..c941411 100644 --- a/src/Program.cs +++ b/src/Program.cs @@ -16,18 +16,18 @@ namespace iFileProxy SerilogConfig.CreateLogger(); Serilog.ILogger logger = Log.Logger.ForContext(); - Console.Write(" "); // ǿ��֢�����ſ�ʼ��������־�����벻�þ� + Console.Write(" "); // 补全日志第一行开头的空白 var builder = WebApplication.CreateBuilder(args); - // ���� CORS ���� + // CORS配置 builder.Services.AddCors(options => { options.AddPolicy("AllowFrontend", builder => { builder - .WithOrigins("http://localhost:3000", "http://admin.gitdl.cn", "https://admin.gitdl.cn","http://47.243.56.137:50050") // ǰ�˵�ַ + .WithOrigins("http://localhost:3000", "http://admin.gitdl.cn", "https://admin.gitdl.cn","http://47.243.56.137:50050") .AllowAnyMethod() .AllowAnyHeader() .AllowCredentials(); @@ -55,10 +55,9 @@ namespace iFileProxy builder.Services.AddSingleton(); - // ������֤���� + // 添加验证服务 builder.Services.AddScoped(); - // ����JWT��֤ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { @@ -77,9 +76,8 @@ namespace iFileProxy var app = builder.Build(); - AppConfig.CheckAppConfig(app.Services); - - LocalCacheManager localCacheManager = new(app.Services); + // 全局错误处理中间件 + app.UseMiddleware(); app.UseSerilogRequestLogging(options => { @@ -98,17 +96,21 @@ namespace iFileProxy app.UseSwaggerUI(); } - // �������м�� - app.UseMiddleware(); + // 检查自定义配置 + AppConfig.CheckAppConfig(app.Services); + + // 初始化缓存管理器 + LocalCacheManager localCacheManager = new(app.Services); + app.UseCors("AllowFrontend"); app.UseHttpsRedirection(); - // ����Ĭ���ļ�ѡ�� + var defaultFilesOptions = new DefaultFilesOptions(); - defaultFilesOptions.DefaultFileNames.Clear(); // ���Ĭ���б� - defaultFilesOptions.DefaultFileNames.Add("index.html"); // �����Զ���Ĭ���ļ� + defaultFilesOptions.DefaultFileNames.Clear(); + defaultFilesOptions.DefaultFileNames.Add("index.html"); app.UseDefaultFiles(defaultFilesOptions); @@ -120,7 +122,7 @@ namespace iFileProxy app.Services.GetRequiredService>>(), AppConfig.GetCurrConfig().SecurityOptions.DailyRequestLimitPerIP); - // �����м�� + // JWT中间件 app.UseMiddleware(); app.MapControllers(); diff --git a/src/Services/DatabaseGateService.cs b/src/Services/DatabaseGateService.cs index c9664b0..793a94c 100644 --- a/src/Services/DatabaseGateService.cs +++ b/src/Services/DatabaseGateService.cs @@ -115,11 +115,22 @@ namespace iFileProxy.Services if (db_user == null || db_password == null || db_host == null || db_port == null) throw new NoNullAllowedException("数据库配置获取失败,不允许为空的字段出现空值"); - string db_connstr = $"server={db_host};user={db_user};database={Db.DatabaseName};port={db_port};password={db_password};Pooling=true;MaximumPoolSize=500;"; - MySqlConnection conn; + var builder = new MySqlConnectionStringBuilder + { + Server = db_host, + UserID = db_user, + Database = Db.DatabaseName, + Port = (uint)db_port, + Password = db_password, + Pooling = true, + MinimumPoolSize = 1, + MaximumPoolSize = 50, + ConnectionLifeTime = 300 // 连接最大生命周期(秒) + }; + try { - conn = new MySqlConnection(db_connstr); + var conn = new MySqlConnection(builder.ConnectionString); conn.Open(); return conn; } @@ -900,5 +911,61 @@ namespace iFileProxy.Services var users = await ExecuteQueryAsync(sql, parameters); return users.FirstOrDefault(); } + + /// + /// 获取数据库连接池状态 + /// + /// 连接池信息 + public async Task GetConnectionPoolInfoAsync() + { + try + { + var appName = "iFileProxy"; // 程序名称 + var parameters = new Dictionary + { + { "@appName", $"%{appName}%" } + }; + + // 获取总连接数 + var totalSql = @"SELECT COUNT(*) + FROM information_schema.processlist + WHERE info LIKE @appName OR host LIKE @appName"; + var totalConnections = await ExecuteScalarAsync(totalSql, parameters); + + // 获取活跃连接数 + var activeSql = @"SELECT COUNT(*) + FROM information_schema.processlist + WHERE Command != 'Sleep' + AND (info LIKE @appName OR host LIKE @appName)"; + var activeConnections = await ExecuteScalarAsync(activeSql, parameters); + + // 获取睡眠连接数 + var sleepingSql = @"SELECT COUNT(*) + FROM information_schema.processlist + WHERE Command = 'Sleep' + AND (info LIKE @appName OR host LIKE @appName)"; + var sleepingConnections = await ExecuteScalarAsync(sleepingSql, parameters); + + // 获取连接详情 + var detailSql = @"SELECT id, user, host, db, command, time, state, info + FROM information_schema.processlist + WHERE info LIKE @appName OR host LIKE @appName"; + var connections = await ExecuteQueryAsync(detailSql, parameters); + + return new ConnectionPoolInfo + { + TotalConnections = totalConnections, + ActiveConnections = activeConnections, + SleepingConnections = sleepingConnections, + MaxPoolSize = 50, // 从配置中获取的最大连接数 + Connections = connections + }; + } + catch (Exception ex) + { + _logger.Error($"获取连接池信息失败: {ex.Message}"); + throw; + } + } } } diff --git a/src/Services/LocalCacheManager.cs b/src/Services/LocalCacheManager.cs index aa44e43..8cb46af 100644 --- a/src/Services/LocalCacheManager.cs +++ b/src/Services/LocalCacheManager.cs @@ -39,7 +39,7 @@ namespace iFileProxy.Services public void CheckAndCleanCache(object state) { // 初始化并打开一个MySQL连接 防止后续数据过多导致程序crush - var dbConn = _dbGateService.GetAndOpenDBConn(DbConfigName.iFileProxy); + using var dbConn = _dbGateService.GetAndOpenDBConn(DbConfigName.iFileProxy); // 获取数据库中超出生命周期的缓存数据 string result = _dbGateService.QueryTableData($"SELECT * FROM t_tasks_info WHERE UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(update_time) > {CACHE_LIFETIME} AND (tag <> 'CLEANED' OR tag IS NULL)", DbConfigName.iFileProxy); @@ -67,6 +67,8 @@ namespace iFileProxy.Services _dbGateService.UpdateTaskStatus(taskInfo,dbConn); } } + + } ///