go rate 原生标准限速库的使用

2025-05-25 15:50
文章标签 go 使用 标准 原生 rate 限速

本文主要是介绍go rate 原生标准限速库的使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《gorate原生标准限速库的使用》本文主要介绍了Go标准库golang.org/x/time/rate实现限流,采用令牌桶算法控制请求速率,提供Allow/Reserve/Wait方法,具有一定...

在我们实际生产开发过程中,不免存在一些高并发的场景,此时我们就需要对请求进行限流,避免过高的QPS,影响我们服务器,导致服务出现波动或不可用。

  • 对于go开发人员而言,golanghttp://www.chinasem.cn标准库就已经为我们提供了现成的类库golang.org/x/time/rate,我们只需直接调用即可。下面将为大家介绍该类库的详细用法。

文中代码地址,欢迎大家⭐️:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-rate

介绍

限流(Rate Limiting)是控制对某些资源访问频率的一种技术手段。在高并发的服务中,限流机制可以有效防止资源过载、服务崩溃,保障系统的稳定性和可用性。Golang 官方标准库 golang.org/x/time/rate 提供了一个高效且易用的限流器(Rate Limiter),可以帮助开发者方便地实现限流功能。

原理:golang官方的类库采用了令牌桶算法进行限流。

  • 令牌桶算法(Token Bucket Algorithm):是一种常用的限流算法,它通过在固定时间间隔内向“桶&rdqwww.chinasem.cnuo;中添加“令牌”,请求在处理前需要从桶中获取令牌。如果桶中有足够的令牌,请求被处理;否则,请求被拒绝或等待。
  • 速率(Rate):速率定义了令牌添加的速度,即每秒向桶中添加多少令牌。
  • 容量(Burst):容量定义了桶的大小,即桶中最多可以存储多少令牌。它决定了在一段时间内允许的最大突发请求数。

安装

go get golang.org/x/time/rate

API介绍

rate.NewLimiter:创建限流器

创建限流器后,可以通过 Allow、Reserve、Wait 等方法请求许可

package main

import (
    "fmt"
    "golang.org/x/time/rate"
    "time"
)

func main() {
    // 每秒生成3个令牌,桶的容量为10个令牌
    // 相当于每秒最多能处理三个请求,顺时并发最多能处理10个请求
    limiter := rate.NewLimiter(3, 10)

    fmt.Println("Limiter created with rate 3 tokens per second and burst size of 10")
}

limiter.Allow():请求是否被允许/限流

Allow 方法立即返回一个布尔值,指示请求是否被允许

if limiter.Allow() {
    fmt.Println("Request allowed")
} else {
python    fmt.Println("Request denied")
}

limiter.Reserve():返回值包含了许可时间和是否可用的信息

Reserve 方法返回一个 Reservation 对象,包含了许可时间和是否可用的信息

reservation := limiter.Reserve()
if reservation.OK() {
    fmt.Println("Request reserved, delay:", reservation.Delay())
} else {
    fmt.Println("Request cannot be reserved")
}

limiter.Wait(ctx):阻塞当前协程,直到允许请求或上下文取消

Wait 方法阻塞当前协程,直到允许请求或上下文取消

ctx := context.Background()
if err := limiter.Wait(ctx); err == nil {
    fmt.Println("Request allowed after wait")
} else {
    fmt.Println("Request denied:", err)
}

实战使用

并发处理任务

一段时间内,限制服务器处理任务数

// Demo_CurrentHandleWorks 模拟并发处理任务
func Demo_CurrentHandleWorks() {
	var wg sync.WaitGroup
	numWorkers := 5 // 模拟5个并发请求
	// 构造限流器:每10s向桶中新增一个令牌,桶里最多能存放2个令牌 => 每10s能处理一个任务,一定时间内最多能处理2个任务(令牌有剩余)
	var l = rate.NewLimiter(rate.Every(time.Second*10), 2)
	for i := 1; i <= numWorkers; i++ {
		wg.Add(1)
		go wowww.chinasem.cnrker(i, &wg, l)
	}

	wg.Wait()
}

func worker(id int, wg *sync.WaitGroup, limiter *rate.Limiter) {
	defer wg.Done()
	if limiter.Allow() {
		fmt.Printf("Worker %d processed at %s\n", id, time.Now().Format("15:04:05.000"))
	} else {
		fmt.Printf("Worker %d rejected at %s\n", id, time.Now().Format("15:04:05.000"))
	}
}

HTTP服务请求限流

当我们通过jmeter/脚本/连续刷新页面并发请求测试时,发现在1s内,服务器最多只能处理2个请求,其余请求都不会被处理,会返回Too Many Requests。EjcJD

// Demo_CurrentHandleWithHTTP 模拟HTTP请求限流
func Demo_CurrentHandleWithHTTP() {
	// 每秒最多处理 1 个请求,允许突发 2 个请求
	limiter := rate.NewLimiter(1, 2)
	http.HandleFunc("/", func(w http.ResponseWriter, request *http.Request) {
		if limiter.Allow() {
			fmt.Fprintln(w, "Request allowed")
		} else {
			http.Error(w, "Too Many Requests", http.StatusTooManyRequests)
		}
	})
	fmt.Println("Server started at :8080")
	_ = http.ListenAndServe(":8080", nil)
}

正常请求:

go rate 原生标准限速库的使用

频繁请求(超过频次):

go rate 原生标准限速库的使用

模拟等待耗时任务处理

可用于限制资源(文件)的访问,避免资源(文件)被频繁访问造成性能问题。

func Demo_HandleWorkWithWait() {
	// 创建一个限速器,每3秒允许1个事件
	limiter := rate.NewLimiter(rate.Every(3*time.Second), 1)

	// 模拟10次对资源的访问
	for i := 0; i < 10; i++ {
		// 使用limiter.Wait(ctx)等待,直到可以访问资源(访问文件/执行数据库查询等)
		if err := limiter.Wait(context.Background()); err != nil {
			log.Fatalf("Failed to wait for rate limiter: %v", err)
		}
		// 访问资源
		fmt.Printf("Accessing resource at %v\n", time.Now())
	}
}

全部代码

Github:https://github.com/ziyifast/ziyifast-code_instruction/tree/main/go-demo/go-rat

参考文章:
https://cloud.tencent.com/developer/article/2429254
https://www.cnblogs.com/gnivor/p/10623028.html

到此这篇关于go rate 原生标准限速库的使用的文章就介绍到这了,更多相关go rate 原生标准限速库内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!

这篇关于go rate 原生标准限速库的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1154771

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Redis 基本数据类型和使用详解

《Redis基本数据类型和使用详解》String是Redis最基本的数据类型,一个键对应一个值,它的功能十分强大,可以存储字符串、整数、浮点数等多种数据格式,本文给大家介绍Redis基本数据类型和... 目录一、Redis 入门介绍二、Redis 的五大基本数据类型2.1 String 类型2.2 Hash

Redis中Hash从使用过程到原理说明

《Redis中Hash从使用过程到原理说明》RedisHash结构用于存储字段-值对,适合对象数据,支持HSET、HGET等命令,采用ziplist或hashtable编码,通过渐进式rehash优化... 目录一、开篇:Hash就像超市的货架二、Hash的基本使用1. 常用命令示例2. Java操作示例三