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)
}
當(dāng)然實際生產(chǎn)場景中考慮因素遠(yuǎn)遠(yuǎn)比這個復(fù)雜的多现柠,只是用作簡單原理展示
在本文示例代碼中,我們使用Go語言實現(xiàn)了一個簡單的限流算法——令牌桶算法拥诡,并將其應(yīng)用于HTTP請求服務(wù)器的/index GET接口上择克。具體地,我們定義了一個Counter結(jié)構(gòu)體來記錄當(dāng)前請求計數(shù)和時間戳驼修,使用NewCounter函數(shù)初始化一個Counter對象,并實現(xiàn)了Inc方法來增加計數(shù)器的值诈铛,并根據(jù)時間戳判斷是否需要重置計數(shù)器的值乙各。同時,我們還定義了一個處理函數(shù)幢竹,使用http.HandleFunc函數(shù)來為HTTP請求注冊處理函數(shù)耳峦。在處理函數(shù)中,我們對請求路徑和請求方法進(jìn)行判斷焕毫,僅對/index GET請求進(jìn)行限流蹲坷,限流閾值為10。最后邑飒,我們使用net.Listen函數(shù)創(chuàng)建一個listener對象循签,并使用http.Serve函數(shù)啟動HTTP服務(wù)器,監(jiān)聽在localhost:8080地址上疙咸。
需要注意的是县匠,本示例代碼中的計數(shù)器算法僅是一種簡單的實現(xiàn),并未考慮實際應(yīng)用中可能遇到的更多因素,如計數(shù)器的重置策略乞旦、限流閾值的動態(tài)調(diào)整贼穆、高并發(fā)等問題。在實際應(yīng)用中杆查,我們需要結(jié)合具體的業(yè)務(wù)場景和需求扮惦,采用更加嚴(yán)謹(jǐn)和完善的限流算法來保證服務(wù)的可靠性和穩(wěn)定性。同時亲桦,我們還需要關(guān)注算法的性能和并發(fā)安全等問題崖蜜,以確保其正確性和可維護(hù)性。