Go 语言 API 限流实战:保障系统稳定性的护盾

文章精选推荐

1 JetBrains Ai assistant 编程工具让你的工作效率翻倍
2 Extra Icons:JetBrains IDE的图标增强神器
3 IDEA插件推荐-SequenceDiagram,自动生成时序图
4 BashSupport Pro 这个ides插件主要是用来干嘛的 ?
5 IDEA必装的插件:Spring Boot Helper的使用与功能特点
6 Ai assistant ,又是一个写代码神器

文章正文

为什么要进行 API 限流?

API 限流是控制和管理应用程序访问量的重要手段,旨在防止恶意滥用、保护后端服务的稳定性和可用性,并确保系统能够有效处理请求。API 限流不仅能提高系统的性能,还能优化用户体验。下面是为什么要进行 API 限流的一些原因:

  1. 防止服务过载
  • 当 API 接口的访问量过大时,后端服务可能无法处理所有请求,导致服务崩溃或响应迟缓。
  • 限流能够保证后端服务不会因为高并发请求而被击垮,从而提升系统的可靠性。
  1. 保护资源
  • API 服务通常需要访问数据库、缓存、第三方 API 等资源。通过限流,可以控制这些资源的访问频率,防止它们被过度消耗。
  • 防止用户发送大量无效请求或重复请求,避免不必要的资源浪费。
  1. 提高用户体验
  • API 限流能够确保每个用户公平地获得访问权限,避免某些用户发送过多请求从而影响其他用户的体验。
  1. 防止恶意攻击
  • 限流是抵御 DDoS(分布式拒绝服务)攻击的一种手段,可以有效减缓大量请求的冲击。
  • 防止 暴力破解(如密码暴力破解、账户滥用等)攻击,限制某些频繁请求的行为。
  1. 成本控制
  • 许多服务(如云服务、第三方 API)基于请求量计费。通过限流,能够在一定程度上减少不必要的成本。

常用的 API 限流算法

以下是一些常见的 API 限流算法,每种算法有不同的优缺点和适用场景:

1. 令牌桶算法(Token Bucket)
  • 原理:令牌桶算法维护一个桶,每个请求需要获取一个令牌。令牌会以固定速率放入桶中,桶有最大容量。如果桶满了,新的令牌将会丢弃。当请求到达时,若桶中有令牌,说明可以处理该请求,令牌被取走;若桶中没有令牌,则拒绝请求。

  • 特点

    • 能够处理突发流量,因为桶中可以积累一定数量的令牌。
    • 适用于允许请求量有一定波动的场景。
  • 适用场景:适用于限流场景中需要允许短时间内的流量突增,例如某些高并发的 API 服务。

2. 漏桶算法(Leaky Bucket)
  • 原理:漏桶算法也使用一个桶来存储请求,当请求到达时,它们会依次进入桶中。如果桶没有满,水会以恒定的速率流出。如果桶已满,则新请求会被丢弃。

  • 特点

    • 平滑的流量控制,能确保请求按照固定速率流出。
    • 不允许短时间内出现突发流量,所有的请求流量必须按固定速率流出。
  • 适用场景:适用于需要平滑流量、避免短时间内的突发请求影响系统的场景。

3. 固定窗口计数算法(Fixed Window Counter)
  • 原理:在固定的时间窗口内(如每分钟或每小时),允许一定数量的请求通过。每当时间窗口结束时,计数器会重置。超出最大请求数的请求将被拒绝。

  • 特点

    • 简单易实现,但容易受到时间窗口边界问题的影响(即在窗口切换时,可能会允许过多的请求通过)。
  • 适用场景:适用于流量相对平稳的场景,通常在请求量较低的应用中使用。

4. 滑动窗口计数算法(Sliding Window Counter)
  • 原理:与固定窗口计数算法类似,但是它不是固定的时间窗口,而是以滑动的方式进行计数。每次请求都会在时间轴上记录,滑动窗口会随着时间的推移进行更新。

  • 特点

    • 能够更加平滑地控制请求速率,避免固定窗口切换时的突发流量。
  • 适用场景:适用于需要精确限流的场景,减少边界效应。

5. 基于 Redis 的限流
  • 原理:使用 Redis 的键值存储特性,可以结合 Redis 的过期时间来实现限流。例如,在 Redis 中记录每个用户或 IP 的请求次数,并设置过期时间,来实现请求的限制。

  • 特点

    • 分布式限流,非常适合分布式系统。
    • 高效、易扩展。
  • 适用场景:适用于分布式系统,尤其是微服务架构中的 API 限流。

使用 Go 实现 API 限流

以下是如何在 Go 中实现 API 限流的几种常见方式:

1. 基于 Token Bucket 算法实现限流
package mainimport ("fmt""time"
)type TokenBucket struct {capacity int           // 桶的最大容量tokens   int           // 当前桶中令牌数量rate     time.Duration // 令牌生成速率lastTime time.Time     // 上次令牌生成时间
}func NewTokenBucket(capacity int, rate time.Duration) *TokenBucket {return &TokenBucket{capacity: capacity,tokens:   capacity,rate:     rate,lastTime: time.Now(),}
}func (tb *TokenBucket) Allow() bool {// 计算令牌的生成数量now := time.Now()elapsed := now.Sub(tb.lastTime)tokensToAdd := int(elapsed / tb.rate)tb.lastTime = now// 如果有令牌生成,更新桶中的令牌数量if tokensToAdd > 0 {tb.tokens = min(tb.capacity, tb.tokens+tokensToAdd)}// 如果有令牌,则消费一个令牌并返回 trueif tb.tokens > 0 {tb.tokens--return true}// 否则返回 false,拒绝请求return false
}func min(a, b int) int {if a < b {return a}return b
}func main() {tb := NewTokenBucket(5, time.Second)// 模拟请求for i := 0; i < 10; i++ {if tb.Allow() {fmt.Println("Request", i, "allowed")} else {fmt.Println("Request", i, "denied")}time.Sleep(200 * time.Millisecond)}
}
2. 基于 Redis 实现限流(使用 Go Redis 客户端)

使用 Redis 进行限流实现时,常用的是 SETNX(设置一个键值对,如果键不存在则设置,防止重复计数)和 EXPIRE(设置过期时间)来控制访问频率。

package mainimport ("fmt""log""time""github.com/go-redis/redis/v8""golang.org/x/net/context"
)var rdb *redis.Client
var ctx = context.Background()func init() {// 初始化 Redis 客户端rdb = redis.NewClient(&redis.Options{Addr: "localhost:6379", // Redis 地址})
}func limitRequest(userID string) bool {// 使用 Redis 来存储访问记录key := fmt.Sprintf("rate_limit:%s", userID)// 设置每个用户的最大请求次数限制maxRequests := 5// 设置过期时间为 60 秒expiration := 60 * time.Second// 获取当前用户的请求次数count, err := rdb.Get(ctx, key).Int()if err != nil && err != redis.Nil {log.Fatalf("Error retrieving count from Redis: %v", err)}// 如果请求次数超过限制,拒绝请求if count >= maxRequests {return false}// 增加请求次数err = rdb.Incr(ctx, key).Err()if err != nil {log.Fatalf("Error incrementing count: %v", err)}// 设置过期时间,避免无限制的请求rdb.Expire(ctx, key, expiration)return true
}func main() {userID := "user123"for i := 0; i < 10; i++ {if limitRequest(userID) {fmt.Println("Request allowed")} else {fmt.Println("Request denied due to rate limit")}time.Sleep(5 * time.Second)}
}

3. 总结

  • 限流的必要性:API 限流不仅能提高系统的可靠性,防止服务过载,还能优化用户体验和控制

资源消耗。

  • 常用限流算法:包括令牌桶、漏桶、固定窗口计数、滑动窗口计数等,每种算法适用于不同的场景。
  • Go 中实现限流:可以通过直接编写限流算法或使用 Redis 等第三方工具来实现 API 限流。使用 Redis 进行限流特别适合分布式系统。

在实际开发中,可以根据需求选择适合的限流算法和实现方式,从而确保 API 服务的稳定性和安全性。

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

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

相关文章

word文档中的文档网格——解决相同行间距当显示出不同行间距的情况

1 问题 被一个行间距调疯了&#xff0c;就是样式改了没用&#xff0c;格式刷刷了没用。就是肉眼可以看出行间距完全不一样。 2 解决方法 1&#xff09;修改论文正文(即出现问题文本的样式)样式&#xff1a;样式>修改>格式>段落>缩进和间距>取消"如果定义了…

CDP集群安全指南-静态数据加密

[一]静态数据加密的架构 CDP 支持两种加密组件&#xff0c;这些组件可以组合成独特的解决方案。在选择密钥管理系统&#xff08;KMS&#xff09;时&#xff0c;您需要决定哪些组件能够满足企业的密钥管理和加密需求。 CDP 加密组件 以下是 Cloudera 用于静态数据加密的组件描…

ACM算法模板

ACM算法模板 起手式基础算法前缀和与差分二分查找三分查找求极值分治法&#xff1a;归并排序 动态规划基本线性 d p dp dp最长上升子序列I O ( n 2 ) O(n ^ 2) O(n2)最长上升子序列II O ( n l o g n ) O(nlogn) O(nlogn) 贪心二分最长公共子序列 背包背包求组合种类背包求排列…

AcWing练习题:差

读取四个整数 A,B,C,D&#xff0c;并计算 (AB−CD)的值。 输入格式 输入共四行&#xff0c;第一行包含整数 A&#xff0c;第二行包含整数 B&#xff0c;第三行包含整数 C&#xff0c;第四行包含整数 D。 输出格式 输出格式为 DIFERENCA X&#xff0c;其中 X 为 (AB−CD) 的…

前端路由 Hash 和 History 模式原理对比区别

前端路由 Hash 和 History 模式原理对比区别 1. 基本概念 1.1 什么是前端路由 前端路由是指在单页应用&#xff08;SPA&#xff09;中&#xff0c;通过 JavaScript 来实现页面的切换和状态管理&#xff0c;而无需向服务器请求新的页面。主要有两种实现方式&#xff1a;Hash …

头歌实训数据结构与算法 - 字符串匹配(第2关:实现KMP字符串匹配)

任务描述 本关任务&#xff1a;编写一个程序&#xff0c;利用kmp算法求子串在主串中不重叠出现的次数。 实验目的&#xff1a;深入掌握KMP算法的应用。实验内容&#xff1a;编写一个程序&#xff0c;利用KMP算法求子串t在主串s中出现的次数&#xff0c;例如&#xff1a;s“aa…

enzymejest TDD与BDD开发实战

一、前端自动化测试需要测什么 1. 函数的执行逻辑&#xff0c;对于给定的输入&#xff0c;输出是否符合预期。 2. 用户行为的响应逻辑。 - 对于单元测试而言&#xff0c;测试粒度较细&#xff0c;需要测试内部状态的变更与相应函数是否成功被调用。 - 对于集成测试而言&a…

UE5通过蓝图节点控制材质参数

通过蓝图节点控制材质的参数 蓝图节点 在材质上设置标量值 和 在材质上设置向量参数值 Set Scalar Parameter Value on Materials Set Vector Parameter Value on Materials 这两个蓝图节点都可以在蓝图中&#xff0c;控制材质的参数值和向量值

MySQL秘籍之索引与查询优化实战指南

MySQL秘籍之索引与查询优化实战指南 目录 MySQL秘籍之索引与查询优化实战指南相关阅读索引相关EXPLAIN 版本 1. 初级篇1.1 【练体术】基础1.1.1 库操作1.1.1 表操作创建一个表增加表字段 1.1.2 增删改插入一条数据删除一条数据更新一条数据库 1.1.3 查询查询所有数据条件查询&a…

沁恒CH32V208GBU6蓝牙MTU二:减小连接间隔提升速度;修改GAP里面的连接参数提高兼容性

从事嵌入式单片机的工作算是符合我个人兴趣爱好的,当面对一个新的芯片我即想把芯片尽快搞懂完成项目赚钱,也想着能够把自己遇到的坑和注意事项记录下来,即方便自己后面查阅也可以分享给大家,这是一种冲动,但是这个或许并不是原厂希望的,尽管这样有可能会牺牲一些时间也有哪天原…

探索 Vue.js 的动态样式与交互:一个有趣的样式调整应用

修改日期备注2025.1.3初版 一、前言 今天和大家分享在 Vue.js 学习过程中开发的超酷的小应用。这个应用可以让我们通过一些简单的交互元素&#xff0c;如复选框、下拉菜单和输入框&#xff0c;来动态地改变页面上元素的样式哦 让我们一起深入了解一下这个项目的实现过程&…

Python应用指南:高德交通态势数据

在现代城市的脉络中&#xff0c;交通流量如同流动的血液&#xff0c;交通流量的动态变化对出行规划和城市管理提出了更高的要求。为了应对这一挑战&#xff0c;高德地图推出了交通态势查询API&#xff0c;旨在为开发者提供一个强大的工具&#xff0c;用于实时获取指定区域或道路…

整合版canal ha搭建--基于1.1.4版本

开启MySql Binlog&#xff08;1&#xff09;修改MySql配置文件&#xff08;2&#xff09;重启MySql服务,查看配置是否生效&#xff08;3&#xff09;配置起效果后&#xff0c;创建canal用户&#xff0c;并赋予权限安装canal-admin&#xff08;1&#xff09;解压 canal.admin-1…

物联网控制期末复习

第3章 物联网控制系统的过程通道设计 3.1 模拟量输出通道 3.1.1单模拟量输出通道的构成 计算机控制系统的模拟量输出通道将计算机产生的数字控制信号转换为模拟信号&#xff08;电压或电流&#xff09;作用于执行机构&#xff0c;以实现对被控对象的控制。 多D/A结构&#…

python生成、操作svg图片

生成svg图片 通过python生成svg图片的方法有许多&#xff0c;比如OpenCV的源码中有svgfig.py这个脚本可以用于生成svg图片(OpenCV的棋盘格图片可以通过这个方法生成)&#xff0c;也可以使用svg.py的库&#xff0c;安装方法如下 pip install svg.py 下面是通过这个库生成一个简…

2024年大型语言模型(LLMs)的发展回顾

2024年对大型语言模型&#xff08;LLMs&#xff09;来说是充满变革的一年。以下是对过去一年中LLMs领域的关键进展和主题的总结。 GPT-4的壁垒被打破 去年&#xff0c;我们还在讨论如何构建超越GPT-4的模型。如今&#xff0c;已有18个组织拥有在Chatbot Arena排行榜上超越原…

Servlet解析

概念 Servlet是运行在服务端的小程序&#xff08;Server Applet)&#xff0c;可以处理客户端的请求并返回响应&#xff0c;主要用于构建动态的Web应用&#xff0c;是SpringMVC的基础。 生命周期 加载和初始化 默认在客户端第一次请求加载到容器中&#xff0c;通过反射实例化…

图片验证码如何显示在 Apifox 的响应控制台中

当接口返回的响应数据结构非常复杂&#xff0c;充斥着嵌套的对象和数组&#xff0c;其中还可能包含着图片的 URL 时&#xff0c;如果要查找特定信息&#xff0c;你需要不断上下滚动 JSON 响应&#xff0c;试图找到所需的字段。这不仅让人恼火&#xff0c;还浪费了宝贵的时间。 …

设计模式 创建型 单例模式(Singleton Pattern)与 常见技术框架应用 解析

单例模式&#xff08;Singleton Pattern&#xff09;是一种创建型设计模式&#xff0c;旨在确保某个类在应用程序的生命周期内只有一个实例&#xff0c;并提供一个全局访问点来获取该实例。这种设计模式在需要控制资源访问、避免频繁创建和销毁对象的场景中尤为有用。 一、核心…

《Xsens动捕与人形机器人训练》讲座将于1月9日下午2:30在线上召开

《Xsens动捕与人形机器人训练》讲座将于1月9日下午2:30在线上召开&#xff0c;本次讲座中来自Xsens的人形机器人与动捕技术专家Jeffrey Muller与Dennis Kloppenburg不仅将就Xsens动作捕捉系统与人形机器人行为训练中的实际应用进行详细讲解&#xff0c;同时还会对目前大家所关注…