Go语言框架快速集成限流中间件详解

 更新时间:2022年09月07日 09:29:41   作者:Masters  
这篇文章主要为大家介绍了Go语言框架快速集成限流中间件详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前言

在我们的日常开发中, 常用的中间件有很多, 今天来讲一下怎么集成限流中间件, 它可以很好地用限制并发访问数来保护系统服务, 避免系统服务崩溃, 资源占用过大甚至服务器崩溃进而影响到其他应用!

分布式版

简介

通常我们的服务会同时存在多个进程, 也就是负载来保证服务的性能和稳定性, 那么就需要走一个统一的限流, 这个时候就需要借助我们的老朋友-redis, 来进行分布式限流;

算法

漏桶算法

即一个水桶, 进水(接受请求)的速率不限, 出水(处理请求)的速率是一定的, 如果出水的速率小于进水的速率, 就会造成水桶溢出(也就是拒绝请求); 主要是从出口限制, 以固定的速率控制访问速度, 缺点是难以应对突发请求;

实现

下面是一个简单的实现, 对 /v1/hello接口进行每分钟2次的速率限制

// RateLimitConf 速率配置, 允许多长时间通过多少次.
type RateLimitConf struct {
	Limit int64
	Timer time.Duration
}
// exampleLimiterMap 接口请求速率配置, 建议放入redis/数据库同步本地缓存.
var exampleLimiterMap = map[string]RateLimitConf{
	"/v1/hello": {Limit: 2, Timer: time.Minute},
}
// LimiterMiddle 分布式限流中间件.
func LimiterMiddle(ctx iris.Context) {
	var (
		uri    = ctx.Request().RequestURI
		client = redis.NewClusterClient()
		key    = uri
	)
	conf, ok := exampleLimiterMap[uri]
	if ok {
		limiter := redis_rate.NewLimiter(client)
		if _, _, b := limiter.Allow(key, conf.Limit, conf.Timer); !b {
			r, _ := httpcode.NewRequest(ctx, nil)
			r.Code(httpcode.TooManyReq, fmt.Errorf("req rate limit"), nil)
			return
		}
	}
	ctx.Next()
}

注意

  • 接口速率配置如果需要进行实时配置, 则建议将配置写入数据库, 然后刷新到本地缓存/存到redis;
  • 如果需要对设备/ip/用户进行接口限制访问, 则将 key加上唯一标志即可;

单机版

简介

这个就只适用于单个服务进程的限流, 比如个人搭的一些小网站之类的;

算法

令牌桶算法

即也是一个桶, 按照设定的速率往桶里放令牌, 10s二十次即1s放两个令牌(允许处理两次请求), 然后请求来之后必须从桶里取出来令牌才可以进行处理, 没有令牌则选择拒绝或等待; 主要是从入口限制, 允许一定量的突发请求(即桶内所有的令牌);

依赖库

golang.org/x/time/rate

实现

下面是一个简单的实现, 对 /v1/hello接口进行每分钟2次的速率限制

// exampleStandAloneLimiterMap 单机接口请求速率配置.
var exampleStandAloneLimiterMap = map[string]*rate.Limiter{
	"/v1/hello": rate.NewLimiter(rate.Every(time.Minute), 2),
}
// StandAloneLimiterMiddle 单机限流中间件.
func StandAloneLimiterMiddle(ctx iris.Context) {
	var (
		uri = ctx.Request().RequestURI
	)
	limiter, ok := exampleStandAloneLimiterMap[uri]
	if ok {
		if b := limiter.Allow(); !b {
			r, _ := httpcode.NewRequest(ctx, nil)
			r.Code(httpcode.TooManyReq, fmt.Errorf("req rate limit"), nil)
			return
		}
	}
	ctx.Next()
}

结语

上面的代码均摘自我开发的一个开源项目中, 主要是一个Go的标准项目布局, 封装了一些常用的组件, 有兴趣的朋友可以了解一下, 新手极易上手;

以上就是Go语言框架快速集成限流中间件详解的详细内容,更多关于Go框架集成限流中间件的资料请关注脚本之家其它相关文章!

相关文章

  • go日志系统logrus显示文件和行号的操作

    go日志系统logrus显示文件和行号的操作

    这篇文章主要介绍了go日志系统logrus显示文件和行号的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • Go语言WaitGroup使用时需要注意的坑

    Go语言WaitGroup使用时需要注意的坑

    Go语言中WaitGroup的用途是它能够一直等到所有的goroutine执行完成,并且阻塞主线程的执行,直到所有的goroutine执行完成。之前一直使用也没有问题,但最近通过同事的一段代码引起了关于WaitGroup的注意,下面这篇文章就介绍了WaitGroup使用时需要注意的坑及填坑。
    2016-12-12
  • 使用Golang实现AES加解密的代码示例

    使用Golang实现AES加解密的代码示例

    在现代的数据安全中,加密和解密是极其重要的一环,其中,高级加密标准(AES)是最广泛使用的加密算法之一,本文将介绍如何使用Golang来实现AES加密和解密,需要的朋友可以参考下
    2024-04-04
  • 浅析GO并发处理选择sync还是channel

    浅析GO并发处理选择sync还是channel

    这篇文章主要想来和大家讨论一下,GO 语言处理并发的时候我们是选择sync还是channel,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下
    2023-08-08
  • Go语言中的Slice学习总结

    Go语言中的Slice学习总结

    这篇文章主要介绍了Go语言中的Slice学习总结,本文讲解了Slice的定义、Slice的长度和容量、Slice是引用类型、Slice引用传递发生“意外”等内容,需要的朋友可以参考下
    2014-11-11
  • 深入学习Golang并发编程必备利器之sync.Cond类型

    深入学习Golang并发编程必备利器之sync.Cond类型

    Go 语言的 sync 包提供了一系列同步原语,其中 sync.Cond 就是其中之一。本文将深入探讨 sync.Cond 的实现原理和使用方法,帮助大家更好地理解和应用 sync.Cond,需要的可以参考一下
    2023-05-05
  • golang RWMutex读写锁实现读共享写独占的功能示例

    golang RWMutex读写锁实现读共享写独占的功能示例

    在 Go 里除了互斥锁外,还有读写锁 RWMutex,它主要用来实现读共享,写独占的功能,今天我们也顺便分析下读写锁,加深对 Go 锁的理解
    2023-09-09
  • golang 字符串拼接性能的对比分析

    golang 字符串拼接性能的对比分析

    这篇文章主要介绍了golang 字符串拼接性能的对比分析,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Go中Gzip与json搭配实现数据压缩demo

    Go中Gzip与json搭配实现数据压缩demo

    这篇文章主要为大家介绍了Go中Gzip与json搭配使用压缩数据的实现demo,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • 从零封装Gin框架及项目初始化教程

    从零封装Gin框架及项目初始化教程

    这篇文章主要为大家介绍了从零封装Gin框架及项目的初始化教程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01

最新评论