简单实现计数器限流算法

package main

import (
    "fmt"
    "net"
    "net/http"
    "sync"
    "time"
)

type Counter struct {
    mu        sync.Mutex
    count     int
    timestamp time.Time
}

func NewCounter() *Counter {
    return &Counter{
        count:     0,
        timestamp: time.Now(),
    }
}

func (c *Counter) Inc() {
    c.mu.Lock()
    defer c.mu.Unlock()
    now := time.Now()
    if now.Sub(c.timestamp) > time.Second {
        c.count = 1
        c.timestamp = now
    } else {
        c.count++
    }
}

func (c *Counter) Count() int {
    c.mu.Lock()
    defer c.mu.Unlock()
    return c.count
}

func main() {
    counter := NewCounter()
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        if r.URL.Path == "/index" && r.Method == "GET" {
            if counter.Count() >= 10 {
                http.Error(w, "Too Many Requests", http.StatusTooManyRequests)
                return
            }
            counter.Inc()
        }
        fmt.Fprintf(w, "Hello, world!")
    })
    listener, err := net.Listen("tcp", "localhost:8080")
    if err != nil {
        fmt.Println("Error listening:", err)
        return
    }
    defer listener.Close()
    fmt.Println("Listening on localhost:8080...")
    http.Serve(listener, nil)
}

当然实际生产场景中考虑因素远远比这个复杂的多,只是用作简单原理展示

在本文示例代码中,我们使用Go语言实现了一个简单的限流算法——令牌桶算法,并将其应用于HTTP请求服务器的/index GET接口上。具体地,我们定义了一个Counter结构体来记录当前请求计数和时间戳,使用NewCounter函数初始化一个Counter对象,并实现了Inc方法来增加计数器的值,并根据时间戳判断是否需要重置计数器的值。同时,我们还定义了一个处理函数,使用http.HandleFunc函数来为HTTP请求注册处理函数。在处理函数中,我们对请求路径和请求方法进行判断,仅对/index GET请求进行限流,限流阈值为10。最后,我们使用net.Listen函数创建一个listener对象,并使用http.Serve函数启动HTTP服务器,监听在localhost:8080地址上。

需要注意的是,本示例代码中的计数器算法仅是一种简单的实现,并未考虑实际应用中可能遇到的更多因素,如计数器的重置策略、限流阈值的动态调整、高并发等问题。在实际应用中,我们需要结合具体的业务场景和需求,采用更加严谨和完善的限流算法来保证服务的可靠性和稳定性。同时,我们还需要关注算法的性能和并发安全等问题,以确保其正确性和可维护性。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容