常见的限流算法- python版本

shigen坚持更新文章的博客写手,擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长,分享认知,留住感动。
个人IP:shigen

在系统的稳定性设计中,需要考虑到的就是限流,避免高并发环境下一下子把服务整垮了。shigen在翻看以前的笔记的时候,看到了python版本的限流算法,在此做一个分享。

前提

本地的redis服务已经启动,mac用户两行命令即可:

brew install redis && brew services start redis

完了之后,在代码里写上获得redis连接的代码:

def get_redis_con():pool = redis.ConnectionPool(max_connections=4, decode_responses=True)return redis.Redis(connection_pool=pool)

其他配置参照官方文档。

固定窗口

类似于把时间切分了,每个时间段只允许固定次的请求。

固定窗口

最直白的话语就是:我的接口1s只允许100次请求,多了我就抛异常。

def fixed_window(user, action, time_zone=60, max_times=30):key = f'{action}'count = get_redis_con().get(key)if not count:count = 1get_redis_con().setex(key, time_zone, count)if int(count) < max_times:get_redis_con().incr(key)return Truereturn False

代码中加上了user,其实就是避免单个用户的接口防刷。在之前的文章<如何优雅的实现接口防刷>中,其实就是用的这种方法。

对应的话,其实也是有一些问题的。

最主要的一个缺点就是:流量不是平滑的,可能存在多个流量峰值导致服务间歇性的不可用。最直观的感受是在窗口切换的时候,流量堆积导致的问题。

滑动窗口

描述的原理是:

  1. 将时间划分为细粒度的区间,每个区间维持一个计数器,每进入一个请求则将计数器加一;
  2. 多个区间组成一个时间窗口,每流逝一个区间时间后,则抛弃最老的一个区间,纳入新区间;
  3. 若当前窗口的区间计数器总和超过设定的限制数量,则本窗口内的后续请求都被丢弃。

可能还是有一些抽象,我们借用代码来讲解:

def silde_window(user, action, time_zone=60, max_times=30):key = f'{action}'now_ts = time.time() * 1000# ms级时间戳,保证唯一value = now_ts# 时间窗口的左边界old_ts = now_ts - time_zone * 1000# 记录 {成员元素:分数值}mapping = {value: now_ts,}get_redis_con().zadd(key, mapping)# 删除时间窗口之前的数据get_redis_con().zremrangebyscore(key, -1, old_ts)# 获得窗口内的行为数量count = get_redis_con().zcard(key)get_redis_con().expire(key, time_zone + 1)if not count or int(count) < max_times:return Truereturn False

用到的数据结构是zset。这里的时间戳就是对应值的score

这种方式可以应对流量的激增,但是流量的曲线还是不够平滑。

漏桶算法

就类似于一个桶,请求先去填满桶,填满之后,其它的请求直接拒绝;同时,桶以一定的速率漏出,放行请求。

这种算法的速率是不支持动态调整的,对于系统资源的充分利用上还是存在问题的。

令牌桶算法

漏桶算法的主角是桶,令牌桶的主角是令牌。

def pass_token_bucket(user, action, time_zone=60, max_times=30):key = f'{user}:{action}'# 令牌生成速度rate = max_times / time_zonecapacity = max_timestoken_count = get_redis_con().hget(key, 'tokens')last_time = get_redis_con().hget(key, 'last_time')now = time.time()token_count = int(token_count) if token_count else capacitylast_time = last_time if last_time else now# 经过一段时间之后生成的令牌数量new_token_count = int((now - last_time) * rate)if new_token_count > 1:token_count += new_token_countif token_count > capacity:token_count = capacitylast_time = time.time()get_redis_con().hset(key, 'last_time', last_time)if token_count >= 1:token_count -= 1get_redis_con().hset(key, 'tokens', token_count)return Truereturn False

对于漏桶和令牌桶,算法的实现其实都大差不差。shigen在学习这个的时候,还有一点整混淆了。

最后,说一下如何验证,使用到了python的多线程。

executor = ThreadPoolExecutor(max_workers=4)
APIS = ['/api/a', '/get/user/1', '/get/user/2', '/get/user/3']def task() -> bool:user = random.randint(1000, 1010)status = pass_token_bucket(user, random.choice(APIS))if not status:raise SystemError('{}被限制'.format(user))return statusif __name__ == '__main__':jobs = [executor.submit(task) for _ in range(1000)]for job in jobs:print(job.result())

与shigen一起,每天不一样!

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

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

相关文章

Elastic Stack--08--SpringData框架

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 SpringData[官网&#xff1a; https://spring.io/projects/spring-data](https://spring.io/projects/spring-data) Spring Data Elasticsearch 介绍 1.SpringData-…

AI+X 高校行:首场浙大站爆满!

Datawhale线下 线下活动&#xff1a;AIX 高校行活动 AIX&#xff1a;希望将人工智能&#xff08;AI&#xff09;与各个学科和行业&#xff08;X&#xff09;结合&#xff0c; 激发无限潜力和创造力&#xff08;X&#xff09;&#xff0c;让年轻人拥有更多可能性&#xff08;X&…

Discord OAuth2授权以及机器人监听群事件

下面文章讲解获取OAuth2授权整个流程&#xff0c;创建机器人&#xff0c;使用机器人监听工会&#xff08;工会就是创建的服务器&#xff09;成员变化等等&#xff0c;对接国外的都是需要VPN的哦&#xff0c;对接的时候记得提前准备。 创建应用 点击 此页面添加应用,&#xff…

Midjourney绘图欣赏系列(七)

Midjourney介绍 Midjourney 是生成式人工智能的一个很好的例子&#xff0c;它根据文本提示创建图像。它与 Dall-E 和 Stable Diffusion 一起成为最流行的 AI 艺术创作工具之一。与竞争对手不同&#xff0c;Midjourney 是自筹资金且闭源的&#xff0c;因此确切了解其幕后内容尚不…

【wps】wps与office办公函数储备使用(结合了使用案例 持续更新)

【wps】wps与office办公函数储备使用(结合了使用案例 持续更新) 1、TODAY函数 返回当前电脑系统显示的日期 TODAY函数&#xff1a;表示返回当前电脑系统显示的日期。 公式用法&#xff1a;TODAY() 2、NOW函数 返回当前电脑系统显示的日期和时间 NOW函数&#xff1a;表示返…

蚂蚁链摩斯荣获“艾瑞保险业数字化卓越服务商“奖

近日&#xff0c;艾瑞咨询发布《2023年中国保险业数字化转型研究报告》&#xff0c;摩斯隐私计算解决方案被报告入选&#xff0c;并获得“保险业数字化卓越服务商”奖。 蚂蚁摩斯是隐私计算行业的领先布局者&#xff1a;早在2017年&#xff0c;蚂蚁集团启动了隐私计算项目&…

Linux操作系统-07-Linux安装应用

一、使用rpm安装应用&#xff08;不推荐&#xff09; 先下载到本地&#xff0c;以.rpm文件名结尾&#xff0c;下载完成后&#xff0c;再安装 rpm -qa | grep mysql #查询当前系统是否有下载过mysql包 先上传mysql的rpm安装包到linux的opt目录 安装 rpm -ivh …

Linux 多进程开发(上)

第二章 Linux 多进程开发 2.1 进程概述2.2 进程状态转换2.3 进程创建2.4 exec 函数族2.5 进程控制 网络编程系列文章&#xff1a; 第1章 Linux系统编程入门&#xff08;上&#xff09; 第1章 Linux系统编程入门&#xff08;下&#xff09; 第2章 Linux多进程开发&#xff08;…

Opencv 插值方法 总结

一、概括 面试的时候问到了一个图&#xff0c;就是如何将一个算子放缩&#xff1f;&#xff1f;我第一反应是resize&#xff08;&#xff09;,但是后来我转念一想&#xff0c;人家问的是插值方式&#xff0c;今天来总结一下 最邻近插值法原理分析及c实现_最临近插值法-CSDN博…

Python与C++的对比——跟老吕学Python编程

Python与C的对比——跟老吕学Python编程 Python与C的对比1.C编译型 vs Python解释型2.执行效率3.开发效率4.跨平台5.可移植性6.内存管理机制7.易学性8.静态类型 vs 动态类型9.面向对象编程概念10.垃圾回收11.应用领域 Python与C的对比表 Python与C的对比 Python和C都是最受欢迎…

数据结构小记【Python/C++版】——散列表篇

一&#xff0c;基础概念 散列表&#xff0c;英文名是hash table&#xff0c;又叫哈希表。 散列表通常使用顺序表来存储集合元素&#xff0c;集合元素以一种很分散的分布方式存储在顺序表中。 散列表是一个键值对(key-item)的组合&#xff0c;由键(key)和元素值(item)组成。键…

解密阿里巴巴面试题:如何设计一个微博?

亲爱的小米科技粉丝们,大家好呀!今天小米带来了一则热门话题——阿里巴巴面试题:如何设计一个微博?别着急,跟着小米一起来揭秘吧! 实现哪些功能? 在设计微博系统时,需要考虑实现哪些功能才能满足用户的需求。除了基本的发布推文、时间线、新闻推送、关注/不允许用户以…

【JavaScript 漫游】【034】AJAX

文章简介 本篇文章为【JavaScript 漫游】专栏的第 034 篇文章&#xff0c;对浏览器模型的 XMLHttpRequest 对象&#xff08;AJAX&#xff09;的知识点进行了总结。 XMLHttpRequest 对象概述 浏览器与服务器之间&#xff0c;采用 HTTP 协议通信。用户在浏览器地址栏键入一个网…

Java项目源码基于springboot的家政服务平台的设计与实现

大家好我是程序员阿存&#xff0c;在java圈的辛苦码农。辛辛苦苦板砖&#xff0c;今天要和大家聊的是一款Java项目源码基于springboot的家政服务平台的设计与实现&#xff0c;项目源码以及部署相关请联系存哥&#xff0c;文末附上联系信息 。 项目源码&#xff1a;Java基于spr…

虚拟机镜像iso下载

MSDN, 我告诉你 - 做一个安静的工具站 (itellyou.cn)

CANalyzer使用_00 概述

计划写一个专题&#xff0c;该专题主要介绍CANalyzer的使用&#xff0c;每次文档计划写一个点&#xff0c;自己不累&#xff0c;别人看着也不累&#xff0c;并且方便拓展。本文作为专题的开篇主要介绍下CANalyzer软件的背景&#xff0c;软件界面等信息。 1 软件介绍 CANalyze…

FastAPI 学习笔记

FastAPI 学习笔记 0. 引言1. 快速开始2. 升级示例代码 0. 引言 在 Python 这个充满活力的生态系统中&#xff0c;FastAPI 应运而生&#xff0c;它是一个现代的、快速的 Web 框架&#xff0c;专注于构建 RESTful API。 无论你是一名有经验的 Python 开发人员&#xff0c;还是一…

HTTP/2、HTTP/3对HTTP/1.1的性能改进和优化

HTTP/1.1 相比 HTTP/1.0 提高了什么性能&#xff1f; 性能上的改进&#xff1a; 使用长连接的方式改善了 HTTP/1.0 短连接造成的性能开销。 支持管道&#xff08;pipeline&#xff09;网络传输&#xff0c;只要第一个请求发出去了&#xff0c;不必等其回来&#xff0c;就可以…

Purple Pi OH鸿蒙开发板7天入门OpenHarmony开源鸿蒙教程【五】

在完成了Purple Pi OH大部分的接口测试之后&#xff0c;紧接着就是一个充满挑战的任务——利用SDK来编译生成我们自己的镜像文件。通过这一过程&#xff0c;不仅能够让你获得一个可在真实硬件上运行的系统镜像&#xff0c;更重要的是&#xff0c;它让你对OpenHarmony系统的构建…

Qt - 信号和槽

目录 一、信号 二、槽 三、信号和槽的使用 (一) 连接信号和槽 (二) 自定义槽 (三) 通过 Qt Creator生成信号槽代码 (四) 自定义信号 四、带参数的信号和槽 五、信号与槽的断开 六、Qt4版本信号与槽的连接 (一) Qt4版本信号与槽连接的优缺点 一、信号 在 Qt 中&…