技术文摘
Go 语言实现的几种限流算法
2024-12-31 02:07:38 小编
Go 语言实现的几种限流算法
在当今的高并发系统中,限流算法是保障系统稳定性和可靠性的重要手段。本文将介绍几种常见的限流算法,并展示如何使用 Go 语言来实现它们。
一、固定窗口限流算法
固定窗口限流算法是一种简单直观的限流方式。它将时间划分为固定大小的窗口,在每个窗口内允许一定数量的请求通过。
以下是使用 Go 语言实现固定窗口限流算法的示例代码:
package main
import (
"fmt"
"time"
)
type FixedWindowLimiter struct {
limit int
windowSize time.Duration
requests int
lastTimestamp time.Time
}
func (l *FixedWindowLimiter) AllowRequest() bool {
now := time.Now()
if now.Sub(l.lastTimestamp) >= l.windowSize {
l.requests = 0
l.lastTimestamp = now
}
if l.requests < l.limit {
l.requests++
return true
}
return false
}
func main() {
limiter := &FixedWindowLimiter{
limit: 100,
windowSize: time.Minute,
}
for i := 0; i < 200; i++ {
if limiter.AllowRequest() {
fmt.Printf("Request %d allowed\n", i)
} else {
fmt.Printf("Request %d denied\n", i)
}
}
}
二、滑动窗口限流算法
滑动窗口限流算法相对于固定窗口算法更加精确。它将时间划分为多个小的子窗口,通过滑动窗口来统计请求数量。
以下是滑动窗口限流算法的 Go 语言实现示例:
package main
import (
"fmt"
"time"
)
type SlidingWindowLimiter struct {
limit int
windowSize time.Duration
bucketCount int
buckets []int
currentIndex int
}
func (l *SlidingWindowLimiter) Init() {
bucketDuration := l.windowSize / time.Duration(l.bucketCount)
l.buckets = make([]int, l.bucketCount)
for i := 0; i < l.bucketCount; i++ {
l.buckets[i] = 0
}
}
func (l *SlidingWindowLimiter) AllowRequest() bool {
now := time.Now()
elapsedBuckets := int(now.Sub(l.lastRequestTime) / bucketDuration)
if elapsedBuckets > 0 {
for i := 0; i < elapsedBuckets; i++ {
l.buckets[(l.currentIndex+i)%l.bucketCount] = 0
}
l.currentIndex = (l.currentIndex + elapsedBuckets) % l.bucketCount
}
totalRequests := 0
for _, count := range l.buckets {
totalRequests += count
}
if totalRequests < l.limit {
l.buckets[l.currentIndex]++
return true
}
return false
}
func main() {
limiter := &SlidingWindowLimiter{
limit: 100,
windowSize: time.Minute,
bucketCount: 10,
}
limiter.Init()
for i := 0; i < 200; i++ {
if limiter.AllowRequest() {
fmt.Printf("Request %d allowed\n", i)
} else {
fmt.Printf("Request %d denied\n", i)
}
}
}
三、漏桶限流算法
漏桶算法可以将突发的流量整形为固定的输出速率。
以下是漏桶限流算法的 Go 语言实现:
package main
import (
"fmt"
"time"
)
type LeakyBucketLimiter struct {
capacity int
rate int
water int
lastLeakTime time.Time
}
func (l *LeakyBucketLimiter) AllowRequest() bool {
now := time.Now()
elapsed := now.Sub(l.lastLeakTime)
leaked := int(elapsed.Seconds() * float64(l.rate))
l.water = max(0, l.water - leaked)
l.lastLeakTime = now
if l.water < l.capacity {
l.water++
return true
}
return false
}
func main() {
limiter := &LeakyBucketLimiter{
capacity: 100,
rate: 20,
}
for i := 0; i < 200; i++ {
if limiter.AllowRequest() {
fmt.Printf("Request %d allowed\n", i)
} else {
fmt.Printf("Request %d denied\n", i)
}
}
}
以上就是几种常见的限流算法及其在 Go 语言中的实现。在实际应用中,需要根据具体的业务场景选择合适的限流算法,以保障系统的稳定运行。
- Git 操作错误后的应对之策,收藏此文档
- Redis 在海量数据与高并发中的优化实践直接上手
- 给女朋友转账促使我思考分布式事务
- Spring 中有关 Null 的这些事,你真的清楚吗?
- 决战紫禁之巅:深度学习框架 Keras 与 PyTorch 之比较
- Python 十大图像优化工具,尽显简洁魅力
- 彻底搞懂写缓冲(Change Buffer)
- 9 款免费的 Java 流程监控工具
- 阿里巴巴为何要求慎用 ArrayList 中的 subList 方法
- 后台(脱离模式)运行 Docker 容器的方法
- Java 效率工具 Lombok:代码洁癖者的福音
- JavaScript 能否成为 Web 开发的未来
- 用三行 Python 代码,让你的数据处理速度超他人 4 倍
- 浅议汇编器、编译器与解释器
- 彻底弄懂“分布式事务”