go-zero中限流怎么玩?

限流

在大部分应用中,为了对服务进行保护,我们通常都会添加限流策略,比如:限制同一用户一段时间内验证码的发送频率、开放API平台,限制每个应用在单位时间内的API调用次数、单节点限制最大并发数据,防止压垮服务等等。

今天我们一起来看看在go-zero中限流怎么玩?

go-zero中的限流主要有三种,我们依次看下。

一、 配置MaxConns

它是一种http单节点的限流,它限制的是当前节点的并发量(并发数)

它**最简单,只需要我们在api模块下的etc目录配置MaxConns**就行,其它啥也不用做,如下:

yaml 复制代码
Name: limit

Host: 0.0.0.0

Port: 8888

MaxConns: 100

PS: 默认情况下MaxConns为10000.

原理

它是通过syncx.Limit实现的。

它的机制是一种连接池机制,一开始有一个池,这个池子有一个最大的并发量。

  • 每次请会先从池子借用一个连接

  • 使用完后归还连接

当全部借出后,则不再处理请求,提示(concurrent connections over ...).

它的使用非常简单,就是三步:

  1. 初始化池子(sync.Limit)

  2. 借用

  3. 归还

代码如下:

go 复制代码
package main

  


import (

"fmt"

"log"

  


"github.com/zeromicro/go-zero/core/syncx"

)

  


func main() {

limit := syncx.NewLimit(2)

  


if limit.TryBorrow() {

fmt.Println("借用成功啦")

} else {

fmt.Println("借用失败")

}

  


err := limit.Return()

if err != nil {

log.Println("归还失败:", err)

} else {

fmt.Println("归还成功")

}

}

二、令牌通限流

上面我们已经介绍了针对于http请求场景的单节点限流,它的粒度相对较大。在一些其它场景还是不能满足我们的要求。

比如:比如我们希望对某一个细分模块限流,比如发送短信模块,我们希望每秒内最多发送100条短信,那么我们就可以使用令牌桶限流。

它限制的是:每秒内的发生频率,且支持一个范围,一个最小值和一个最大值------应对突发情况.

PS:它的使用要复杂点,依赖于redis

代码:

go 复制代码
package main

  


import (

"fmt"

  


"github.com/zeromicro/go-zero/core/limit"

"github.com/zeromicro/go-zero/core/stores/redis"

)

  


func main() {

store, err := redis.NewRedis(redis.RedisConf{Host: "127.0.0.1:6379", Type: "node"})

if err != nil {

panic(err)

}

  


// 每秒中内 可以处理 5-10个请求(最大20个超过就爆掉)

// example-key 是redis中标记(或者限制模块的key)

limiter := limit.NewTokenLimiter(5, 10, store, "example-key")

  


// 我们测试

for i := 0; i < 20; i++ {

// 是否允许

if limiter.Allow() {

fmt.Println("Request allowed") // 前10个成功

} else {

fmt.Println("Request not allowed") // 后10个失败

}

}

}

  


// Request allowed

// Request allowed

// Request allowed

// Request allowed

// Request allowed

// Request allowed

// Request allowed

// Request allowed

// Request allowed

// Request allowed

// Request not allowed

// Request not allowed

// Request not allowed

// Request not allowed

// Request not allowed

// Request not allowed

// Request not allowed

// Request not allowed

// Request not allowed

// Request not allowed

前10个请求成功,后10个请求失败,符合我们的预期。

三、计数器(时间内限流)

前面我们限制的是1s内处理数,但是在很多场景下,通常我们限制的是一个时间范围内的请求次数

比如:一个用户在一分钟内,只能获取2次验证码。

它通常是更细分、用户级的限流

它也依赖于redis

它的使用大体和令牌桶类似,只是它的参数不同,如下:

go 复制代码
package main

  


import (

"fmt"

  


"github.com/zeromicro/go-zero/core/limit"

"github.com/zeromicro/go-zero/core/stores/redis"

)

  


func main() {

store, err := redis.NewRedis(redis.RedisConf{Host: "127.0.0.1:6379", Type: "node"})

if err != nil {

panic(err)

}

  


// 这里限制60秒内 最多允许2次

// 注意这里的exampleKey只是一个前缀(具体的key后半部分由场景决定)

limiter := limit.NewPeriodLimit(60, 2, store, "exampleKey")

  


for i := 0; i < 10; i++ {

// 这里的限制用户的请求次数

result, err := limiter.Take("userId")

if err != nil {

fmt.Println("Error:", err)

return

}

  


switch result {

case limit.Allowed:

fmt.Println("Request allowed")

case limit.HitQuota: // 代表达到临界点(下一次就超了)

fmt.Println("Hit the quota")

case limit.OverQuota:

fmt.Println("Over the quota")

default:

fmt.Println("Unknown status")

}

}

}

  


// Request allowed

// Hit the quota

// Over the quota

// Over the quota

// Over the quota

// Over the quota

// Over the quota

// Over the quota

// Over the quota

// Over the quota
相关推荐
IT_陈寒6 分钟前
Vite 3.0 性能优化实战:5个技巧让你的构建速度提升200% 🚀
前端·人工智能·后端
程序新视界26 分钟前
MySQL的整体架构及功能详解
数据库·后端·mysql
绝无仅有27 分钟前
猿辅导Java面试真实经历与深度总结(二)
后端·面试·github
绝无仅有34 分钟前
猿辅导Java面试真实经历与深度总结(一)
后端·面试·github
Victor3561 小时前
Redis(76)Redis作为缓存的常见使用场景有哪些?
后端
Victor3562 小时前
Redis(77)Redis缓存的优点和缺点是什么?
后端
摇滚侠5 小时前
Spring Boot 3零基础教程,WEB 开发 静态资源默认配置 笔记27
spring boot·笔记·后端
天若有情6737 小时前
Java Swing 实战:从零打造经典黄金矿工游戏
java·后端·游戏·黄金矿工·swin
一只叫煤球的猫8 小时前
建了索引还是慢?索引失效原因有哪些?这10个坑你踩了几个
后端·mysql·性能优化
magic334165639 小时前
Springboot整合MinIO文件服务(windows版本)
windows·spring boot·后端·minio·文件对象存储