使用.NetCore自带的后台作业,出入队简单模拟生产者消费者处理请求响应的数据

环境:Core:3.1的项目

说明:由于该方案为个人测试项目,重启时队列中的部分数据很可能会丢失,

对数据有要求的该方案不适用,不能照搬需要持久化处理,

另外发布到Linux Docker中通常不会自动回收,但是发布到IIS中需要简单设置不回收即可!!! 如下截图:

在IIS中找到这个站点所用的程序池,点击 高级设置。。。 

使用.NetCore自带的后台作业,出入队简单模拟生产者消费者处理请求响应的数据

回收——固定时间间隔       修改为 0

回收——虚拟/专用内存限制   修改为 0

进程模型——闲置超时       修改为 0

1:先来看效果

1.1:操作日志数据到表

使用.NetCore自带的后台作业,出入队简单模拟生产者消费者处理请求响应的数据

 1.2:操作日志数据到文件

使用.NetCore自带的后台作业,出入队简单模拟生产者消费者处理请求响应的数据

 2:过滤器

using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Filters; using System.Text; using System.Diagnostics; using QzjcService.Models.Dto.LogModels; using QzjcService.Controllers; using SqlSugar.IOC; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using QzjcService.Helper; using Microsoft.AspNetCore.Mvc; using QzjcService.Models;  namespace QzjcService.Filters {     public class ActionNewLogFilter : ActionFilterAttribute     {         private static Stopwatch _watting = new Stopwatch();         public static double? longtime = 0;         private ActionLogModel log = new ActionLogModel();         private readonly ILogger<ActionNewLogFilter> _logger;          public ActionNewLogFilter(ILogger<ActionNewLogFilter> logger)         {             _logger = logger;         }          public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)         {             _watting.Start();             string controllerName = context.ActionDescriptor.RouteValues["controller"];             string actionName = context.ActionDescriptor.RouteValues["action"];             string method = context.HttpContext.Request.Method;//请求方式             string queryString = context.HttpContext.Request.QueryString.Value;//地址参数             string argments = JsonConvert.SerializeObject(context.ActionArguments);             string url = context.HttpContext.Request.Host + context.HttpContext.Request.Path;//接口地址             var logStr = string.Format("rn【接口地址】:{0} rn【请求方式】:{1} rn【地址参数】:{2} rn【Body参数】:{3}", new object[] { url, method, queryString, argments });             log.ControllerName = controllerName;             log.ActionName = actionName;          //请求方式 0:get, 1:Post             log.Menthod = (method.Equals("get", StringComparison.InvariantCultureIgnoreCase) || method.Equals("httpget", StringComparison.InvariantCultureIgnoreCase)) ? 0 : 1;             log.CreateTime = DateTime.Now;             log.RequstParms = logStr;             var _context = context.HttpContext;             if (_context != null)             {                 var tokenStr = context.HttpContext.Request.Headers[ConstData.Authorization].ToString();                 log.userId = string.IsNullOrEmpty(tokenStr) ? 0 : TokenHelper.GetUserModel(context.HttpContext)?.UserId;             }             await base.OnActionExecutionAsync(context, next);         }         public override async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)         {             _watting.Stop();             longtime = 0;             if (context.Result is ObjectResult result)             {                 if (result != null)                     log.ResposeParam = JsonConvert.SerializeObject(result.Value);             }             longtime = _watting.Elapsed.TotalMilliseconds;             log.LongTimeMs = longtime.Value;             _watting.Reset();             log.RequstParms += "rn【响应参数】:" + log.ResposeParam + "rn============================================";             _logger.LogCritical(log.RequstParms);             //  await DbScoped.Sugar.Insertable<ActionLogModel>(log).ExecuteCommandAsync();             await LogQueueHelper.EnQueueLogAsync(log);             await base.OnResultExecutionAsync(context, next);         }      } }

3:后台自带的定时器

using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using QzjcService.Helper; using QzjcService.Models.Dto.LogModels; using SqlSugar.IOC; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace QzjcService.Services {     public class LogTimeService : BackgroundService     {         private readonly ILogger<LogTimeService> _logger;         public LogTimeService(ILogger<LogTimeService> logger )         {             _logger = logger;         }         protected override async Task ExecuteAsync(CancellationToken stoppingToken)         {             await Task.Factory.StartNew(async () =>             {                 while (!stoppingToken.IsCancellationRequested)                 {                     try                     {                         var model = await LogQueueHelper.DeQueueLogAsync();                         if (model != null)                         {                             Console.WriteLine($"===={DateTime.Now}=LogTimeService=DeQueueLog  Success====");                             await DbScoped.Sugar.Insertable<ActionLogModel>(model).ExecuteCommandAsync();                         }                         await Task.Delay(3000);                     }                     catch (Exception ex)                     {                         _logger.LogError($"====={DateTime.Now}===LogTimeService异常:=={ex.Message}==========");                         continue;                     }                 }             });          }     } }

4:Log记录Model

using SqlSugar; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; using System.Threading.Tasks; namespace QzjcService.Models.Dto.LogModels {     [Table("qzjc_action_loginfos")]     [SugarTable("qzjc_action_loginfos")]     public class ActionLogModel     {         /// <summary>         ///          /// </summary>         [Column("id")]         [SugarColumn(ColumnName = "id")]         public int id { get; set; }          /// <summary>         ///          /// </summary>         [Column("controller_name")]         [SugarColumn(ColumnName = "controller_name")]         public string ControllerName { get; set; }          /// <summary>         ///          /// </summary>         [Column("action_name")]         [SugarColumn(ColumnName = "action_name")]         public string ActionName { get; set; }          /// <summary>         ///          /// </summary>         [Column("request_parms")]         [SugarColumn(ColumnName = "request_parms")]         public string RequstParms { get; set; }          /// <summary>         ///          /// </summary>         [Column("long_time")]         [SugarColumn(ColumnName = "long_time")]         public double LongTimeMs { get; set; }          /// <summary>         ///          /// </summary>         [Column("create_time")]         [SugarColumn(ColumnName = "create_time")]         public DateTime CreateTime { get; set; }          /// <summary>         ///          /// </summary>         [Column("create_userid")]         [SugarColumn(ColumnName = "create_userid")]         public int? userId { get; set; }           [Column("menthod")]         [SugarColumn(ColumnName ="")]         public int? Menthod { get; set; }          //[Column("state")]         //[SugarColumn(ColumnName = "state")]         //public int? State { get; set; }                  [Column("respose_parms")]         [SugarColumn(ColumnName = "respose_parms")]         public string ResposeParam { get; set; }     } }

5:贴上系统自带的队列Queue

using QzjcService.Models.Dto.LogModels;  using System.Collections; using System.Threading.Channels; using System.Threading.Tasks; namespace QzjcService.Helper {     public static class LogQueueHelper     {         public static Queue queue;         private static readonly object Lock = new object();         static LogQueueHelper()         {             queue = new Queue();         }         /// <summary>         ///          /// </summary>         /// <returns></returns>         private static async Task<Queue> GetQueueAsync()         {             if (queue == null)             {                 lock (Lock)                 {                     if (queue == null)                         queue = new Queue();                 }             }             await Task.CompletedTask;             return queue;         }          public static async Task<bool> EnQueueLogAsync(ActionLogModel model)         {             try             {                 queue = await GetQueueAsync();                 queue.Enqueue(model);                 return true;             }             catch (System.Exception)             {                 return false;             }         }         public static async Task<ActionLogModel> DeQueueLogAsync()         {             try             {                 queue = await GetQueueAsync();                 object obj = queue.Dequeue();                 if (obj != null)                 {                     ActionLogModel model = obj as ActionLogModel;                     return model ?? null;                 }                 return null;             }             catch (System.Exception)             {                 return null;             }         }     } }

6:这里也贴出Serilog相关code

using System; using System.IO; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Configuration; using Serilog; using Serilog.Events;  namespace QzjcService {     public class Program     {         public static void Main(string[] args)         {             string dataTime = DateTime.Now.ToString("yyyy-MM-dd");//这里去掉更好,让其自增长             string fileStr = $"Logs/{dataTime}_logs.txt";             Log.Logger = new LoggerConfiguration()                 .MinimumLevel.Warning() //Debug()                   .MinimumLevel.Override("Microsoft", LogEventLevel.Warning)                   .MinimumLevel.Override("System", LogEventLevel.Warning)                   .MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)                   .Enrich.FromLogContext()                   .WriteTo.Async(c => c.File(fileStr, rollOnFileSizeLimit: true, fileSizeLimitBytes: 1024 * 1024 * 10, retainedFileCountLimit: 30))                   .CreateLogger();             try             {                 Log.Information("=========Starting web host==========");                 CreateHostBuilder(args).Build().Run();             }             catch (Exception ex)             {                 Log.Fatal(ex, "Host terminated unexpectedly!");             }             finally             {                 Log.CloseAndFlush();             }         }          public static IHostBuilder CreateHostBuilder(string[] args) =>             Host.CreateDefaultBuilder(args)              .ConfigureLogging((hostingContext, builder) =>              {                  builder.ClearProviders();              })                 .ConfigureWebHostDefaults(webBuilder =>                 {                     webBuilder.ConfigureKestrel(c => { c.Limits.MaxRequestBodySize = 1024 * 1024 * 300; });                     webBuilder.UseUrls("http://*:4444");                     webBuilder.UseStartup<Startup>();                 })                .UseSerilog();     } }
<PackageReference Include="Serilog.Extensions.Hosting" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.Async" Version="1.4.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="8.2.0" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />

发表评论

相关文章