ASP.NET Core中使用令牌桶算法限流1

简介: ASP.NET Core中使用令牌桶算法限流1

在服务限流时一般会限制某个时间周期内的请求数,简单点会采用固定窗口算法(也称计数器算法),这种算法实现相对简单,也很高效;但在实际的应用场景中请求并不是特别均匀,某些情况下会产生一些瞬时的突发流量,然后很快恢复正常,很多时候这并不会对系统产生破坏性的影响,但是固定窗口算法不能很好的处理这种情况。

比如某个数据查询接口限流每秒100次请求,绝大多数的时间里都不会超过这个数,但是偶尔某一秒钟会达到120次请求,接着很快又会恢复正常。此时如果采用固定窗口算法会触发限流,用户的正常访问会被干扰,体验上不太好;如果接口的调用方还有重试的逻辑,则在后续的时间窗口内系统可能收到更多的请求,然后更多的请求被限流,又产生更多的重试请求,循环往复让系统的负担愈加沉重,严重的话可能导致系统崩溃。

假设上文中120次的请求不会对系统稳定性带来实质性的影响,则可以在一定程度上允许这种瞬时的突发流量,从而为用户带来更好的使用体验,也可一定程度上避免因为限流重试导致系统负担进一步加重的问题。本文就介绍一种令牌桶的算法来应对这个情况。


算法原理


说了这么多,那么令牌桶算法怎么解决问题的呢?请看下图:

1689133395528.png


如上图所示,该算法的基本原理是:有一个令牌桶,容量是X,每Y单位时间会向桶中放入Z个令牌,如果桶中的令牌数超过X,则丢弃令牌;请求要想通过首先需要从令牌桶中获取一个令牌,获取不到令牌则拒绝请求。可以看出对于令牌桶算法X、Y、Z这几个数的设定特别重要,Z应该略大于绝大数时候的Y单位时间内的请求数,系统会长期处于这个状态,X可以是系统允许承载的瞬时最大请求数,系统不能长时间处于这个状态。


算法实现


这里讲两种实现方法:进程内即内存令牌桶算法、基于Redis的令牌桶算法。


进程内即内存令牌桶算法


这里在请求时计算投放数量,没有单独的投放处理,比固定窗口算法麻烦一些,但是仔细阅读,也很容易理解。

使用字典,Key是限流目标,Value包括当前令牌桶令牌数和上次令牌投放时间。初始状态下,认为每个限流目标的令牌桶是装满的,即令牌桶令牌数=令牌桶容量,不过仅在处理中发现限流目标的令牌桶不存在时才创建这个令牌桶。

请求进入后,根据限流目标在字典中查找:

  • 如果找不到,则创建令牌桶,并设置令牌数为:令牌桶容量-本次请求消耗令牌数,设置上次令牌投放时间为:当前时间。
  • 如果找到,则计算当前时间与上次令牌投放时间之间的间隔:
  • 如果大于等于令牌投放时间间隔,则计算令牌数为:max(令牌桶令牌数+令牌投放数量,令牌桶容量)-本次请求消耗令牌数,上次令牌投放时间为:当前时间。
  • 如果小于令牌投放时间间隔,则计算令牌数为:令牌桶令牌数-本次请求消耗令牌数。‘
  • 如果计算出的令牌数小于0,则触发限流,否则更新到令牌桶中。

在C#语言中可以使用MemoryCache,它的缓存项有一个过期时间,可以自动回收一些很少使用或者不再使用的令牌桶,减少内存占用。

进程内算法最适合单实例处理的程序限流,多实例处理的情况下可能每个实例收到的请求数不均匀,不能保证限流效果。


基于Redis的令牌桶算法


Redis作为KV存储,类似于字典,而且也自带过期时间。处理请求时,首先从请求中提取限流目标,然后根据限流目标去Redis中查找,其处理规则和内存算法一样,只不过使用了两个Redis KV:

  • 限流目标的令牌桶,Value是当前令牌数。
  • 限流目标的上次令牌投放时间,Value是上次投放令牌的时间戳。

这些操作逻辑可以封装在一个Lua script中,因为Lua script在Redis中执行时也是原子操作,所以Redis的限流计数在分布式部署时天然就是准确的。



相关文章
|
12月前
|
开发框架 .NET C#
ASP.NET Core Blazor 路由配置和导航
大家好,我是码农刚子。本文系统介绍Blazor单页应用的路由机制,涵盖基础配置、路由参数、编程式导航及高级功能。通过@page指令定义路由,支持参数约束、可选参数与通配符捕获,结合NavigationManager实现页面跳转与参数传递,并演示用户管理、产品展示等典型场景,全面掌握Blazor路由从入门到实战的完整方案。
788 6
|
开发框架 .NET 开发者
简化 ASP.NET Core 依赖注入(DI)注册-Scrutor
Scrutor 是一个简化 ASP.NET Core 应用程序中依赖注入(DI)注册过程的开源库,支持自动扫描和注册服务。通过简单的配置,开发者可以轻松地从指定程序集中筛选、注册服务,并设置其生命周期,同时支持服务装饰等高级功能。适用于大型项目,提高代码的可维护性和简洁性。仓库地址:<https://github.com/khellang/Scrutor>
952 5
|
人工智能 算法 Go
Go实现常见的限流算法
本文介绍了五种常见的限流算法:固定窗口、滑动窗口、漏桶算法、令牌桶和滑动日志。固定窗口简单高效,但可能产生两倍突发流量;滑动窗口可避免突发问题,但可能掐断流量;漏桶算法搭配生产者消费者模式实现平滑流量;令牌桶允许一定突发流量;滑动日志适用于多级限流场景。每种算法通过Go语言实现并附有代码解读,帮助理解其工作原理与适用场景。
312 6
|
开发框架 .NET C#
在 ASP.NET Core 中创建 gRPC 客户端和服务器
本文介绍了如何使用 gRPC 框架搭建一个简单的“Hello World”示例。首先创建了一个名为 GrpcDemo 的解决方案,其中包含一个 gRPC 服务端项目 GrpcServer 和一个客户端项目 GrpcClient。服务端通过定义 `greeter.proto` 文件中的服务和消息类型,实现了一个简单的问候服务 `GreeterService`。客户端则通过 gRPC 客户端库连接到服务端并调用其 `SayHello` 方法,展示了 gRPC 在 C# 中的基本使用方法。
621 5
在 ASP.NET Core 中创建 gRPC 客户端和服务器
|
开发框架 算法 中间件
ASP.NET Core 中的速率限制中间件
在ASP.NET Core中,速率限制中间件用于控制客户端请求速率,防止服务器过载并提高安全性。通过`AddRateLimiter`注册服务,并配置不同策略如固定窗口、滑动窗口、令牌桶和并发限制。这些策略可在全局、控制器或动作级别应用,支持自定义响应处理。使用中间件`UseRateLimiter`启用限流功能,并可通过属性禁用特定控制器或动作的限流。这有助于有效保护API免受滥用和过载。 欢迎关注我的公众号:Net分享 (239字符)
560 1
|
开发框架 缓存 .NET
GraphQL 与 ASP.NET Core 集成:从入门到精通
本文详细介绍了如何在ASP.NET Core中集成GraphQL,包括安装必要的NuGet包、创建GraphQL Schema、配置GraphQL服务等步骤。同时,文章还探讨了常见问题及其解决方法,如处理复杂查询、错误处理、性能优化和实现认证授权等,旨在帮助开发者构建灵活且高效的API。
611 3
|
12月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
899 0
|
12月前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
541 2
|
传感器 机器学习/深度学习 编解码
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
MATLAB|主动噪声和振动控制算法——对较大的次级路径变化具有鲁棒性
462 3

热门文章

最新文章