限流算法,基于go的gRPC 实现的
目录
一、单机限流
1、令牌桶算法
3、固定窗口限流算法
4、滑动窗口
二、集群限流
1、分布式固定窗口 (基于redis)
2、分布式滑动窗口
一、单机限流
1、令牌桶算法
令牌桶算法是当流量进入系统前需要获取令牌,没有令牌那么就要进行限流
这个算法是怎么实现的呢
-
定义一个后台协程按照一定的频率去产生token
-
后台协程产生的token 放到固定大小容器里面
-
有流量进入系统尝试拿到token,没有token 就需要限流了

type TokenBucketLimiter struct {token chan struct{}stop chan struct{}
}
func NewTokenBucket(capactity int, timeInternal time.Duration) *TokenBucketLimiter {te := make(chan struct{}, capactity)stop := make(chan struct{})ticker := time.NewTicker(timeInternal)go func() {defer ticker.Stop()for {select {case <-ticker.C:select {case te <- struct{}{}:default:
}case <-stop:return}}}()return &TokenBucketLimiter{token: te,stop: stop,}
}
func (t *TokenBucketLimiter) BuildServerInterceptor() grpc.UnaryServerInterceptor {return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {select {case <-ctx.Done():err = ctx.Err()returncase <-t.token:return handler(ctx, req)case <-t.stop:err = errors.New("缺乏保护")return}}
}
func (t *TokenBucketLimiter) Stop() {close(t.stop)
}
3、固定窗口限流算法
什么是固定窗口限流算法
固定窗口限流算法(Fixed Window Rate Limiting Algorithm)是一种最简单的限流算法,其原理是在固定时间窗口(单位时间)内限制请求的数量。该算法将时间分成固定的窗口,并在每个窗口内限制请求的数量。具体来说,算法将请求按照时间顺序放入时间窗口中,并计算该时间窗口内的请求数量,如果请求数量超出了限制,则拒绝该请求。
优点:实现简单
缺点:对于瞬时流量没发处理,也就是临界问题,比如下图在20t前后,在16t以及26t有大量流量进来,在这10t中,已经超过了流量限制,没法限流
实现如下

type fixWindow1 struct {lastVistTime int64vistCount int64interval int64maxCount int64
}
func NewfixWindow1(macCount int64) *fixWindow1 {t := &fixWindow1{maxCount: macCount,}return t
}
func (f *fixWindow1) FixWindow1() grpc.UnaryServerInterceptor {return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {current := time.Now().UnixNano()lasttime := atomic.LoadInt64(&f.lastVistTime)if lasttime+f.interval > current {if atomic.CompareAndSwapInt64(&f.lastVistTime, lasttime, current) {atomic.StoreInt64(&f.lastVistTime, current)atomic.StoreInt64(&f.maxCount, 0)}}count := atomic.AddInt64(&f.vistCount, 1)if count > f.maxCount {return gen.GetByIDResp{}, errors.New("触发限流")}return handler(ctx, req)}
}
4、滑动窗口
什么是滑动窗口算法:
滑动窗口限流算法是一种常用的限流算法,用于控制系统对外提供服务的速率,防止系统被过多的请求压垮。它将单位时间周期分为n个小周期,分别记录每个小周期内接口的访问次数,并且根据时间滑动删除过期的小周期。它可以解决固定窗口临界值的问题。

type slideWindow struct {
timeWindow *list.Listinterval int64maxCnt intlock sync.Mutex
}
func NewSlideWindow(interval time.Duration, maxCnt int) *slideWindow {t := &slideWindow{timeWindow: list.New(),interval: interval.Nanoseconds(),maxCnt: maxCnt,}return t
}
func (s *slideWindow) SlideWinowlimit() grpc.UnaryServerInterceptor {return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {s.lock.Lock()now := time.Now().UnixNano()// 快路径if s.timeWindow.Len() < s.maxCnt {resp, err = handler(ctx, req)s.timeWindow.PushBack(now)s.lock.Unlock()return}front := s.timeWindow.Front()for front != nil && front.Value.(int64)+s.interval < now {s.timeWindow.Remove(front)front = s.timeWindow.Front()}if s.timeWindow.Len() >= s.maxCnt {s.lock.Unlock()return &gen.GetByIdReq{}, errors.New("触发限流")}s.lock.Unlock()resp, err = handler(ctx, req)s.timeWindow.PushBack(now)return}
}
二、集群限流
下面是分布式限流,为啥是分布式限流,单机限流只能对单台服务器进行限流,没发对集权进行限流,需要用分布式限流来进行集权限流
1、分布式固定窗口 (基于redis)
type redisFix struct {
serName stringinterVal intlimitCnt intredis redis.Cmdable
}
//go:embed lua/fixwindow.lua
var lua_redis_fix string
func NewRedisFix(serName string, interval int, limitCnt int, redis redis.Cmdable) *redisFix {t := &redisFix{serName: serName,interVal: interval,limitCnt: limitCnt,redis: redis,}return t
}
func (r *redisFix) RedisFix() grpc.UnaryServerInterceptor {return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {res, err := r.limit(ctx)if err != nil {return &gen.GetByIDResp{}, err}if res {return &gen.GetByIdReq{}, errors.New("触发限流")}return handler(ctx, req)}
}
func (r *redisFix) limit(ctx context.Context) (res bool, err error) {keys := []string{r.serName}res, err = r.redis.Eval(ctx, lua_redis_fix, keys, r.interVal, r.limitCnt).Bool()return
}
lua
local key = KEYS[1]
local limitCnt = tonumber(ARGV[2])
local val = redis.call('get',key)
if val==false thenif limitCnt<1 thenreturn "true"elseredis.call('set',key,1,'PX',ARGV[1])return "false"end
elseif tonumber(val)<limitCnt thenredis.call('incr',key)return "false"
elsereturn "true"
end
2、分布式滑动窗口
//go:embed lua/slidewindow.lua
var slideWindLua string
type redisSlib struct {serverName stringinterVal time.DurationmaxCnt int64redis redis.Cmdable
}
func NewRedisSlib(interval time.Duration, maxCnt int64, serverName string, clientCmd redis.Cmdable) *redisSlib {t := &redisSlib{serverName: serverName,interVal: interval,maxCnt: maxCnt,redis: clientCmd,}return t
}
func (r *redisSlib) RedisSlibLimt() grpc.UnaryServerInterceptor {return func(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {limt, err := r.limt(ctx)if err != nil {return nil, err}if limt {return nil, errors.New("限流")}return handler(ctx, req)}
}
func (r *redisSlib) limt(ctx context.Context) (bool, error) {now := time.Now().UnixMilli()return r.redis.Eval(ctx, slideWindLua, []string{r.serverName}, r.interVal.Milliseconds(), r.maxCnt, now).Bool()
}
lua
local key = KEYS[1]
local window = tonumber(ARGV[1])
local maxCnt = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
--- 窗口的最小边界
local min = now-window
redis.call('ZREMRANGEBYSCORE',key,'-inf',min)
local cnt = redis.call('ZCOUNT',key,'-inf','+inf')
if cnt>=maxCnt thenreturn "true"
elseredis.call('ZADD',key,now,now)redis.call('PEXPIRE',key,window)return "false"
end
相关文章:
限流算法,基于go的gRPC 实现的
目录 一、单机限流 1、令牌桶算法 3、固定窗口限流算法 4、滑动窗口 二、集群限流 1、分布式固定窗口 (基于redis) 2、分布式滑动窗口 一、单机限流 1、令牌桶算法 令牌桶算法是当流量进入系统前需要获取令牌,没有令牌那么就要进行限…...
Shell中HTTP变量和文本处理
在Shell中,HTTP变量和文本处理是常见的任务之一。Shell是一个命令行解释器,可以用来自动化执行各种系统任务。在Shell中,我们可以使用各种命令和工具来处理HTTP变量和文本。 首先,让我们来看看如何在Shell中处理HTTP变量。HTTP变…...
java学习part39map
159-集合框架-Map不同实现类的对比与HashMap中元素的特点_哔哩哔哩_bilibili 1.Map 2.Entry 个人理解是c的pair,代表一个键值对。Map就是entry的叠加 3.常用方法 4.TreeMap 5.Properties...
使用sqoop操作HDFS与MySQL之间的数据互传
一,数据从HDFS中导出至MySQL中 1)开启Hadoop、mysql进程 start-all.sh/etc/init.d/mysqld start/etc/init.d/mysqld status 2)将学生数据stu_data.csv传到HDFS的/local_student目录下 在hdfs中创建目录 hdfs dfs -mkdir /local_student 上…...
Kafka使用指南
Kafka简介架构设计Kafka的架构设计关键概念Kafka的架构设计关键机制 Partition介绍Partition工作机制 应用场景ACK机制介绍ACK机制原理ACK机制对性能的影响ACK控制粒度Kafka分区数对集群性能影响调整分区优化集群性能拓展Kafka数据全局有序 Kafka简介 Kafka是由Apache软件基金…...
HarmonyOS4.0从零开始的开发教程03初识ArkTS开发语言(中)
HarmonyOS(二)初识ArkTS开发语言(中)之TypeScript入门 浅析ArkTS的起源和演进 1 引言 Mozilla创造了JS,Microsoft创建了TS,Huawei进一步推出了ArkTS。 从最初的基础的逻辑交互能力,到具备类…...
西工大计算机学院计算机系统基础实验一(函数编写1~10)
还是那句话,千万不要慌,千万不要着急,耐下性子慢慢来,一步一个脚印,把基础打的牢牢的,一样不比那些人差。回到实验本身,自从按照西工大计算机学院计算机系统基础实验一(…...
VMware 虚拟机 电脑重启后 NAT 模式连不上网络问题修复
问题描述: 昨天 VMware 安装centos7虚拟机,网络模式配置的是NAT模式,配置好后,当时能连上外网,今天电脑重启后,发现连不上外网了 检查下各个配置,都没变动,突然就连不上了 网上查了…...
【桑基图】绘制桑基图
绘制桑基图 一、绘制桑基图(1)方法一:去在线网站直接绘制(2)方法二:写html之后在vscode上运行 二、遇到的问题(1)当导入一些excel的时候,无法绘制出桑基图 一、绘制桑基图…...
ACM32F403/F433 12 位多通道,支持 MPU 存储保护功能,应用于工业控制,智能家居等产品中
ACM32F403/F433 芯片的内核基于 ARMv8-M 架构,支持 Cortex-M33 和 Cortex-M4F 指令集。芯片内核 支持一整套DSP指令用于数字信号处理,支持单精度FPU处理浮点数据,同时还支持Memory Protection Unit (MPU)用于提升应用的…...
7. 从零用Rust编写正反向代理, HTTP及TCP内网穿透原理及运行篇
wmproxy wmproxy是由Rust编写,已实现http/https代理,socks5代理, 反向代理,静态文件服务器,内网穿透,配置热更新等, 后续将实现websocket代理等,同时会将实现过程分享出来ÿ…...
UE4.27-UE5.1设置打包Android环境
打包Android配置文件 1. 配置打包Android的SDK需求文件位于下面文件中: 2. 指定了对应的SDK环境变量名字以及NDK需求等: UE4.27-UE5.1--脚本自动配置 安装前提 1. 务必关闭虚幻编辑器和Epic Games Launcher,以确保NDK组件的安装或引擎环境…...
MySQL授权密码
mysql> crate databases school charcter set utf8; Query OK, 1 row affected, 1 warning (0.00 sec) 2.在school数据库中创建Student和Score表 mysql> use school Database changed mysql> create table student-> -> (id int(10) primary key auto_incremen…...
0X05
打开题目 点击完登录和注册都没有什么反应,所以先扫一下看看 在出现admin.php后就截止了,访问看看,进入后台。。 尝试一下弱口令 admin/12345 或者是demo/demo 设计中-自定义->右上角导出主题 找到一个导出的点,下载了一个1.zip压缩包…...
Doris优化总结
1 查看QueryProfile 利用查询执行的统计结果,可以更好的帮助我们了解Doris的执行情况,并有针对性的进行相应Debug与调优工作。 FE将查询计划拆分成为Fragment下发到BE进行任务执行。BE在执行Fragment时记录了运行状态时的统计值,并将Fragment执行的统计信息输出到日志之中。…...
案例059:基于微信小程序的在线投稿系统
文末获取源码 开发语言:Java 框架:SSM JDK版本:JDK1.8 数据库:mysql 5.7 开发软件:eclipse/myeclipse/idea Maven包:Maven3.5.4 小程序框架:uniapp 小程序开发软件:HBuilder X 小程序…...
利用STM32内置Bootloader实现USB DFU固件升级
本文将介绍如何利用STM32内置的Bootloader来实现USB DFU(Device Firmware Upgrade)固件升级功能。首先,我们会介绍USB DFU的原理和工作流程。然后,我们将详细讲解如何配置STM32芯片以支持USB DFU,并提供相应的代码示例…...
Centos7如何安装MySQL
目录 一、卸载mysql 二、安装mysql 注:本文主要是看了这位大佬安装MySQL,才想着写一篇记录一下。 一、卸载mysql 安装mysql之前一定要将之前安装的mysql相关文件删除干净,防止出现错误。 (1)关闭mysql 开启了mysql就…...
VR远程带看,助力线下门店线上化转型“自救”
VR远程带看,因自身高效的沉浸式在线沟通功能,逐渐走进了大众的视野。身临其境的线上漫游体验以及实时同屏互联的新型交互模式,提升了商家同用户之间的沟通效率,进一步实现了远程线上一对一、一对多的同屏带看,用户足不…...
算法通关村第十七关-白银挑战贪心算法高频题目
大家好我是苏麟 , 今天说说贪心算法的高频题目 . 大纲 区间问题判断区间是否重叠合并区间插入区间 区间问题 判断区间是否重叠 描述 : 给定一个会议时间安排的数组 intervals ,每个会议时间都会包括开始和结束的时间intervalsl[i] [start, end] ,请你…...
网易技术岗校招通关秘籍:从需求画像到Offer收割(实战篇)
1. 网易技术岗校招需求画像解析 第一次参加大厂校招的同学,往往会被各种岗位JD绕晕。去年我带过一个浙大的学弟,他同时投了网易的Java和后端开发岗,结果发现笔试题目完全不同。后来才知道,网易不同业务线对"后端开发"的…...
英雄联盟Akari助手:5大核心功能解决游戏中的常见痛点
英雄联盟Akari助手:5大核心功能解决游戏中的常见痛点 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 还在为英雄联盟游戏中的繁琐操…...
sqlite-utils与Datasette集成:构建数据驱动的Web应用终极指南
sqlite-utils与Datasette集成:构建数据驱动的Web应用终极指南 【免费下载链接】sqlite-utils Python CLI utility and library for manipulating SQLite databases 项目地址: https://gitcode.com/gh_mirrors/sq/sqlite-utils sqlite-utils是一款强大的Pytho…...
目标检测 - 从FPN到PAN:双向路径聚合如何提升特征融合效率
1. 目标检测中的特征金字塔:从FPN到PAN的进化之路 在目标检测任务中,处理多尺度目标一直是个棘手的问题。想象一下,你要在一张图片中同时识别出近处的行人、远处的车辆和更远处的交通标志,这些目标的尺寸差异可能达到数十倍。传统…...
STM32F4当USB主机,驱动CH340串口模块的保姆级调试笔记(附源码)
STM32F4作为USB主机驱动CH340模块的深度实践指南 在嵌入式开发中,USB主机功能扩展串口资源是常见需求。当标准CDC类设备无法满足特殊场景时,驱动像CH340这样的厂商自定义设备就成了一项必备技能。本文将带您深入探索STM32F4系列微控制器作为USB主机与CH3…...
终极指南:5分钟快速解密网易云音乐NCM文件,实现音乐自由
终极指南:5分钟快速解密网易云音乐NCM文件,实现音乐自由 【免费下载链接】ncmdump ncmdump - 网易云音乐NCM转换 项目地址: https://gitcode.com/gh_mirrors/ncmdu/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗&#…...
现代化WPF可视化设计引擎:从XAML代码到拖拽式开发的效率革命
现代化WPF可视化设计引擎:从XAML代码到拖拽式开发的效率革命 【免费下载链接】WpfDesigner The WPF Designer from SharpDevelop 项目地址: https://gitcode.com/gh_mirrors/wp/WpfDesigner 在WPF应用程序开发中,手动编写XAML代码进行界面布局是每…...
终极分屏神器Nucleus Co-Op:一台电脑实现4人同时开黑完整指南
终极分屏神器Nucleus Co-Op:一台电脑实现4人同时开黑完整指南 【免费下载链接】nucleuscoop Starts multiple instances of a game for split-screen multiplayer gaming! 项目地址: https://gitcode.com/gh_mirrors/nu/nucleuscoop 你是否曾因朋友聚会时电脑…...
【大模型服务治理实战指南】:奇点智能大会首发的7大避坑法则与3套可落地架构模板
更多请点击: https://intelliparadigm.com 第一章:大模型服务治理:奇点智能大会 在2024年奇点智能大会上,大模型服务治理成为核心议题。随着LLM推理服务规模化部署,企业面临模型版本混乱、流量调度失衡、资源隔离缺失…...
OpenClaw Mattermost插件:为团队协作平台注入AI智能的轻量集成方案
1. 项目概述:为团队协作平台注入AI灵魂如果你所在的技术团队正在使用 Mattermost 这类自托管、注重数据隐私的团队协作工具,同时又希望引入一个能处理工单、回答疑问、甚至自动执行任务的智能助手,那么你很可能已经厌倦了那些需要复杂 API 调…...
