English 简体中文 繁體中文 한국 사람 日本語 Deutsch русский بالعربية TÜRKÇE português คนไทย french
查看: 4|回复: 0

如何为 .NET 在线客服系统的 Open Api 开放接口实现 QPS 限流功能

[复制链接]
查看: 4|回复: 0

如何为 .NET 在线客服系统的 Open Api 开放接口实现 QPS 限流功能

[复制链接]
查看: 4|回复: 0

227

主题

0

回帖

691

积分

高级会员

积分
691
4VAqEYxBm

227

主题

0

回帖

691

积分

高级会员

积分
691
2025-2-16 23:30:58 | 显示全部楼层 |阅读模式
我在业余时间开发了一款自己的独立产品:升讯威在线客服与营销系统。陆陆续续开发了几年,从一开始的偶有用户尝试,到如今线上环境和私有化部署均有了越来越多的稳定用户。
而我收到的用户需求也越来越多,产品化的需求,个性化的需求都有。最近两天收到一个用户的开放接口需求,为客服系统的 Open Api 开放接口提供一个获取在线访客列表的接口。

如何在 .NET 系统中实现 Open Api 我在前文分解过,今天我想分享的是如何为在线客服系统的开放接口设计实现一个 QPS 限流功能

如下图所示,在为用户提供接口的过程中,我对这个接口应用了基本的 QPS 限流技术。

<hr>什么是 QPS 接口限流

QPS(Queries Per Second,查询每秒)接口限流是指对 API 或网络服务的访问进行限制,控制每秒钟可以接受的最大请求数量。这种限流机制常用于防止服务器因为过多的请求而被过载,从而保证服务的稳定性和性能。
QPS 限流的具体做法通常是:

  • 设置最大 QPS 限制:对于每个用户、IP 地址或系统等,设定一个请求次数上限。比如,一个接口每秒钟最多允许 100 次请求。
  • 超限处理:当请求数超过设定的 QPS 限制时,系统通常会拒绝多余的请求,返回错误信息(如 HTTP 429 Too Many Requests)。有时,也可能选择进行排队、重试等处理。
  • 分级限流:为了避免单一用户或 IP 造成整个系统的拥塞,可以根据用户类型、接口的优先级等进行不同的限流策略。
  • 突发流量处理:对于突发的高频请求,系统可能允许短时间内的超出限制的请求,但会有相应的窗口期或滑动窗口来平滑流量。
QPS 限流的目的通常是:

  • 防止恶意请求或过多请求导致服务崩溃。
  • 确保公平性,避免单个用户或请求占用过多资源。
  • 提高服务的可用性和稳定性。
.NET 接口有哪些QPS限流方案

1. 基于内存的限流(Memory-based Rate Limiting)


  • 这种方法使用内存中的数据结构(如 Dictionary 或 Queue)来记录每个用户或请求的时间戳,从而计算每秒钟的请求数量。
  • 适用于流量较小、对性能要求较高的场景。
示例
public class MemoryRateLimiter{    private readonly int _maxQps;    private readonly Dictionary<string, Queue<DateTime>> _requests = new Dictionary<string, Queue<DateTime>>();    public MemoryRateLimiter(int maxQps)    {        _maxQps = maxQps;    }    public bool IsRequestAllowed(string key)    {        var now = DateTime.UtcNow;        if (!_requests.ContainsKey(key))        {            _requests[key] = new Queue<DateTime>();        }        var requestQueue = _requests[key];        // Remove requests older than 1 second        while (requestQueue.Count > 0 && (now - requestQueue.Peek()).TotalSeconds >= 1)        {            requestQueue.Dequeue();        }        // Check if the current request exceeds the limit        if (requestQueue.Count >= _maxQps)        {            return false;        }        requestQueue.Enqueue(now);        return true;    }}2. 基于令牌桶算法(Token Bucket)

令牌桶算法是一种流量控制算法,它通过给每个请求一个令牌来限制流量。每秒钟会向桶中添加一定数量的令牌,只有获取到令牌的请求才能通过。

  • 适合需要处理突发流量的场景,因为令牌桶可以在短时间内允许一定数量的超限请求。
  • .NET 没有内置令牌桶算法,但可以自己实现或使用一些开源库(例如 RateLimiter 包)。
示例
public class TokenBucketRateLimiter{    private readonly int _bucketCapacity;    private readonly int _tokensPerSecond;    private int _tokens;    private DateTime _lastRefillTime;    public TokenBucketRateLimiter(int bucketCapacity, int tokensPerSecond)    {        _bucketCapacity = bucketCapacity;        _tokensPerSecond = tokensPerSecond;        _tokens = bucketCapacity;        _lastRefillTime = DateTime.UtcNow;    }    public bool IsRequestAllowed()    {        var now = DateTime.UtcNow;        var elapsedSeconds = (now - _lastRefillTime).TotalSeconds;        // Refill tokens        if (elapsedSeconds > 1)        {            _tokens = Math.Min(_bucketCapacity, _tokens + (int)(elapsedSeconds * _tokensPerSecond));            _lastRefillTime = now;        }        // Check if we have tokens available        if (_tokens > 0)        {            _tokens--;            return true;        }        return false;    }}3. 基于滑动窗口(Sliding Window)

滑动窗口限流算法通过维护一个请求的时间窗口来限制请求次数。在窗口内,最多可以接受一定数量的请求。每次请求都会刷新这个窗口,并根据窗口内的请求数决定是否允许请求通过。

  • 适合对请求的时间分布进行精确控制的场景。
  • 实现相对复杂,但能更平滑地处理流量。
示例
public class SlidingWindowRateLimiter{    private readonly int _maxQps;    private readonly TimeSpan _windowSize;    private readonly Queue<DateTime> _requests = new Queue<DateTime>();    public SlidingWindowRateLimiter(int maxQps, TimeSpan windowSize)    {        _maxQps = maxQps;        _windowSize = windowSize;    }    public bool IsRequestAllowed()    {        var now = DateTime.UtcNow;        // Remove requests that are outside the window        while (_requests.Count > 0 && (now - _requests.Peek()).TotalMilliseconds > _windowSize.TotalMilliseconds)        {            _requests.Dequeue();        }        // Check if we can allow the request        if (_requests.Count < _maxQps)        {            _requests.Enqueue(now);            return true;        }        return false;    }}4. 使用第三方库(如 AspNetCoreRateLimit)

AspNetCoreRateLimit 是一个非常流行的 .NET 库,可以帮助开发者轻松实现 API 的限流。它支持多种限流算法,如固定窗口、滑动窗口、令牌桶等,并且可以在 ASP.NET Core 中使用。
安装 NuGet 包
dotnet add package AspNetCoreRateLimit配置示例:
public void ConfigureServices(IServiceCollection services){    // Add rate limiting services    services.AddInMemoryRateLimiting();    services.Configure<IpRateLimitOptions>(options =>    {        options.GeneralRules = new List<RateLimitRule>        {            new RateLimitRule            {                Endpoint = "*",                Period = "1s",   // Limit requests per second                Limit = 100       // Max 100 requests per second            }        };    });    services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();}public void Configure(IApplicationBuilder app){    app.UseIpRateLimiting();}5. 使用 Redis 实现分布式限流

如果你的应用是分布式的,可以使用 Redis 来存储每个请求的时间戳或者计数器,从而实现跨多台服务器的 QPS 限流。
示例
public class RedisRateLimiter{    private readonly string _key;    private readonly int _maxQps;    private readonly IDatabase _database;    public RedisRateLimiter(string key, int maxQps, IConnectionMultiplexer redis)    {        _key = key;        _maxQps = maxQps;        _database = redis.GetDatabase();    }    public async Task<bool> IsRequestAllowedAsync()    {        var now = DateTime.UtcNow;        var timeFrame = TimeSpan.FromSeconds(1);        var requestCount = await _database.ListLengthAsync(_key);        // Remove expired requests from the list        await _database.ListRemoveAsync(_key, now.Add(-timeFrame).ToString());        if (requestCount < _maxQps)        {            // Add current request time to the list            await _database.ListLeftPushAsync(_key, now.ToString());            return true;        }        return false;    }}6. 基于 ASP.NET Core 中间件限流

在 ASP.NET Core 应用中,可以创建一个中间件来处理请求限流逻辑,并通过 HTTP 请求的头信息来告知客户端当前的请求状态。
示例
public class RateLimitingMiddleware{    private readonly RequestDelegate _next;    private readonly MemoryRateLimiter _rateLimiter;    public RateLimitingMiddleware(RequestDelegate next, MemoryRateLimiter rateLimiter)    {        _next = next;        _rateLimiter = rateLimiter;    }    public async Task InvokeAsync(HttpContext context)    {        if (!_rateLimiter.IsRequestAllowed(context.Connection.RemoteIpAddress.ToString()))        {            context.Response.StatusCode = 429;            await context.Response.WriteAsync("Rate limit exceeded.");            return;        }        await _next(context);    }}总结

在 .NET 中实现 QPS 限流有很多方案,对于小流量的应用,内存限流和基于中间件的限流方式可能已经足够,而对于高并发的分布式系统,可能需要 Redis 或者更复杂的算法,如令牌桶或滑动窗口。
<hr>简介下这个 .net 开发的小系统

https://kf.shengxunwei.com/
升讯威在线客服与营销系统是一款客服软件,但更重要的是一款营销利器。

  • 可以追踪正在访问网站或使用 APP 的所有访客,收集他们的浏览情况,使客服能够主动出击,施展话术,促进成单。
  • 可嵌入网站、手机 APP、公众号、或者通过 URL 地址直接联系客服。
  • 支持访客信息互通,可传输访客标识、名称和其它任意信息到客服系统,与您的业务系统对接。
  • 可全天候 7 × 24 小时挂机运行,网络中断,拔掉网线,手机飞行模式,不掉线不丢消息,欢迎实测。


希望能够打造: 开放、开源、共享。努力打造 .net 社区的一款优秀开源产品。
钟意的话请给个赞支持一下吧,谢谢~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

227

主题

0

回帖

691

积分

高级会员

积分
691

QQ|智能设备 | 粤ICP备2024353841号-1

GMT+8, 2025-3-12 20:42 , Processed in 1.525746 second(s), 29 queries .

Powered by 智能设备

©2025

|网站地图