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
相关推荐
Chandler2412 分钟前
Go:反射
开发语言·后端·golang
pwzs18 分钟前
深入浅出 MVCC:MySQL 并发背后的多版本世界
数据库·后端·mysql
盒子691019 分钟前
go for 闭环问题【踩坑记录】
开发语言·后端·golang
刘大猫261 小时前
Arthas monitor(方法执行监控)
人工智能·后端·监控
追逐时光者1 小时前
MongoDB从入门到实战之MongoDB简介
后端·mongodb
Huazie2 小时前
在WSL2 Ubuntu中部署FastDFS服务的完整指南
服务器·后端·ubuntu
行者无疆xcc3 小时前
【Django】设置让局域网内的人访问
后端·python·django
嘵奇3 小时前
基于Spring Boot实现文件秒传的完整方案
java·spring boot·后端
Value_Think_Power3 小时前
azure 一个 pod 内有多个 container ,这些container 可以 共享一块磁盘吗
后端
李菠菜3 小时前
优化Centos关闭SELinux/Swap及资源限制调整
linux·后端·centos