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 语言中的实现。在实际应用中,需要根据具体的业务场景选择合适的限流算法,以保障系统的稳定运行。

TAGS: Go 语言开发 Go 语言实现 限流算法类型 Go 语言限流算法

欢迎使用万千站长工具!

Welcome to www.zzTool.com