使用.NetCore自带的后台作业,出入队简单模拟生产者消费者处理请求响应的数据
环境:Core:3.1的项目
说明:由于该方案为个人测试项目,重启时队列中的部分数据很可能会丢失,
对数据有要求的该方案不适用,不能照搬需要持久化处理,
另外发布到Linux Docker中通常不会自动回收,但是发布到IIS中需要简单设置不回收即可!!! 如下截图:
在IIS中找到这个站点所用的程序池,点击 高级设置。。。 回收——固定时间间隔 修改为 0
回收——虚拟/专用内存限制 修改为 0
进程模型——闲置超时 修改为 0
1:先来看效果
1.1:操作日志数据到表
1.2:操作日志数据到文件
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("\r\n【接口地址】:{0} \r\n【请求方式】:{1} \r\n【地址参数】:{2} \r\n【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 += "\r\n【响应参数】:" + log.ResposeParam + "\r\n============================================";
_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:这里也贴出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" />
使用.NetCore自带的后台作业,出入队简单模拟生产者消费者处理请求响应的数据的更多相关文章
- Python推导式详解,带你写出比较精简酷炫的代码
Python推导式详解,带你写出比较精简酷炫的代码 前言 1.推导式分类与用法 1.1 列表推导 1.2 集合推导 1.3 字典推导 1.4 元组推导?不存在的 2.推导式的性能 2.1 列表推导式与 ...
- 【Javascript Demo】遮罩层和百度地图弹出层简单实现
其实想做的就是显示百度地图的弹出层,现在已经简单实现了.示例和代码如下,点击按钮可以看到效果: 1.示例: 2.代码: <!DOCTYPE html PUBLIC "-//W3C/ ...
- 【Javascript Demo】遮罩层和弹出层简单实现
最近纠结于遮罩层和弹出层的实现,终于搞定了个简单的版本.示例和代码如下,点击按钮可以看到效果: 1.示例: 2.代码: <!DOCTYPE html PUBLIC "-//W3C//D ...
- 在使用Ajax请求返回json数据的时候IE浏览器弹出下载保存对话框的解决方法
在使用Ajax请求返回json数据的时候IE浏览器弹出下载保存对话框的解决方法 最近在做一个小东西,使用kindeditor上传图片的时候,自己写了一个上传的方法,按照协议规则通过ajax返回json ...
- PDO 拿出來的 Float 數據跟数据库中的数据不匹配
数据库中的价格字段是 float 类型的,在 Laravel 中取出会出现这样的情况 数据库:71.9 -> 程序打印:72.0 数据库:75.2 -> 程序打印:75.3 在另外一个测试 ...
- 【452】pandas筛选出表中满足另一个表所有条件的数据
参考:pandas筛选出表中满足另一个表所有条件的数据 参考:pandas:匹配两个dataframe 使用 pd.merge 来实现 on 表示查询的 columns,如果都有 id,那么这是很好的 ...
- C语言:将带头节点的单向链表结点域中的数据从小到大排序。-求出单向链表结点(不包括头节点)数据域中的最大值。-将M*N的二维数组中的数据,按行依次放入一维数组,
//函数fun功能是将带头节点的单向链表结点域中的数据从小到大排序. //相当于数组的冒泡排序. #include <stdio.h> #include <stdlib.h> ...
- 终于等到你!MobileTest免费公测,华为带你走出安卓适配大坑
一.安卓适配之痛真的无解吗? Android平台的诞生对智能手机的普及功不可没,但设备繁多.品牌众多.版本各异,芯片.摄像头.分辨率不统一等等,这些都逐渐成为Android系统发展的障碍,碎片化严重不 ...
- 利用ASP.netCore自带DI(DependencyInjection)实现批量依赖注入
ASP.net Core自带DI(依赖注入),用法如下: services.AddScoped(typeof(IProductService), typeof(ProductService)); 如果 ...
随机推荐
- Java学习day13
泛型类格式: 修饰符 class 类名<类型>{ } 常用T.E.K.V等形式的参数表示泛型 使用方式与C++的类模板相似,在创建对象时要明确数据类型 泛型方法定义格式: 修饰符<类 ...
- 『忘了再学』Shell基础 — 11、变量定义的规则和分类
目录 1.定义变量的规则 2.变量的分类 1.定义变量的规则 在定义变量时,有一些规则需要遵守 变量名称可以由字母.数字和下划线组成,但是不能以数字开头.如果变量名是2name则是错误的. 在Bash ...
- Java语言学习day22--7月28日
###12多态概述 * A: 多态概述 多态是继封装.继承之后,面向对象的第三大特性. 现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态. Ja ...
- 爬虫篇-如何下载selenium及其适配谷歌浏览器插件chromedriver(含chrome各版本及下载地址)
最近换了电脑,练习爬虫时用到selenium,结果在重新安装chromedriver插件的时候发现原网址不能使用,找了好久终于找到了了新网址,顺便更一篇详细使用的文章,希望可以对屏幕前的你有所帮助.本 ...
- 【虚拟机】VMware-Ubuntu-安装与卸载
VMware-Ubuntu 一.Ubuntu虚拟机安装 1.安装Ubuntu镜像 下载Ubuntu镜像文件,下载地址:http://www.ubuntu.com,点击download 下一步,到如下页 ...
- 如何基于ZEGO SDK 实现通话质量监测
如何基于ZEGO SDK 实现通话质量监测 1 功能简介 在进行视频通话过程中,用户有时候会出现网络不好的情况,比如在进行多人视频通话或者多人唱歌时,我们需要实时显示用户的网络质量. 示例源码 请参考 ...
- XCTF练习题---MISC---坚持60S
XCTF练习题---MISC---坚持60S flag:flag{DajiDali_JinwanChiji} 解题步骤: 1.观察题目,下载附件,是一个java文件 2.打开玩了一会,真鸡儿难,试着反 ...
- GO语言学习——切片二
使用make()函数构造切片 格式: make([]T, size, cap) 其中: T:切片的元素类型 size:切片中元素的数量 cap:切片的容量 切片的本质 切片的本质就是对底层数组的封装, ...
- 【VMware】在移动硬盘或U盘中安装便携linux系统
背景: 操作系统课需要在Linux环境下进行编程.本来是给了个傻瓜式的Ubuntu虚拟机镜像,但奈何虚拟机这东西我这老本子跑起来巨卡,装双系统又卡,只能选择把系统装进便携设备里了. 前期准备: 一个2 ...
- fxksmdb.exe 是什么进程?
今天打开电脑应用进程发现fxksmdb.exe.fxksmpl.exe.fxksmW.exe三个进程,经过查看文件路径发现原来是施乐打印机的驱动程序自带的应用,平时都没注意到这个,这下放心了. 我这里 ...