技术文摘
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 语言中的实现。在实际应用中,需要根据具体的业务场景选择合适的限流算法,以保障系统的稳定运行。
- 清华姚班毕业生创全新特效编程语言 仅用 99 行代码呈现《冰雪奇缘》
- 量子霸权难以实现:造出有用量子计算机困难重重
- 你们公司的“微服务”竟如此反人类
- Java 日志中 Slf4j、Log4J 与 Logback 原理综述
- 提升 Python 程序 30%运行速度的技巧
- 2020 年 Kubernetes 的 5 大预测
- Java 的 JSP 真的已被淘汰?
- CSS 中那些令人困惑的经典问题
- 我在 GitHub 任 CTO 的团队打造历程
- React 团队的技术规范
- 谷歌向美最高法院示警:甲骨文或成垄断势力
- 2020 年微软开发者的五项值得探究技术
- 为何一到年底部分网站会出现日期混乱,该如何向女友解释
- 技术运营中台建设与 AIOps 实践,一篇尽览
- 知识图谱并不复杂,我为您梳理