心那边 發表於 2026-4-25 14:59:00

.NET 集成 日志 (Serilog/NLog)、AOP、简单限流

<h2>一、环境准备(新建 .NET Web API)</h2>
<div>&nbsp;</div>
<div>先安装所有需要的 NuGet 包:</div>
<div>&nbsp;</div>
<h3>必装包</h3>
<div>&nbsp;</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>&nbsp;</div>
</div>
</div>
<div>&nbsp;</div>
<hr>
<div>&nbsp;</div>
<h1>二、日志实现(二选一即可)</h1>
<div>&nbsp;</div>
<h2>方案 1:Serilog(简洁强大)</h2>
<div>&nbsp;</div>
<h3>1. Program.cs 配置</h3>
<div>&nbsp;</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>&nbsp;</div>
</div>
</div>
<h3>2. 使用日志</h3>
<div>&nbsp;</div>
<div>
<div dir="ltr">
<div>
<pre><code>
")]
public class TestController : ControllerBase
{
    private readonly ILogger&lt;TestController&gt; _logger;

    // 直接注入使用
    public TestController(ILogger&lt;TestController&gt; logger)
    {
      _logger = logger;
    }

   
    public IActionResult Get()
    {
      _logger.LogInformation("请求 Test 接口");
      return Ok("Hello Serilog");
    }
}
</code></pre>
</div>
<div>&nbsp;</div>
</div>
</div>
<hr>
<div>&nbsp;</div>
<h2>方案 2:NLog(配置灵活)</h2>
<div>&nbsp;</div>
<h3>1. 添加 <code>nlog.config</code> 文件</h3>
<div>&nbsp;</div>
<div>
<div dir="ltr">
<div>
<div>xml</div>
<div>&nbsp;</div>
</div>
<div>
<pre><code>&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      autoReload="true"&gt;

&lt;targets&gt;
    &lt;target xsi:type="Console" name="console"/&gt;
    &lt;target xsi:type="File" name="file" fileName="logs/${shortdate}.log" layout="${longdate}|${level}|${message} ${exception:format=tostring}"/&gt;
&lt;/targets&gt;

&lt;rules&gt;
    &lt;logger name="*" minlevel="Info" writeTo="console,file"/&gt;
&lt;/rules&gt;
&lt;/nlog&gt;
</code></pre>
</div>
<div>&nbsp;</div>
</div>
</div>
<h3>2. Program.cs</h3>
<div>&nbsp;</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>&nbsp;</div>
</div>
</div>
<div>&nbsp;</div>
<div>使用方式和 Serilog 完全一样,直接注入 <code>ILogger&lt;T&gt;</code> 即可。</div>
<div>&nbsp;</div>
<hr>
<div>&nbsp;</div>
<h1>三、AOP 切面编程(Autofac + 拦截器)</h1>
<div>&nbsp;</div>
<h2>用途:自动记录方法执行日志、耗时、异常,不用每个方法手写</h2>
<div>&nbsp;</div>
<h3>1. 编写 AOP 拦截器</h3>
<div>&nbsp;</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&lt;LogInterceptor&gt; _logger;

    public LogInterceptor(ILogger&lt;LogInterceptor&gt; 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>&nbsp;</div>
</div>
</div>
<h3>2. 注册 Autofac + AOP</h3>
<div>&nbsp;</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&lt;ContainerBuilder&gt;(containerBuilder =&gt;
{
    // 注册拦截器
    containerBuilder.RegisterType&lt;LogInterceptor&gt;();

    // 注册需要 AOP 的服务(示例:TestService)
    containerBuilder.RegisterType&lt;TestService&gt;()
      .As&lt;ITestService&gt;()
      .EnableInterfaceInterceptors() // 开启接口拦截
      .InterceptedBy(typeof(LogInterceptor)); // 使用拦截器
});

builder.Services.AddControllers();
</code></pre>
</div>
<div>
<p>&nbsp;</p>
<div>
<div>
<div>&nbsp;</div>
<div>&nbsp;</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>&nbsp;</div>
<h2>&nbsp;</h2>
</div>
</div>
</div>
<h3>3. 测试服务 + 接口</h3>
<div>&nbsp;</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>&nbsp;</div>
</div>
</div>
<div>访问 <code>/test/aop</code> 就能看到 自动日志 + 耗时统计。</div>
<div>&nbsp;</div>
<hr>
<div>&nbsp;</div>
<h1>四、简单限流(2 种常用方案)</h1>
<div>&nbsp;</div>
<h2>方案 1:固定窗口限流(固定时间窗口限流,此外还有滑动窗口和令牌桶等)</h2>
<div>&nbsp;</div>
<h3>Program.cs</h3>
<div>&nbsp;</div>
<div>
<div dir="ltr">
<div>
<pre><code>using AspNetCoreRateLimit;

var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();

// 限流配置
builder.Services.AddInMemoryRateLimiting();
builder.Services.AddSingleton&lt;IRateLimitConfiguration, RateLimitConfiguration&gt;();

builder.Services.AddControllers();

var app = builder.Build();

// 启用限流
app.UseIpRateLimiting();

app.MapControllers();
app.Run();
</code></pre>
</div>
<div>&nbsp;</div>
</div>
</div>
<h3>添加限流规则(appsettings.json)</h3>
<div>&nbsp;</div>
<div>
<div dir="ltr">
<div>
<pre><code>"IpRateLimiting": {
"GeneralRules": [
    {
      "Endpoint": "*",
      "Period": "1m",
      "Limit": 10
    }
]
}
</code></pre>
</div>
<div>&nbsp;</div>
</div>
</div>
<div>表示:1 分钟内最多请求 10 次。</div>
<div>&nbsp;</div>
<hr>
<div>&nbsp;</div>
<h2>方案 2:.NET 原生限流</h2>
<div>&nbsp;</div>
<h3>Program.cs</h3>
<div>&nbsp;</div>
<div>
<div dir="ltr">
<div>
<pre><code>var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();

// 原生限流
builder.Services.AddRateLimiter(options =&gt;
{
    // 固定窗口:每秒最多 2 个请求
    options.AddFixedWindowLimiter("fixed", opt =&gt;
    {
      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>&nbsp;</div>
</div>
</div>
<h3>控制器使用</h3>
<div>&nbsp;</div>
<div>
<div dir="ltr">
<div>
<pre><code>
// 启用限流
public IActionResult LimitTest()
{
    return Ok("限流测试");
}
</code></pre>
</div>
<div>&nbsp;</div>
</div>
</div>
<hr>
<div>&nbsp;</div>
<h1>五、三合一效果</h1>
<div>&nbsp;</div>
<div>你访问接口时,会自动:</div>
<div>&nbsp;</div>
<ol>
<li>Serilog/NLog 记录日志(控制台 + 文件)</li>
<li>AOP 拦截:记录方法执行、耗时、异常</li>
<li>限流保护:防止恶意刷接口</li>
</ol>
<div>&nbsp;</div>
<hr>
<div>&nbsp;</div>
<h3>总结</h3>
<div>&nbsp;</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]
查看完整版本: .NET 集成 日志 (Serilog/NLog)、AOP、简单限流