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
相关推荐
小石潭记丶5 小时前
goland无法debug项目
go
Asthenia04126 小时前
如何在项目中集成GC日志输出与高效分析?一篇开发者必读的实践指南
后端
码界筑梦坊6 小时前
基于Flask的第七次人口普查数据分析系统的设计与实现
后端·python·信息可视化·flask·毕业设计
独泪了无痕7 小时前
MySQL查询优化-distinct
后端·mysql·性能优化
阿波茨的鹅8 小时前
Asp.Net 前后端分离项目——项目搭建
后端·asp.net
Asthenia04128 小时前
Jvm参数——规律记忆方法
后端
超爱吃士力架8 小时前
MySQL 三层 B+ 树能存多少数据?
java·后端·面试
转转技术团队8 小时前
高并发下秒杀系统的设计
后端
超爱吃士力架8 小时前
MySQL 索引的最左前缀匹配原则是什么?
java·后端·面试
bobz9659 小时前
keepalive 启用 syslog
后端