Golang高效流控实践

流控对于构建高可靠弹性系统至关重要,本文介绍了Golang内置的流控组件,通过该组件就可以打造适合各种业务场景的流控系统。原文: Rate Limiting in Go: Controlling Traffic with Efficiency[1]

Jon Cellier @Unsplash
Jon Cellier @Unsplash
导言

流控(Rate limiting)是构建可扩展弹性系统的重要技术之一,目的是通过限制指定时间内允许通过的请求数量来控制流量。在 Go 中实施流控可以确保最佳的资源利用率,并保护应用不被过多的流量或滥用行为所冲垮。本文将探讨 Go 中的流控技术,并提供代码示例,帮助感兴趣的读者有效实施这些技术。

了解流控

流控包括定义一套规则,确定客户端在给定时间窗口内可以发出多少请求,从而确保系统能够处理负载,防止滥用或拒绝服务攻击[2]。两种常见的流控方法是:

  • **固定窗口流控(Fixed Window Rate Limiting)**:在这种方法中,在一个固定时间窗口内执行流控。例如,如果流控设置为每分钟 100 个请求,则系统在任何给定的 60 秒窗口内最多允许 100 个请求,超过此限制的请求将被拒绝或延迟到下一个时间窗口。
  • **令牌桶流控(Token Bucket Rate Limiting)**:令牌桶流控基于令牌从桶中消耗的概念。令牌桶最初装满固定数量的令牌,每个令牌代表一个请求。当客户端要发出请求时,必须从桶中获取一个令牌。如果桶是空的,客户端必须等待,直到有令牌可用。
在 Go 中实施流控

Go 提供了一个名为 golang.org/x/time/rate 的内置软件包,实现了流控功能。接下来我们看看如何使用固定窗口和令牌桶两种方法来实现流控。

固定窗口流控
package main

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

func main() {
 limiter := rate.NewLimiter(rate.Limit(100), 1// Allow 100 requests per second

 for i := 0; i < 200; i++ {
  if !limiter.Allow() {
   fmt.Println("Rate limit exceeded. Request rejected.")
   continue
  }
  // Process the request
  fmt.Println("Request processed successfully.")
  time.Sleep(time.Millisecond * 100// Simulate request processing time
 }
}

在上面的代码片段中,我们用 rate.NewLimiter 创建了一个限制器,其速率限制为每秒 100 个请求。每个请求都会调用 limiter.Allow() 方法,如果允许请求,则返回 true,如果超过速率限制,则返回 false,超过速率限制的请求将被拒绝。

令牌桶流控
package main

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

func main() {
 limiter := rate.NewLimiter(rate.Limit(10), 5// Allow 10 requests per second with a burst of 5

 for i := 0; i < 15; i++ {
  if err := limiter.Wait(context.TODO()); err != nil {
   fmt.Println("Rate limit exceeded. Request rejected.")
   continue
  }
  // Process the request
  fmt.Println("Request processed successfully.")
  time.Sleep(time.Millisecond * 100// Simulate request processing time
 }
}

在上述代码中,我们用 rate.NewLimiter 创建了一个限制器,其速率限制为每秒 10 个请求,允许 5 个并发请求。每个请求都会调用 limiter.Wait() 方法,该方法会阻塞直到有令牌可用。如果令牌桶是空的,没有可用令牌,请求就会被拒绝。

动态流控

动态流控是指根据客户端行为、系统负载或业务规则等动态因素调整速率限制。这种技术允许我们实时调整流控,以优化资源利用率并提供更好的用户体验。让我们看看 Go 中动态流控的示例:

package main

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

func main() {
 limiter := rate.NewLimiter(rate.Limit(100), 1// Initial rate limit of 100 requests per second

 // Dynamic rate adjustment
 go func() {
  time.Sleep(time.Minute) // Adjust rate every minute
  limiter.SetLimit(rate.Limit(200)) // Increase rate limit to 200 requests per second
 }()

 for i := 0; i < 300; i++ {
  if !limiter.Allow() {
   fmt.Println("Rate limit exceeded. Request rejected.")
   continue
  }
  // Process the request
  fmt.Println("Request processed successfully.")
  time.Sleep(time.Millisecond * 100// Simulate request processing time
 }
}

在上面的代码片段中,我们创建了一个限制器,初始速率限制为每秒 100 个请求。然后,启动一个 goroutine,在一分钟后将速率限制调整为每秒 200 个请求。这样,我们就能根据不断变化的情况动态调整流控。

自适应流控

自适应流控可根据之前请求的响应时间或错误率动态调整速率限制,从而允许系统自动适应不同的流量条件,确保获得最佳性能和资源利用率。让我们看看 Go 中自适应流控示例:

package main

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

func main() {
 limiter := rate.NewLimiter(rate.Limit(100), 1// Initial rate limit of 100 requests per second

 // Adaptive rate adjustment
 go func() {
  for {
   responseTime := measureResponseTime() // Measure the response time of previous requests
   if responseTime > 500*time.Millisecond {
    limiter.SetLimit(rate.Limit(50)) // Decrease rate limit to 50 requests per second
   } else {
    limiter.SetLimit(rate.Limit(100)) // Increase rate limit to 100 requests per second
   }
   time.Sleep(time.Minute) // Adjust rate every minute
  }
 }()

 for i := 0; i < 200; i++ {
  if !limiter.Allow() {
   fmt.Println("Rate limit exceeded. Request rejected.")
   continue
  }
  // Process the request
  fmt.Println("Request processed successfully.")
  time.Sleep(time.Millisecond * 100// Simulate request processing time
 }
}

func measureResponseTime() time.Duration {
 // Measure the response time of previous requests
 // Implement your own logic to measure the response time
 return time.Millisecond * 200
}

在上述代码片段中,我们用 measureResponseTime 函数模拟测量之前请求的响应时间。根据测量到的响应时间,通过 limiter.SetLimit 设置不同的值来动态调整速率限制。这样,系统就能根据观察到的响应时间调整其流控策略。

结论
Jo Jo @Unsplash
Jo Jo @Unsplash

流控是保障 Go 应用程序稳定性和安全性的基本技术。通过有效控制传入请求的流量,可以防止资源耗尽并确保资源的公平分配。本文探讨了固定窗口和令牌桶流控的概念,并提供了代码片段,演示了如何基于 golang.org/x/time/rate 包实现流控策略,帮助读者将流控纳入应用程序,以构建能够高效处理不同流量水平的弹性系统。


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

参考资料
[1]

Rate Limiting in Go: Controlling Traffic with Efficiency: https://towardsdev.com/rate-limiting-in-go-controlling-traffic-with-efficiency-6a5ef7444ef8

[2]

拒绝服务攻击: https://en.wikipedia.org/wiki/Denial-of-service_attack

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/750293.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Javaweb day17 day18 day19

mysql-DDL 数据库操作 写法 客户端工具 &#xff08;也可以使用idea&#xff09; 表 写法 约束 数据类型 案例 写法 表的查询修改删除 写法 删除

RTC的Google拥塞控制算法 rmcat-gcc-02

摘要 本文档描述了使用时的两种拥塞控制方法万维网&#xff08;RTCWEB&#xff09;上的实时通信&#xff1b;一种算法是基于延迟策略&#xff0c;一种算法是基于丢包策略。 1.简介 拥塞控制是所有共享网络的应用程序的要求互联网资源 [RFC2914]。 实时媒体的拥塞控制对于许…

Lua中文语言编程源码-第四节,更改linit.c初始化库函数, 使Lua加载中文库关键词(与所有的基础库相关)

源码已经更新在CSDN的码库里&#xff1a; git clone https://gitcode.com/funsion/CLua.git 在src文件夹下的linit.c初始化库的函数&#xff0c;用于lua.c和其他客户端。 增加加载中文库宏名列表&#xff0c;保留英文库宏名列表。 原始的代码为&#xff1a; static const …

​​SQLiteC/C++接口详细介绍之sqlite3类(十)

返回目录&#xff1a;SQLite—免费开源数据库系列文章目录 上一篇&#xff1a;SQLiteC/C接口详细介绍之sqlite3类&#xff08;九&#xff09; 下一篇&#xff1a;​​SQLiteC/C接口详细介绍之sqlite3类&#xff08;十一&#xff09; 30.sqlite3_enable_load_extension&#x…

venv uvicorn python 虚拟服务器外网无法访问

python -m venv .venv source ./.venv/bin/activate pip install -r requirements.txt ./run.sh source ./.venv/bin/activate uvicorn main:app --reload 虚拟web服务器外网访问控制台启动命令用以下代码启动 uvicorn main:app --host 0.0.0.0 --port 8501 --reload 启动到后…

生命周期模型

1. 编码修补模型&#xff08;Code-and-Fix Model&#xff09; 定义&#xff1a;这是一种非正式的软件开发过程&#xff0c;开发者开始编写代码&#xff0c;然后在发现问题时修复它们&#xff0c;没有明确的需求分析和设计阶段。特征&#xff1a; 开始编码而不进行大量的设计或…

【Git】本地仓库关联远程仓库

Git 本地项目关联远程仓库 本地 本地已有项目 ● 项目 07.GitLocalTest 包含有一个js ○ test.js 远程仓库 ● 远程仓库地址 ○ https://github.com/Sonnenlicht77/gitTest.git ○ 仓库只有一个 readme.md 关联 1.本地 1.1 本地仓库 ● git init ● git add . ● gi…

掌握人工智能:人工智能工程师必须了解的顶级编程语言

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

单片机FLASH深度解析和编程实践(下)

本篇文章将同大家分享单片机FLASH编程的相关寄存器和寄存器操作及库函数操作。本篇文章依然以STM32单片机为例进行解析。有关FLASH的基本原理和实现方法&#xff0c;大家可以参考上一篇文章&#xff1a;单片机FLASH深度解析和编程实践&#xff08;上&#xff09;-CSDN博客 目录…

探索设计模式的魅力:探索发布-订阅模式的深度奥秘-实现高效、解耦的系统通信

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;并坚持默默的做事。 探索发布-订阅模式的深度奥秘&#xff1a;实现高效、解耦的系统通信 文章目录 一、案例场景&am…

Python深度学习之路:TensorFlow与PyTorch对比【第140篇—Python实现】

Python深度学习之路&#xff1a;TensorFlow与PyTorch对比 在深度学习领域&#xff0c;TensorFlow和PyTorch是两个备受青睐的框架&#xff0c;它们为开发人员提供了强大的工具来构建和训练神经网络模型。本文将对这两个框架进行对比&#xff0c;探讨它们的优势和劣势&#xff0…

macOS上基于httpd-dav搭建WebDav服务

文章目录 配置 Apache httpd修改 ServerName启动验证 httpd 服务启用 Dav 扩展服务配置 配置 httpd 扩展 Dav 服务设置共享目录文件夹配置 DavLockDB 目录创建 WebDAV 访客用户 httpd-dav.conf 主要改动部分BasicDigest共享多个目录 授予 httpd 完全磁盘访问权限验证更新配置重…

自适应日落动态卡通动画404页面模板

源码介绍 自适应日落动态卡通动画404页面模板&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面 下载地址 自适应日落动态卡通动画404页面模板

Java高级互联网架构师之路:排查当前JVM错误的步骤

程序 这个程序是有问题的,我们通过一些命令来分析这个程序究竟是哪里出了问题。首先把当前的程序通过SSH工具传输到centos系统中,之后我们就可以在linux环境下编译和执行。 注意一点:上面类的名字是Z,但是在linux环境下,我们将其改为了AA,并且文件名改为了AA,所以文章下…

常用图像滤波器,图像增强

滤波器 滤波器在图像处理中有各种各样的应用&#xff0c;它们可以用于去除噪声、平滑图像、增强图像特征等。以下是一些常见的滤波器及其主要应用&#xff1a; 均值滤波器&#xff08;Mean Filter&#xff09;&#xff1a; 用于去除高斯噪声或均匀噪声。 平滑图像&#xff0…

掌握Go语言:深入理解Go语言中的数组和切片,灵活处理数据的利器(16)

Go语言中的数组和切片是常用的集合类型&#xff0c;它们在处理数据时提供了不同的特性和灵活性。本文将深入探讨数组和切片的使用方法、特性、实例以及应用场景。 1. 数组和切片简介 在Go语言中&#xff0c;数组和切片都是集合类的类型&#xff0c;用于存储相同类型的元素。它…

Python实战:Python内置函数与常用标准库介绍

Python是一种广泛使用的高级编程语言&#xff0c;其内置函数和标准库为开发者提供了丰富的功能。本文将详细介绍Python的内置函数和常用标准库&#xff0c;包括数据类型、输入输出、文件操作、网络编程等。 1. 引言 Python的内置函数和标准库为开发者提供了丰富的功能&#x…

计算机网络----计算机网络的基础

目录 一.计算机网络的相关概念 二.计算机网络的功能 三.计算机网络的发展 四.计算机网络的组成 五.计算机网络的分类 六.计算机的性能指标 1.速率 2.带宽 3.吞吐量 4.时延 5.时延带宽积 6.往返时延RTT 7.利用率 七.计算机的分层结构 八.ISO/OSI参考模型 九.OSI…

2024云服务器安装MySQL,连接Navicat保姆级教程

文章目录 yum方式安装指定版本mysqlNavicat连接mysql&#xff0c;并建表 yum方式安装指定版本mysql 使用绝对路径cd /etc/yum.repos.d/进入该目录使用文本编辑器&#xff08;如 vim、nano 或 gedit&#xff09;创建 mysql57-community.repo 文件&#xff0c;在编辑页面粘贴下方…

软考80-上午题-【面向对象技术3-设计模式】-结构型设计模式03

一、外观模式 1-1、意图 为子系统中的一组接口提供一个一致的界面。 Facade 模式定义了一个高层接口&#xff0c;这个接口使得这一子系统更加容易使用。 1-2、结构 Facade 知道哪些子系统类负责处理请求&#xff1a;将客户的请求代理给适当的子系统对象。Subsvstem classes …