Go 语言 服务限流算法实现 Go语言版本

Go阿木 发布于 2025-06-23 8 次阅读


Go 语言服务限流算法实现

在分布式系统中,服务限流是一种常见的保护措施,用于防止系统过载和资源耗尽。限流算法可以确保在系统负载过高时,对请求进行合理的控制,从而保证系统的稳定性和可用性。本文将围绕Go语言实现服务限流算法这一主题,详细探讨几种常见的限流算法,并给出相应的代码实现。

限流算法概述

限流算法主要分为以下几类:

1. 固定窗口限流算法:在固定的时间窗口内,限制请求的通过量。

2. 滑动窗口限流算法:在滑动的时间窗口内,限制请求的通过量。

3. 令牌桶算法:通过维护一个令牌桶,按固定速率发放令牌,请求只有在获取到令牌后才能通过。

4. 漏桶算法:通过维护一个漏桶,以固定速率流出水滴,请求以固定速率通过。

固定窗口限流算法

固定窗口限流算法是最简单的限流算法之一。它通过记录每个时间窗口内的请求量来实现限流。

代码实现

go

package main

import (


"fmt"


"time"


)

type FixedWindowLimiter struct {


windowSize time.Duration


requestsPerSec int


requests []int


}

func NewFixedWindowLimiter(windowSize time.Duration, requestsPerSec int) FixedWindowLimiter {


return &FixedWindowLimiter{


windowSize: windowSize,


requestsPerSec: requestsPerSec,


requests: make([]int, 0, int(windowSize.Seconds()/time.Second)),


}


}

func (l FixedWindowLimiter) Allow() bool {


now := time.Now()


windowStart := now.Add(-l.windowSize)


for _, r := range l.requests {


if r >= windowStart.Unix() {


return false


}


}


l.requests = append(l.requests, now.Unix())


if len(l.requests) > int(l.windowSize.Seconds()/time.Second) {


l.requests = l.requests[1:]


}


return true


}

func main() {


limiter := NewFixedWindowLimiter(10time.Second, 100)


for i := 0; i < 200; i++ {


if limiter.Allow() {


fmt.Println("Request allowed")


} else {


fmt.Println("Request denied")


}


time.Sleep(50 time.Millisecond)


}


}


滑动窗口限流算法

滑动窗口限流算法与固定窗口限流算法类似,但它在处理请求时,会滑动窗口,而不是每次都从头开始。

代码实现

go

package main

import (


"fmt"


"time"


)

type SlidingWindowLimiter struct {


windowSize time.Duration


requestsPerSec int


requests []int


}

func NewSlidingWindowLimiter(windowSize time.Duration, requestsPerSec int) SlidingWindowLimiter {


return &SlidingWindowLimiter{


windowSize: windowSize,


requestsPerSec: requestsPerSec,


requests: make([]int, 0, int(windowSize.Seconds()/time.Second)),


}


}

func (l SlidingWindowLimiter) Allow() bool {


now := time.Now()


windowStart := now.Add(-l.windowSize)


for i, r := range l.requests {


if r >= windowStart.Unix() {


if i == 0 {


l.requests = l.requests[1:]


} else {


l.requests[i] = now.Unix()


}


break


}


}


l.requests = append(l.requests, now.Unix())


if len(l.requests) > int(l.windowSize.Seconds()/time.Second) {


l.requests = l.requests[1:]


}


return true


}

func main() {


limiter := NewSlidingWindowLimiter(10time.Second, 100)


for i := 0; i < 200; i++ {


if limiter.Allow() {


fmt.Println("Request allowed")


} else {


fmt.Println("Request denied")


}


time.Sleep(50 time.Millisecond)


}


}


令牌桶算法

令牌桶算法通过维护一个令牌桶,以固定速率发放令牌,请求只有在获取到令牌后才能通过。

代码实现

go

package main

import (


"fmt"


"time"


)

type TokenBucketLimiter struct {


rate float64


capacity int


tokens int


lastTime time.Time


}

func NewTokenBucketLimiter(rate float64, capacity int) TokenBucketLimiter {


return &TokenBucketLimiter{


rate: rate,


capacity: capacity,


tokens: capacity,


lastTime: time.Now(),


}


}

func (l TokenBucketLimiter) Allow() bool {


now := time.Now()


elapsed := now.Sub(l.lastTime).Seconds()


l.tokens += int(elapsed l.rate)


if l.tokens > l.capacity {


l.tokens = l.capacity


}


l.lastTime = now


if l.tokens > 0 {


l.tokens--


return true


}


return false


}

func main() {


limiter := NewTokenBucketLimiter(1, 100)


for i := 0; i < 200; i++ {


if limiter.Allow() {


fmt.Println("Request allowed")


} else {


fmt.Println("Request denied")


}


time.Sleep(10 time.Millisecond)


}


}


漏桶算法

漏桶算法通过维护一个漏桶,以固定速率流出水滴,请求以固定速率通过。

代码实现

go

package main

import (


"fmt"


"time"


)

type BucketLimiter struct {


rate float64


lastTime time.Time


}

func NewBucketLimiter(rate float64) BucketLimiter {


return &BucketLimiter{


rate: rate,


lastTime: time.Now(),


}


}

func (l BucketLimiter) Allow() bool {


now := time.Now()


elapsed := now.Sub(l.lastTime).Seconds()


l.lastTime = now


if elapsed > 1 {


return true


}


return false


}

func main() {


limiter := NewBucketLimiter(1)


for i := 0; i < 200; i++ {


if limiter.Allow() {


fmt.Println("Request allowed")


} else {


fmt.Println("Request denied")


}


time.Sleep(10 time.Millisecond)


}


}


总结

本文介绍了四种常见的限流算法,并给出了Go语言的实现代码。在实际应用中,可以根据具体场景选择合适的限流算法,以达到最佳的性能和效果。