.NET 集成 日志 (Serilog/NLog)、AOP、简单限流
<h2>一、环境准备(新建 .NET Web API)</h2><div> </div>
<div>先安装所有需要的 NuGet 包:</div>
<div> </div>
<h3>必装包</h3>
<div> </div>
<div>
<div dir="ltr">
<div>
<pre><code># AOP 核心
Install-Package Autofac
Install-Package Autofac.Extras.DynamicProxy
Install-Package Microsoft.Extensions.DependencyInjection
# Serilog 二选一
Install-Package Serilog
Install-Package Serilog.AspNetCore
Install-Package Serilog.Sinks.Console
Install-Package Serilog.Sinks.File
# NLog </code><code>二选一</code></pre>
<pre><code>Install-Package NLog Install-Package NLog.Web.AspNetCore # 限流 Install-Package AspNetCoreRateLimit </code></pre>
</div>
<div> </div>
</div>
</div>
<div> </div>
<hr>
<div> </div>
<h1>二、日志实现(二选一即可)</h1>
<div> </div>
<h2>方案 1:Serilog(简洁强大)</h2>
<div> </div>
<h3>1. Program.cs 配置</h3>
<div> </div>
<div>
<div dir="ltr">
<div>
<pre><code>using Serilog;
var builder = WebApplication.CreateBuilder(args);
// 配置 Serilog
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Information()
.Enrich.FromLogContext()
.WriteTo.Console() // 输出到控制台
.WriteTo.File("Logs/log-.txt", rollingInterval: RollingInterval.Day) // 按天切割
.CreateLogger();
builder.Host.UseSerilog(); // 替换系统默认日志
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
</code></pre>
</div>
<div> </div>
</div>
</div>
<h3>2. 使用日志</h3>
<div> </div>
<div>
<div dir="ltr">
<div>
<pre><code>
")]
public class TestController : ControllerBase
{
private readonly ILogger<TestController> _logger;
// 直接注入使用
public TestController(ILogger<TestController> logger)
{
_logger = logger;
}
public IActionResult Get()
{
_logger.LogInformation("请求 Test 接口");
return Ok("Hello Serilog");
}
}
</code></pre>
</div>
<div> </div>
</div>
</div>
<hr>
<div> </div>
<h2>方案 2:NLog(配置灵活)</h2>
<div> </div>
<h3>1. 添加 <code>nlog.config</code> 文件</h3>
<div> </div>
<div>
<div dir="ltr">
<div>
<div>xml</div>
<div> </div>
</div>
<div>
<pre><code><?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true">
<targets>
<target xsi:type="Console" name="console"/>
<target xsi:type="File" name="file" fileName="logs/${shortdate}.log" layout="${longdate}|${level}|${message} ${exception:format=tostring}"/>
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="console,file"/>
</rules>
</nlog>
</code></pre>
</div>
<div> </div>
</div>
</div>
<h3>2. Program.cs</h3>
<div> </div>
<div>
<div dir="ltr">
<div>
<pre><code>var builder = WebApplication.CreateBuilder(args);
builder.Host.UseNLog(); // 使用 NLog
builder.Services.AddControllers();
var app = builder.Build();
app.MapControllers();
app.Run();
</code></pre>
</div>
<div> </div>
</div>
</div>
<div> </div>
<div>使用方式和 Serilog 完全一样,直接注入 <code>ILogger<T></code> 即可。</div>
<div> </div>
<hr>
<div> </div>
<h1>三、AOP 切面编程(Autofac + 拦截器)</h1>
<div> </div>
<h2>用途:自动记录方法执行日志、耗时、异常,不用每个方法手写</h2>
<div> </div>
<h3>1. 编写 AOP 拦截器</h3>
<div> </div>
<div>
<div dir="ltr">
<div>
<pre><code>using Castle.DynamicProxy;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
public class LogInterceptor : IInterceptor
{
private readonly ILogger<LogInterceptor> _logger;
public LogInterceptor(ILogger<LogInterceptor> logger)
{
_logger = logger;
}
public void Intercept(IInvocation invocation)
{
var method = invocation.Method;
var stopwatch = Stopwatch.StartNew();
try
{
_logger.LogInformation($"【AOP 执行】 {method.DeclaringType.Name}.{method.Name} 开始");
// 执行目标方法
invocation.Proceed();
stopwatch.Stop();
_logger.LogInformation($"【AOP 完成】 {method.Name},耗时:{stopwatch.ElapsedMilliseconds} ms");
}
catch (Exception ex)
{
_logger.LogError(ex, $"【AOP 异常】 {method.Name} 执行出错");
throw;
}
}
}
</code></pre>
</div>
<div> </div>
</div>
</div>
<h3>2. 注册 Autofac + AOP</h3>
<div> </div>
<div>
<div dir="ltr">
<div>
<pre><code>using Autofac;
using Autofac.Extras.DynamicProxy;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();
// Autofac 容器
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder =>
{
// 注册拦截器
containerBuilder.RegisterType<LogInterceptor>();
// 注册需要 AOP 的服务(示例:TestService)
containerBuilder.RegisterType<TestService>()
.As<ITestService>()
.EnableInterfaceInterceptors() // 开启接口拦截
.InterceptedBy(typeof(LogInterceptor)); // 使用拦截器
});
builder.Services.AddControllers();
</code></pre>
</div>
<div>
<p> </p>
<div>
<div>
<div> </div>
<div> </div>
</div>
<div>
<div>
<div>
<table>
<thead>
<tr><th>功能</th><th>.NET 自带 DI</th><th>Autofac</th></tr>
</thead>
<tbody>
<tr>
<td>上手难度</td>
<td>⭐ 极简单</td>
<td>⭐⭐ 简单</td>
</tr>
<tr>
<td>构造函数注入</td>
<td>✅ 支持</td>
<td>✅ 支持</td>
</tr>
<tr>
<td>生命周期管理</td>
<td>✅ 基础</td>
<td>✅ 更精细</td>
</tr>
<tr>
<td>批量注册</td>
<td>❌ 不支持</td>
<td>✅ 一键批量注入</td>
</tr>
<tr>
<td>属性注入</td>
<td>❌ 不支持</td>
<td>✅ 支持</td>
</tr>
<tr>
<td>AOP 切面</td>
<td>❌ 很难</td>
<td>✅ 完美支持</td>
</tr>
<tr>
<td>模块化配置</td>
<td>❌ 弱</td>
<td>✅ 强</td>
</tr>
<tr>
<td>性能</td>
<td>✅ 快</td>
<td>✅ 更快</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<div> </div>
<h2> </h2>
</div>
</div>
</div>
<h3>3. 测试服务 + 接口</h3>
<div> </div>
<div>
<div dir="ltr">
<div>
<pre><code>// 接口
public interface ITestService
{
void Test();
}
// 实现
public class TestService : ITestService
{
public void Test()
{
Console.WriteLine("业务方法执行");
}
}
// 控制器
")]
public class TestController : ControllerBase
{
private readonly ITestService _testService;
public TestController(ITestService testService)
{
_testService = testService;
}
public IActionResult AopTest()
{
_testService.Test();
return Ok("AOP 已生效");
}
}
</code></pre>
</div>
<div> </div>
</div>
</div>
<div>访问 <code>/test/aop</code> 就能看到 自动日志 + 耗时统计。</div>
<div> </div>
<hr>
<div> </div>
<h1>四、简单限流(2 种常用方案)</h1>
<div> </div>
<h2>方案 1:固定窗口限流(固定时间窗口限流,此外还有滑动窗口和令牌桶等)</h2>
<div> </div>
<h3>Program.cs</h3>
<div> </div>
<div>
<div dir="ltr">
<div>
<pre><code>using AspNetCoreRateLimit;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();
// 限流配置
builder.Services.AddInMemoryRateLimiting();
builder.Services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
builder.Services.AddControllers();
var app = builder.Build();
// 启用限流
app.UseIpRateLimiting();
app.MapControllers();
app.Run();
</code></pre>
</div>
<div> </div>
</div>
</div>
<h3>添加限流规则(appsettings.json)</h3>
<div> </div>
<div>
<div dir="ltr">
<div>
<pre><code>"IpRateLimiting": {
"GeneralRules": [
{
"Endpoint": "*",
"Period": "1m",
"Limit": 10
}
]
}
</code></pre>
</div>
<div> </div>
</div>
</div>
<div>表示:1 分钟内最多请求 10 次。</div>
<div> </div>
<hr>
<div> </div>
<h2>方案 2:.NET 原生限流</h2>
<div> </div>
<h3>Program.cs</h3>
<div> </div>
<div>
<div dir="ltr">
<div>
<pre><code>var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();
// 原生限流
builder.Services.AddRateLimiter(options =>
{
// 固定窗口:每秒最多 2 个请求
options.AddFixedWindowLimiter("fixed", opt =>
{
opt.Window = TimeSpan.FromSeconds(1);
opt.PermitLimit = 2;
});
});
builder.Services.AddControllers();
var app = builder.Build();
app.UseRateLimiter(); // 启用限流中间件
app.MapControllers();
app.Run();
</code></pre>
</div>
<div> </div>
</div>
</div>
<h3>控制器使用</h3>
<div> </div>
<div>
<div dir="ltr">
<div>
<pre><code>
// 启用限流
public IActionResult LimitTest()
{
return Ok("限流测试");
}
</code></pre>
</div>
<div> </div>
</div>
</div>
<hr>
<div> </div>
<h1>五、三合一效果</h1>
<div> </div>
<div>你访问接口时,会自动:</div>
<div> </div>
<ol>
<li>Serilog/NLog 记录日志(控制台 + 文件)</li>
<li>AOP 拦截:记录方法执行、耗时、异常</li>
<li>限流保护:防止恶意刷接口</li>
</ol>
<div> </div>
<hr>
<div> </div>
<h3>总结</h3>
<div> </div>
<ol>
<li>日志:Serilog 最简单,NLog 更灵活,二选一即可</li>
<li>AOP:Autofac 拦截器实现统一日志、异常、耗时管理</li>
<li>限流:推荐 .NET 7+ 原生限流,轻量无依赖</li>
<li>所有代码可直接复制运行,无需额外调整</li>
</ol><br><br>
来源:https://www.cnblogs.com/chuansheng/p/19913713
頁:
[1]