Golang高效流控实践

2024-03-16 16:04
文章标签 golang 高效 实践 流控

本文主要是介绍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 多平台发布

这篇关于Golang高效流控实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/815979

相关文章

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

Spring Boot 配置文件之类型、加载顺序与最佳实践记录

《SpringBoot配置文件之类型、加载顺序与最佳实践记录》SpringBoot的配置文件是灵活且强大的工具,通过合理的配置管理,可以让应用开发和部署更加高效,无论是简单的属性配置,还是复杂... 目录Spring Boot 配置文件详解一、Spring Boot 配置文件类型1.1 applicatio

golang 日志log与logrus示例详解

《golang日志log与logrus示例详解》log是Go语言标准库中一个简单的日志库,本文给大家介绍golang日志log与logrus示例详解,感兴趣的朋友一起看看吧... 目录一、Go 标准库 log 详解1. 功能特点2. 常用函数3. 示例代码4. 优势和局限二、第三方库 logrus 详解1.

tomcat多实例部署的项目实践

《tomcat多实例部署的项目实践》Tomcat多实例是指在一台设备上运行多个Tomcat服务,这些Tomcat相互独立,本文主要介绍了tomcat多实例部署的项目实践,具有一定的参考价值,感兴趣的可... 目录1.创建项目目录,测试文China编程件2js.创建实例的安装目录3.准备实例的配置文件4.编辑实例的

Python 中的异步与同步深度解析(实践记录)

《Python中的异步与同步深度解析(实践记录)》在Python编程世界里,异步和同步的概念是理解程序执行流程和性能优化的关键,这篇文章将带你深入了解它们的差异,以及阻塞和非阻塞的特性,同时通过实际... 目录python中的异步与同步:深度解析与实践异步与同步的定义异步同步阻塞与非阻塞的概念阻塞非阻塞同步

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

SpringBoot使用OkHttp完成高效网络请求详解

《SpringBoot使用OkHttp完成高效网络请求详解》OkHttp是一个高效的HTTP客户端,支持同步和异步请求,且具备自动处理cookie、缓存和连接池等高级功能,下面我们来看看SpringB... 目录一、OkHttp 简介二、在 Spring Boot 中集成 OkHttp三、封装 OkHttp

springboot集成Deepseek4j的项目实践

《springboot集成Deepseek4j的项目实践》本文主要介绍了springboot集成Deepseek4j的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录Deepseek4j快速开始Maven 依js赖基础配置基础使用示例1. 流式返回示例2. 进阶

使用Python高效获取网络数据的操作指南

《使用Python高效获取网络数据的操作指南》网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将... 目录网络爬虫的基本概念常用库介绍安装库Requests和BeautifulSoup爬虫开发发送请求解

Android App安装列表获取方法(实践方案)

《AndroidApp安装列表获取方法(实践方案)》文章介绍了Android11及以上版本获取应用列表的方案调整,包括权限配置、白名单配置和action配置三种方式,并提供了相应的Java和Kotl... 目录前言实现方案         方案概述一、 androidManifest 三种配置方式