ASP.NET Core使用filter和redis实现接口防重


在 ASP.NET Core 中使用过滤器(filter)和 Redis 实现接口防重的方法是一种有效的方式,特别是在需要处理并发请求时。接口防重通常用于避免用户多次提交相同请求导致的重复操作或数据异常。下面是实现这一功能的基本步骤:

步骤概述

  1. 安装 Redis 首先确保你的 ASP.NET Core 项目可以连接和使用 Redis。可以通过 NuGet 安装适当的 Redis 客户端库,例如 StackExchange.Redis。

    dotnet add package StackExchange.Redis
    
  2. 创建自定义过滤器 在 ASP.NET Core 中,你可以创建一个自定义的过滤器来实现接口防重逻辑。过滤器可以在控制器方法执行之前或之后拦截请求,并检查 Redis 中是否已经存在某个标识(例如请求 ID)。

    using System;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Mvc.Filters;
    using StackExchange.Redis;
    
    public class PreventDuplicateRequestAttribute : ActionFilterAttribute
    {
        private readonly IDatabase _redisDb;
    
        public PreventDuplicateRequestAttribute(IDatabase redisDb)
        {
            _redisDb = redisDb ?? throw new ArgumentNullException(nameof(redisDb));
        }
    
        public override async Task OnActionExecutingAsync(ActionExecutingContext context)
        {
            var requestId = context.HttpContext.TraceIdentifier; // 使用请求的 TraceIdentifier 作为请求 ID
            var isDuplicate = await _redisDb.StringSetAsync(requestId, "unique", TimeSpan.FromSeconds(60), When.NotExists);
    
            if (!isDuplicate)
            {
                context.Result = new BadRequestObjectResult("Duplicate request detected.");
                return;
            }
    
            await base.OnActionExecutingAsync(context);
        }
    }
    

    上述过滤器 PreventDuplicateRequestAttribute 实现了 ActionFilterAttribute 并覆盖了 OnActionExecutingAsync 方法。在这个方法中,它获取当前请求的 TraceIdentifier 作为请求 ID,并尝试将该请求 ID 存储到 Redis 中。设置过期时间可以确保 Redis 中的键不会永久存在,当超过过期时间后会自动删除。

  3. 在控制器方法中使用过滤器 在需要防重的控制器方法上使用刚刚定义的过滤器即可:

    [ApiController]
    [Route("api/[controller]")]
    public class MyController : ControllerBase
    {
        [HttpPost("my-action")]
        [ServiceFilter(typeof(PreventDuplicateRequestAttribute))]
        public IActionResult MyAction()
        {
            // 处理逻辑
            return Ok();
        }
    }
    

    MyAction 方法上使用了 [ServiceFilter(typeof(PreventDuplicateRequestAttribute))] 属性,这样每次请求该方法时,都会执行 PreventDuplicateRequestAttribute 中的逻辑来检查并防止重复请求。

  4. 配置 Redis 连接 在 ASP.NET Core 的 Startup.cs 中配置 Redis 连接,并注入到自定义过滤器中:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddSingleton<IConnectionMultiplexer>(ConnectionMultiplexer.Connect("your-redis-connection-string"));
        services.AddScoped<IDatabase>(sp => sp.GetRequiredService<IConnectionMultiplexer>().GetDatabase());
    
        services.AddControllers();
    }
    

    这里通过 AddSingleton 注册了 Redis 连接,并且通过 AddScoped 注册了 IDatabase 接口的实现,以便在过滤器中使用。

注意事项

  • 并发处理:考虑并发请求情况下的处理逻辑,确保不同请求的并发不会导致误判。
  • 过期时间:根据实际需求设置合适的 Redis 键过期时间,避免 Redis 中的键占用过多内存。
  • 错误处理:在过滤器中处理 Redis 操作可能出现的异常情况,例如连接断开或超时。

通过以上步骤,你可以在 ASP.NET Core 中实现基于 Redis 的接口防重功能,确保每个请求都能按预期处理,避免重复提交或并发导致的问题。


原文链接:codingdict.net