高并发系统设计 -- 服务限流算法

news2024/11/15 8:40:00

常见的限流算法

漏桶算法

img

漏桶法的关键点在于漏桶始终按照固定的速率运行,但是它并不能很好的处理有大量突发请求的场景,毕竟在某些场景下我们可能需要提高系统的处理效率,而不是一味的按照固定速率处理请求。

关于漏桶的实现,uber团队有一个开源的github.com/uber-go/ratelimit库。 这个库的使用方法比较简单,Take() 方法会返回漏桶下一次滴水的时间。

package main

import (
   "fmt"
   "time"

   "go.uber.org/ratelimit"
)

func main() {
   r1 := ratelimit.New(10) // (10表示1s/10,即每100ms(0.1s)运行一次;同理,1表示1s/1,即每秒运行一次)
   prev := time.Now()
   for i := 0; i < 10; i++ {
      now := r1.Take()
      fmt.Println(i, now.Sub(prev))
      prev = now
   }
}

令牌桶算法

令牌桶(Token bucket)其实和漏桶的原理类似,令牌桶按固定的速率往桶里放入令牌,并且只要能从桶里取出令牌就能通过令牌桶支持突发流量的快速处理

img

对于从桶里取不到令牌的场景,我们可以选择等待也可以直接拒绝并返回。

对于令牌桶的Go语言实现,大家可以参照github.com/juju/ratelimit库。这个库支持多种令牌桶模式,并且使用起来也比较简单。

创建令牌桶的方法:

// 创建指定填充速率和容量大小的令牌桶
func NewBucket(fillInterval time.Duration, capacity int64) *Bucket
// 创建指定填充速率、容量大小和每次填充的令牌数的令牌桶
func NewBucketWithQuantum(fillInterval time.Duration, capacity, quantum int64) *Bucket
// 创建填充速度为指定速率和容量大小的令牌桶
// NewBucketWithRate(0.1, 200) 表示每秒填充20个令牌
func NewBucketWithRate(rate float64, capacity int64) *Bucket

取出令牌的方法如下:

// 取token(非阻塞)
func (tb *Bucket) Take(count int64) time.Duration
func (tb *Bucket) TakeAvailable(count int64) int64

// 最多等maxWait时间取token
func (tb *Bucket) TakeMaxDuration(count int64, maxWait time.Duration) (time.Duration, bool)

// 取token(阻塞)
func (tb *Bucket) Wait(count int64)
func (tb *Bucket) WaitMaxDuration(count int64, maxWait time.Duration) bool

虽说是令牌桶,但是我们没有必要真的去生成令牌放到桶里,我们只需要每次来取令牌的时候计算一下,当前是否有足够的令牌就可以了,具体的计算方式可以总结为下面的公式:

当前令牌数 = 上一次剩余的令牌数 + (本次取令牌的时刻-上一次取令牌的时刻)/放置令牌的时间间隔 * 每次放置的令牌数

我们推荐使用令牌桶算法。

gin中使用限流中间件

import (
   "github.com/gin-gonic/gin"
   "github.com/juju/ratelimit"
   "net/http"
   "time"
)

func RateLimit() gin.HandlerFunc {
   // 每100ms填充一个令牌,令牌桶容量为10000
   bucket := ratelimit.NewBucket(time.Microsecond*100, int64(10000))
   return func(c *gin.Context) {
      // 如果获取不到令牌就中断本次请求返回
      if bucket.TakeAvailable(1) < 1 {
         c.JSON(http.StatusOK, gin.H{
            "msg": "rate limit...",
         })
         c.Abort()
         return
      }
   }
}

我们可以看到这个中间件里面使用了c.Abort这一个代码,所以接下来我们来讲解一下c.Abort

c.Next和c.Abort

Next():在当前中间件中调用c.Next()时会中断当前中间件中后续的逻辑转而执行后续的中间件和handlers,等它们全部执行完之后再回来执行当前中间件的后续代码。

结论

  • c.Next()只针对当前的中间件,并不影响其他中间件。如果在中间件函数的非结尾调用Next()方法当前中间件剩余代码会被暂停执行,会先去执行后续中间件及handlers,等这些handlers全部执行完以后程序控制权会回到当前中间件继续执行剩余代码;
  • 如果想中断剩余中间件以及handlers应该使用Abort方法,但需要注意当前中间件的剩余代码会继续执行。
  • 如果想提前中止当前中间件的执行应该使用return退出而不是Next()方法;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/132233.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

快速入门 .NET nanoFramework 开发 ESP32-Pico 应用

本文是一篇适合初学者的 .NET nanoFramework 保姆级入门教程&#xff0c;并提供了基本的入门程序并介绍了微雪的 ESP32-S2-Pico 使用 .NET nanoFramework 开发过程的基础知识。 目录 1. 背景 1.1 .NET IOT 与 .NET nanoFramework 1.2 微控制器 1.3 实验板介绍 2. 搭建 .NET…

移动Web【空间转换[空间位移、透视、空间旋转、立体呈现、3D导航、空间缩放]、动画、综合案例】

文章目录一、空间转换1.1 空间位移1.2 透视1.3 空间旋转1.4 立体呈现1.5 3D导航1.6 空间缩放二、动画2.1 动画的实现步骤2.2 动画属性三、综合案例2.1 走马灯一、空间转换 空间&#xff1a;是从坐标轴角度定义的。 x 、y 和z三条坐标轴构成了一个立体空间&#xff0c;z轴位置与…

Android实战进阶 - 拉取项目代码后多处报红?如资源找不到该如何处理?

近期参与了一个我很感兴趣的项目&#xff0c;项目内用到了很多新东西&#xff0c;例如组件化、模块化、ARouter路由、MVI框架、Kt高阶用法等等&#xff0c;感觉可以学一段时间… Gradle相关Blog Android Gradle - Gradle、Gradle plugin 基础认知Android Gradle - AndroidStud…

函数极限定义的理解

回顾一下非正式的极限定义法。当x从任意一侧(自左向右或自右向左)接近常量 c时&#xff0c;如果f(x)变得任意接近一个单独的值L, 则当x接近c时f(x)的极限值是L, 写作 咋一看&#xff0c;这个定义似乎非常技术化。即使这样&#xff0c;它仍然是非正式的&#xff0c;因为它没有给…

三、Django -视图

Django 提示&#xff1a;本文根据b站黑马python课整理 链接指引 > 黑马程序员python企业级开发项目-手把手从0到1开发《美多商城》 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录Django视图介绍和项目准备视图…

【数据集6】全球人工不透水面积GAIA(清华数据)

全球人工不透水面积&#xff08;lobal artificial impervious area, GAIA&#xff09; 人工不透水区是表征建成区和城市范围的重要覆盖类型&#xff0c;特别是在较细的空间分辨率下。 1 简介 原理&#xff1a; 由Landsat卫星图像和辅助数据集生成&#xff0c;如夜间灯光数据…

健康码识别[QT+OpenCV]

&#x1f482; 个人主页:风间琉璃&#x1f91f; 版权: 本文由【风间琉璃】原创、在CSDN首发、需要转载请联系博主&#x1f4ac; 如果文章对你有帮助、欢迎关注、点赞、收藏(一键三连)和订阅专栏哦目录 一、识别原理 1.二维码定位 2.颜色识别 二、部分源码 一、识别原理 二维…

matlab实现基本相位调制

相位调制&#xff08;PM&#xff09;是将信息编码为载波的瞬时相位变化的一种调制模式。 调相的基本表达式如下&#xff1b; 载波c(t)是一个标准正弦信号&#xff1b;m(t)是调制信号&#xff1b;调制以后是把m(t)的变化附加到了载波的相位变化上&#xff1b; 调相的基本示意如…

WPF中iconfont图标库的使用

总目录 文章目录总目录前言一、查找项目需要的图标二、图标的使用1.将下载的文件解压缩2.将ttf文件复制粘贴到自己的项目中3.使用总结前言 本文主要介绍在WPF中iconfont图标库的使用 一、查找项目需要的图标 首先进入阿里巴巴矢量图标库网站&#xff0c;登录自己的账号&#…

MySQL快速生成大量测试数据 (脚本一键生成分表数据)

生成128个分表的测试数据敲到手累&#xff1b; 生成的测试数据虽然有离散分布&#xff0c;但随着时间的增长数据量不增反降&#xff0c;不符合大多数线上业务的增长趋势&#xff1b; 生成的测试数据部分超过当前日期。 具体表现如下图所示&#xff1a; 我们直接看下脚本的用法…

月入8000+的steam/csgo搬砖项目(详细拆解)

大家好&#xff0c;我是阿阳 今天就给大家带来一个在steam游戏搬砖项目的拆解&#xff0c;目前这个项目我们团队也一直在带队实操&#xff0c;已经跑通了项目的整个流程&#xff0c;提炼出了完整的赚钱体系。 先给大家看看近期的收益情况&#xff1a; 近期的出售记录&#xf…

[ Azure - Database ] Azure Database for MySQL 配置Auditing并查看使用

传统MySQL的二进制日志binlog可以说是MySQL最重要的日志&#xff0c;它记录了所有的DDL和DML语句&#xff08;除了数据查询语句select&#xff09;&#xff0c;以事件形式记录&#xff0c;还包含语句所执行的消耗的时间。本文会讲解微软云Azure Database for MySQL的binlog相关…

i.MX8MP平台开发分享(IOMUX篇)- 硬件原理

专栏目录&#xff1a;专栏目录传送门 平台内核i.MX8MP5.15.71文章目录1.前言2.IOMUX原理3. 寄存器实例&#xff1a;UART1_RX3.1 PAD: UART1_RXD3.2 PAD: SD1_CMD3.3 PAD: SAI2_RXC3.4 Input select3.5 功能实现4.SION1.前言 我们都知道&#xff0c;芯片包含数量有限的引脚&am…

BeanFactory和Applicationcontext实现

1.容器接口 1.BeanFactory能做哪些事 1.什么是beanFactory 它是spring的核心容器 是ApplicationContext的父接口 ApplicationContext扩展实现都【组合了】beanFactory 2.BeanFactory的功能 明面上只有getBean()方法实际上控制反转、依赖注入、bean生命周期的各种功能都…

tslib-1.4在I.MX6ULL开发板上电容屏不能触摸问题

一、前言 在采用触摸屏的移动终端中&#xff0c;触摸屏性能的调试是个重要问题之一&#xff0c;因为电磁噪声的缘故&#xff0c;触摸屏容易存在点击不准确、有抖动等问题。Tslib是一个开源的程序&#xff0c;能够为触摸屏驱动获得的采样提供诸如滤波、去抖、校准等功能&#x…

ESP32-S3 >>> MicroPython 编程初探

今天买了一个ESP32-S3&#xff0c;打算试试在这上面进行MicroPython的编程&#xff08;附资料网址&#xff09;。 首先为了在ESP32上进行mp的编程&#xff0c;需要对其重新烧录固件。这就需要我们电脑安装好CH343驱动&#xff0c;然后找到适用于ESP32-S3的固件&#xff0c;利用…

Diffusion详解及PyTorch代码

首先附上几个大佬的讲解 lilianweng-diffusion-models 这篇博客借鉴了上述博客和视频&#xff0c;同时加上个人的理解整合了一下&#xff0c;整个推导过程非常详细&#xff0c;希望能使每个人都看懂 结合之前讲过的VAE和GAN模型&#xff0c;Diffusion Model和他们的区别就是…

Apache Struts2远程代码执行漏洞(S2-015)复现及修复方案

Apache Struts2远程代码执行漏洞(S2-015)介绍 Apache Struts 2是用于开发JavaEE Web应用程序的开源Web应用框架。Apache Struts 2.0.0至2.3.14.2版本中存在远程命令执行漏洞。远程攻击者可借助带有‘${}’和‘%{}’序列值&#xff08;可导致判断OGNL代码两次&#xff09;的请求…

LabVIEW​​共享​变量生命周期

LabVIEW​​共享​变量生命周期 共享​变量​生命​周期 ​所有​共享​变量​都是​项目​库​的​一部分。​SVE​将会​注册​项目​库​和​库​中​包含​的​共享​变量​&#xff08;当​LabVIEW​需要​调​用​其中​某​个​变量​时&#xff09;​。​默认​情况​…

AlphaGo简易版MuGo源码解析

文章目录前言源码实现MuGo的输入数据模型的搭建模型的训练参考链接结语前言 自从AlphaGo横空出世&#xff0c;战胜李世石后&#xff0c;AI围棋如雨后春笋一般遍地开花。阅读DeepMind的论文有时还是隔靴搔痒&#xff0c;只有钻到代码里&#xff0c;才能一探究竟。于是&#xff…