支持自定义连接池大小 日志分等级存储
This commit is contained in:
parent
5bf3549522
commit
d34b491c11
8 changed files with 120 additions and 48 deletions
|
@ -2,7 +2,6 @@
|
|||
using Serilog;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using MySql.Data.MySqlClient;
|
||||
|
||||
namespace iFileProxy.Config
|
||||
{
|
||||
|
@ -93,6 +92,9 @@ namespace iFileProxy.Config
|
|||
|
||||
public partial class Database
|
||||
{
|
||||
[JsonPropertyName("MaxConnectionPoolSize")]
|
||||
public uint MaxConnectionPoolSize { get; set; } = 50;
|
||||
|
||||
[JsonPropertyName("Common")]
|
||||
public Common Common { get; set; }
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace iFileProxy.Controllers
|
|||
{
|
||||
public TaskManager _taskManager = taskManager;
|
||||
public DatabaseGateService _dbGateService = dbGateService;
|
||||
private readonly Serilog.ILogger _logger = Log.Logger.ForContext<DatabaseGateService>();
|
||||
private readonly Serilog.ILogger _logger = Log.Logger.ForContext<ManagementController>();
|
||||
|
||||
|
||||
// 查看任务详情
|
||||
|
@ -362,6 +362,7 @@ namespace iFileProxy.Controllers
|
|||
/// <summary>
|
||||
/// 获取数据库连接池状态
|
||||
/// </summary>
|
||||
[Authorize(UserMask.SuperAdmin)]
|
||||
[HttpGet("GetConnectionPoolInfo")]
|
||||
public async Task<ActionResult<CommonRsp>> GetConnectionPoolInfo()
|
||||
{
|
||||
|
|
|
@ -8,16 +8,10 @@ namespace iFileProxy.Controllers
|
|||
{
|
||||
[Route("[controller]")]
|
||||
[ApiController]
|
||||
public class UserController : ControllerBase
|
||||
public class UserController(AuthService authService, ILogger<UserController> logger) : ControllerBase
|
||||
{
|
||||
private readonly AuthService _authService;
|
||||
private readonly ILogger<UserController> _logger;
|
||||
|
||||
public UserController(AuthService authService, ILogger<UserController> logger)
|
||||
{
|
||||
_authService = authService;
|
||||
_logger = logger;
|
||||
}
|
||||
private readonly AuthService _authService = authService;
|
||||
private readonly ILogger<UserController> _logger = logger;
|
||||
|
||||
/// <summary>
|
||||
/// 用户注册
|
||||
|
|
|
@ -130,7 +130,7 @@ namespace iFileProxy.Models
|
|||
/// <summary>
|
||||
/// 连接池最大连接数
|
||||
/// </summary>
|
||||
public int MaxPoolSize { get; set; }
|
||||
public uint MaxPoolSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 连接详情列表
|
||||
|
|
|
@ -8,7 +8,14 @@
|
|||
{
|
||||
public static void CreateLogger()
|
||||
{
|
||||
var filePath = Path.Combine(AppContext.BaseDirectory, $"logs/dispatch.api.log");
|
||||
var baseLogPath = Path.Combine(AppContext.BaseDirectory, "logs");
|
||||
var appName = AppDomain.CurrentDomain.FriendlyName;
|
||||
|
||||
// 确保日志目录存在
|
||||
if (!Directory.Exists(baseLogPath))
|
||||
{
|
||||
Directory.CreateDirectory(baseLogPath);
|
||||
}
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
#if RELEASE
|
||||
|
@ -19,12 +26,41 @@
|
|||
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
|
||||
.MinimumLevel.Override("Microsoft.AspNetCore", LogEventLevel.Warning)
|
||||
.Enrich.FromLogContext()
|
||||
// 控制台输出所有日志
|
||||
.WriteTo.Console(
|
||||
outputTemplate: "{Timestamp:HH:mm:ss.fff} [{Level:u3}] [{SourceContext}] {ClientIp} {Message:lj} {contentType}{NewLine} {Exception}")
|
||||
.WriteTo.File(filePath,
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] {ClientIp} {Message:lj} {contentType} {queryString}{NewLine}{Exception}",
|
||||
rollingInterval: RollingInterval.Day,
|
||||
fileSizeLimitBytes: 1073741824) //1GB
|
||||
outputTemplate: "{Timestamp:HH:mm:ss.fff} [{Level:u3}] [{SourceContext}] {ClientIp} {Message:lj} {contentType}{NewLine} {Exception}")
|
||||
// 错误和致命错误写入单独的文件
|
||||
.WriteTo.Logger(lc => lc
|
||||
.Filter.ByIncludingOnly(evt => evt.Level >= LogEventLevel.Error)
|
||||
.WriteTo.File(
|
||||
Path.Combine(baseLogPath, $"{appName}.error.log"),
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] {ClientIp} {Message:lj} {contentType} {queryString}{NewLine}{Exception}",
|
||||
rollingInterval: RollingInterval.Day,
|
||||
fileSizeLimitBytes: 1073741824)) // 1GB
|
||||
// 警告日志写入单独的文件
|
||||
.WriteTo.Logger(lc => lc
|
||||
.Filter.ByIncludingOnly(evt => evt.Level == LogEventLevel.Warning)
|
||||
.WriteTo.File(
|
||||
Path.Combine(baseLogPath, $"{appName}.warning.log"),
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] {ClientIp} {Message:lj} {contentType} {queryString}{NewLine}{Exception}",
|
||||
rollingInterval: RollingInterval.Day,
|
||||
fileSizeLimitBytes: 1073741824))
|
||||
// 信息日志写入单独的文件
|
||||
.WriteTo.Logger(lc => lc
|
||||
.Filter.ByIncludingOnly(evt => evt.Level == LogEventLevel.Information)
|
||||
.WriteTo.File(
|
||||
Path.Combine(baseLogPath, $"{appName}.info.log"),
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] {ClientIp} {Message:lj} {contentType} {queryString}{NewLine}{Exception}",
|
||||
rollingInterval: RollingInterval.Day,
|
||||
fileSizeLimitBytes: 1073741824))
|
||||
// 调试日志写入单独的文件
|
||||
.WriteTo.Logger(lc => lc
|
||||
.Filter.ByIncludingOnly(evt => evt.Level == LogEventLevel.Debug)
|
||||
.WriteTo.File(
|
||||
Path.Combine(baseLogPath, $"{appName}.debug.log"),
|
||||
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [{SourceContext}] {ClientIp} {Message:lj} {contentType} {queryString}{NewLine}{Exception}",
|
||||
rollingInterval: RollingInterval.Day,
|
||||
fileSizeLimitBytes: 1073741824))
|
||||
.Enrich.WithProperty("node_ip", GetIpAddress())
|
||||
.CreateLogger();
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ using MySql.Data.MySqlClient;
|
|||
using iFileProxy.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace iFileProxy.Services
|
||||
{
|
||||
|
@ -124,7 +123,7 @@ namespace iFileProxy.Services
|
|||
Password = db_password,
|
||||
Pooling = true,
|
||||
MinimumPoolSize = 1,
|
||||
MaximumPoolSize = 50,
|
||||
MaximumPoolSize = AppConfig.GetCurrConfig().Database.MaxConnectionPoolSize,
|
||||
ConnectionLifeTime = 300 // 连接最大生命周期(秒)
|
||||
};
|
||||
|
||||
|
@ -929,27 +928,27 @@ namespace iFileProxy.Services
|
|||
// 获取总连接数
|
||||
var totalSql = @"SELECT COUNT(*)
|
||||
FROM information_schema.processlist
|
||||
WHERE info LIKE @appName OR host LIKE @appName";
|
||||
WHERE `USER` LIKE @appName OR `DB` LIKE @appName";
|
||||
var totalConnections = await ExecuteScalarAsync<long>(totalSql, parameters);
|
||||
|
||||
// 获取活跃连接数
|
||||
var activeSql = @"SELECT COUNT(*)
|
||||
FROM information_schema.processlist
|
||||
WHERE Command != 'Sleep'
|
||||
AND (info LIKE @appName OR host LIKE @appName)";
|
||||
AND ( `USER` LIKE @appName OR `DB` LIKE @appName)";
|
||||
var activeConnections = await ExecuteScalarAsync<long>(activeSql, parameters);
|
||||
|
||||
// 获取睡眠连接数
|
||||
var sleepingSql = @"SELECT COUNT(*)
|
||||
FROM information_schema.processlist
|
||||
WHERE Command = 'Sleep'
|
||||
AND (info LIKE @appName OR host LIKE @appName)";
|
||||
AND ( `USER` LIKE @appName OR `DB` LIKE @appName)";
|
||||
var sleepingConnections = await ExecuteScalarAsync<long>(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";
|
||||
WHERE `USER` LIKE @appName OR `DB` LIKE @appName";
|
||||
var connections = await ExecuteQueryAsync<ProcessListInfo>(detailSql, parameters);
|
||||
|
||||
return new ConnectionPoolInfo
|
||||
|
@ -957,7 +956,7 @@ namespace iFileProxy.Services
|
|||
TotalConnections = totalConnections,
|
||||
ActiveConnections = activeConnections,
|
||||
SleepingConnections = sleepingConnections,
|
||||
MaxPoolSize = 50, // 从配置中获取的最大连接数
|
||||
MaxPoolSize = AppConfig.GetCurrConfig().Database.MaxConnectionPoolSize, // 从配置中获取的最大连接数
|
||||
Connections = connections
|
||||
};
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@ using iFileProxy.Helpers;
|
|||
using iFileProxy.Models;
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
using MySql.Data.MySqlClient;
|
||||
using System.Data;
|
||||
|
||||
namespace iFileProxy.Services
|
||||
{
|
||||
|
@ -16,6 +18,7 @@ namespace iFileProxy.Services
|
|||
private readonly AppConfig _appConfig = AppConfig.GetCurrConfig();
|
||||
private readonly static Serilog.ILogger _logger = Log.Logger.ForContext<LocalCacheManager>();
|
||||
|
||||
private readonly object _lock = new object();
|
||||
private readonly Timer _timer;
|
||||
private readonly DatabaseGateService _dbGateService;
|
||||
private readonly int CACHE_LIFETIME;
|
||||
|
@ -29,46 +32,82 @@ namespace iFileProxy.Services
|
|||
CACHE_LIFETIME = _appConfig.DownloadOptions.CacheLifetime;
|
||||
_dbGateService = serviceProvider.GetRequiredService<DatabaseGateService>();
|
||||
// 开始定时清理任务
|
||||
_timer = new Timer(CheckAndCleanCache, null, TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(60));
|
||||
_timer = new Timer((obj) => {
|
||||
lock (_lock)
|
||||
{
|
||||
CheckAndCleanCache();
|
||||
}
|
||||
}, null, TimeSpan.FromSeconds(6), TimeSpan.FromSeconds(60));
|
||||
_logger.Information("succ.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查并且清理缓存数据
|
||||
/// </summary>
|
||||
public void CheckAndCleanCache(object state)
|
||||
public void CheckAndCleanCache()
|
||||
{
|
||||
// 初始化并打开一个MySQL连接 防止后续数据过多导致程序crush
|
||||
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);
|
||||
List<TaskInfo>? taskInfos = JsonConvert.DeserializeObject<List<TaskInfo>>(result);
|
||||
if (taskInfos != null)
|
||||
try
|
||||
{
|
||||
foreach (TaskInfo taskInfo in taskInfos)
|
||||
// 获取数据库中超出生命周期的缓存数据
|
||||
string sql = $@"SELECT * FROM t_tasks_info
|
||||
WHERE UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(update_time) > {CACHE_LIFETIME}
|
||||
AND (tag <> 'CLEANED' OR tag IS NULL)";
|
||||
|
||||
List<TaskInfo>? taskInfos;
|
||||
using (var conn = _dbGateService.GetAndOpenDBConn(DbConfigName.iFileProxy))
|
||||
{
|
||||
string cacheFileName = Path.Combine(_appConfig.DownloadOptions.SavePath, taskInfo.FileName);
|
||||
if (File.Exists(cacheFileName))
|
||||
using var cmd = new MySqlCommand(sql, conn);
|
||||
using var adapter = new MySqlDataAdapter(cmd);
|
||||
var dataTable = new DataTable();
|
||||
adapter.Fill(dataTable);
|
||||
taskInfos = JsonConvert.DeserializeObject<List<TaskInfo>>(
|
||||
JsonConvert.SerializeObject(dataTable)
|
||||
);
|
||||
}
|
||||
|
||||
if (taskInfos != null)
|
||||
{
|
||||
foreach (TaskInfo taskInfo in taskInfos)
|
||||
{
|
||||
_logger.Information($"正在清理缓存文件: {cacheFileName}");
|
||||
try
|
||||
string cacheFileName = Path.Combine(_appConfig.DownloadOptions.SavePath, taskInfo.FileName);
|
||||
if (File.Exists(cacheFileName))
|
||||
{
|
||||
File.Delete(cacheFileName);
|
||||
_logger.Information($"正在清理缓存文件: {cacheFileName}");
|
||||
try
|
||||
{
|
||||
File.Delete(cacheFileName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.Error($"缓存文件删除失败: {e.Message}");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
|
||||
// 更新数据库状态
|
||||
using (var conn = _dbGateService.GetAndOpenDBConn(DbConfigName.iFileProxy))
|
||||
{
|
||||
_logger.Error("缓存文件删除失败: {e}", e);
|
||||
throw;
|
||||
// 更新标签
|
||||
using (var cmd = new MySqlCommand(
|
||||
"UPDATE t_tasks_info SET tag = @tag WHERE tid = @tid",
|
||||
conn))
|
||||
{
|
||||
cmd.Parameters.AddWithValue("@tag", "CLEANED");
|
||||
cmd.Parameters.AddWithValue("@tid", taskInfo.TaskId);
|
||||
cmd.ExecuteNonQuery();
|
||||
}
|
||||
|
||||
// 更新状态
|
||||
taskInfo.Status = TaskState.Cleaned;
|
||||
_dbGateService.UpdateTaskStatus(taskInfo);
|
||||
}
|
||||
}
|
||||
_dbGateService.Query($"UPDATE t_tasks_info SET `tag` = \"CLEANED\" WHERE `tid` = '{taskInfo.TaskId}'", dbConn);
|
||||
taskInfo.Status = TaskState.Cleaned;
|
||||
_dbGateService.UpdateTaskStatus(taskInfo,dbConn);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error($"清理缓存时发生错误: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"Database": {
|
||||
"MaxConnectionPoolSize": 100,
|
||||
"Common": {
|
||||
"Host": "47.243.56.137",
|
||||
"Port": 3306,
|
||||
|
|
Loading…
Reference in a new issue