You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为SignalR Hub方法配置生效的限流中间件?

问题原因

ASP.NET Core 自带的 Rate Limiting 中间件仅针对HTTP 请求管道生效,而 SignalR Hub 方法的调用是基于已建立的长连接(如 WebSocket)进行的消息交互,不会经过 HTTP 中间件管道,因此直接给 Hub 方法添加 [EnableRateLimiting] 特性无法触发限流逻辑。

解决方案

通过实现 SignalR 的 IHubFilter 过滤器,在 Hub 方法调用前手动集成限流策略,复用你已配置的 "fixed" 限流规则。

1. 自定义限流 Hub 过滤器

创建过滤器类,在方法调用前检查限流状态:

using Microsoft.AspNetCore.RateLimiting;
using Microsoft.AspNetCore.SignalR;
using System.Reflection;
using System.Threading.RateLimiting;

public class RateLimitingHubFilter : IHubFilter
{
    private readonly IRateLimiterFactory _rateLimiterFactory;

    public RateLimitingHubFilter(IRateLimiterFactory rateLimiterFactory)
    {
        _rateLimiterFactory = rateLimiterFactory;
    }

    public async ValueTask<object?> InvokeMethodAsync(HubInvocationContext invocationContext, Func<HubInvocationContext, ValueTask<object?>> next)
    {
        // 检查当前方法是否标记了限流特性
        var rateLimitAttr = invocationContext.Method
            .GetCustomAttribute<EnableRateLimitingAttribute>();

        if (rateLimitAttr == null)
        {
            return await next(invocationContext);
        }

        // 获取已配置的限流器(复用你定义的"fixed"策略)
        var limiter = _rateLimiterFactory.GetRateLimiter(rateLimitAttr.PolicyName);
        // 用用户ID作为限流键(无用户则用连接ID)
        var limitKey = invocationContext.Context.UserIdentifier ?? invocationContext.Context.ConnectionId;

        // 尝试获取限流许可
        using var lease = await limiter.AcquireAsync(limitKey);
        if (!lease.IsAcquired)
        {
            // 触发限流时抛出异常,前端会收到错误消息
            throw new HubException("请求过于频繁,请稍后重试。");
        }

        // 许可获取成功,执行原方法
        return await next(invocationContext);
    }
}

2. 注册过滤器到 SignalR

在 Program.cs 中,将自定义过滤器添加到 SignalR 的配置里:

var builder = WebApplication.CreateBuilder(args);

// 保留你原有的限流配置
builder.Services.AddRateLimiter(_ => _
    .AddFixedWindowLimiter(policyName: "fixed", options =>
    {
        options.PermitLimit = 4;
        options.Window = TimeSpan.FromSeconds(12);
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = 2;
    }));

// 注册SignalR并添加限流过滤器
builder.Services.AddSignalR(options =>
{
    options.AddFilter<RateLimitingHubFilter>();
});

var app = builder.Build();

app.UseRateLimiter();
// 注册你的SignalR Hub端点(示例)
app.MapHub<YourHub>("/your-hub");

app.Run();

3. 验证限流效果

保持你原有的 Hub 方法标记:

[EnableRateLimiting("fixed")]
public Task Test()
{
    // 方法逻辑
    return Task.CompletedTask;
}

当同一用户/连接在12秒内调用 Test 方法超过4次时,会触发限流并抛出异常,前端可捕获该错误提示用户。

内容的提问来源于stack exchange,提问作者Tomorrow will be better

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 00:15:23