go實(shí)現(xiàn)限流功能示例
引言
在我們?nèi)粘>S護(hù)中,經(jīng)常有爬蟲(chóng)進(jìn)行爬取網(wǎng)頁(yè),少則1秒鐘請(qǐng)求數(shù)十次,多則達(dá)百次,嚴(yán)重消耗了服務(wù)器帶寬,且影響正常使用者,好在nginx
可以配合lua
可以完成類(lèi)似的需求,本次我們將使用go
來(lái)完成本需求。
需求背景
在我們?nèi)粘>S護(hù)中,可能需要這樣一種工具,來(lái)對(duì)某些路由,對(duì)特定IP或者用戶ID,在特定時(shí)間內(nèi),限制最大訪問(wèn)次數(shù),這樣有效的避免服務(wù)器帶寬資源的浪費(fèi)的同時(shí)也能接入更多用戶請(qǐng)求,本次使用go
來(lái)做一個(gè)類(lèi)似的。
web demo搭建
我們先來(lái)使用SampleHttp
編寫(xiě)一個(gè)最簡(jiǎn)單的web
服務(wù)器,定義路由queryAll
,收到后,假設(shè)將返回客戶端1w字節(jié)的數(shù)據(jù)信息。
在啟動(dòng)web
服務(wù)器后,我們使用curl
進(jìn)行測(cè)試
命令:
curl 127.0.0.1:8083/queryAll
限制訪問(wèn)次數(shù)編寫(xiě)
在上述整體需求的情況下,我們需要編寫(xiě)在規(guī)定時(shí)間限制訪問(wèn)次數(shù)的需求,這里我們?yōu)榱朔奖?,使?code>ip來(lái)作為限制條件,其核心功能分類(lèi)大致分為:
- 從未訪問(wèn)過(guò)
web
服務(wù)器 - 訪問(wèn)過(guò)
web
服務(wù)器,在規(guī)定時(shí)間內(nèi)沒(méi)有超出限制 - 訪問(wèn)過(guò)
web
服務(wù)器,在在規(guī)定時(shí)間內(nèi)超出了限制 - 訪問(wèn)過(guò)
web
服務(wù)器,時(shí)間間隔超過(guò)了規(guī)定時(shí)間
如上分類(lèi),除了第三種需要限流外,其他則視為正常訪問(wèn)即可。
核心存儲(chǔ),我們可以選擇go map
,其中key
為ip
,value
為結(jié)構(gòu)體,該結(jié)構(gòu)體包含訪問(wèn)次數(shù)和創(chuàng)建間戳。
其定義如下
我們來(lái)根據(jù)如上定義的核心功能來(lái)編寫(xiě)程序
從未訪問(wèn)過(guò)服務(wù)器
我們根據(jù)map
中是否存在這個(gè)key
來(lái)判斷,如
_, ok := visitHashMap[ip]; if !ok { // 如果沒(méi)有該ip的訪問(wèn)次數(shù),則新增記錄 }
訪問(wèn)過(guò)服務(wù)器,在規(guī)定時(shí)間超過(guò)了限制
if time.Now().Unix()-visit.createUnixTime >= interval*60 { // 在規(guī)定時(shí)間超過(guò)了限制,需要重新計(jì)算閾值 }
超過(guò)最大允許訪問(wèn)數(shù)
if visitHashMap[ip].number >= maxNum { // 超過(guò)允許最大訪問(wèn)次數(shù) }
整理為其核心函數(shù)如下
功能測(cè)試
我們?cè)诙x路由地方,將來(lái)訪者IP
傳入,就可以根據(jù)其返回的bool
值來(lái)判斷是否需要限制訪問(wèn)了。
其main
函數(shù)定義如下:
func main() { SampleHttp.Route("get","/queryAll", func(info *SampleHttp.HttpInfo) { ip := strings.Split(info.RemoteIP,":")[0] if ! limits(ip) { info.Write([]byte(fmt.Sprintf("%s 已經(jīng)被限制訪問(wèn),在%d分鐘內(nèi),訪問(wèn)達(dá)到%d次",time.Now(),interval,visitHashMap[ip].number))) return } info.Write([]byte(fmt.Sprintf("%s 收到queryAll請(qǐng)求,開(kāi)始查詢,返回1W字節(jié)數(shù)據(jù)信息...,統(tǒng)計(jì)信息: 在%d分鐘內(nèi),訪問(wèn)達(dá)到%d次",time.Now(),interval,visitHashMap[ip].number))) }) visitHashMap = make(map[string]visitInfo,0) SampleHttp.StartServer("0.0.0.0:8083") }
我們將開(kāi)啟服務(wù)器來(lái)測(cè)試一下
通過(guò)上述執(zhí)行結(jié)果圖,可以看到,當(dāng)1分鐘內(nèi)訪問(wèn)次數(shù)超過(guò)10次后,就被限制訪問(wèn)了,而從第一次訪問(wèn)時(shí)間到目前訪問(wèn)時(shí)間間隔達(dá)到1分鐘以上后,限制就被解除了,可見(jiàn)功能已經(jīng)完成了。
總結(jié)
如上只是實(shí)現(xiàn)了這種方法而已,在實(shí)際項(xiàng)目中,還需要詳細(xì)的打磨才行,不然執(zhí)行效率肯定堪憂,怎么樣,限制這個(gè)看著好玩吧,快來(lái)試試吧,相關(guān)代碼已經(jīng)放置到了gitee上。
以上就是go實(shí)現(xiàn)限流功能示例的詳細(xì)內(nèi)容,更多關(guān)于go限流功能的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang復(fù)制文件夾移動(dòng)到另一個(gè)文件夾實(shí)現(xiàn)方法詳解
這篇文章主要為大家介紹了golang復(fù)制文件夾并移動(dòng)到另一個(gè)文件夾實(shí)現(xiàn)方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07詳解如何在golang鏡像中設(shè)置指定時(shí)區(qū)
這篇文章主要為大家詳細(xì)介紹了如何在golang鏡像中設(shè)置指定時(shí)區(qū),文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的可以了解一下2023-04-04golang并發(fā)之使用sync.Pool優(yōu)化性能
在Go提供如何實(shí)現(xiàn)對(duì)象的緩存池功能,常用一種實(shí)現(xiàn)方式是sync.Pool,?其旨在緩存已分配但未使用的項(xiàng)目以供以后重用,從而減輕垃圾收集器(GC)的壓力,下面我們就來(lái)看看具體操作吧2023-10-10讓GPT教你用go語(yǔ)言和C語(yǔ)言開(kāi)發(fā)IDE配置學(xué)習(xí)
這篇文章主要介紹了讓GPT教你用go語(yǔ)言和C語(yǔ)言開(kāi)發(fā)IDE配置學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10提升Go語(yǔ)言開(kāi)發(fā)效率的小技巧實(shí)例(GO語(yǔ)言語(yǔ)法糖)匯總
這篇文章主要介紹了提升Go語(yǔ)言開(kāi)發(fā)效率的小技巧匯總,也就是Go語(yǔ)言的語(yǔ)法糖,掌握好這些可以提高我們的開(kāi)發(fā)效率,需要的朋友可以參考下2022-11-11go程序測(cè)試CPU占用率統(tǒng)計(jì)ps?vs?top兩種不同方式對(duì)比
這篇文章主要為大家介紹了go程序測(cè)試CPU占用率統(tǒng)計(jì)ps?vs?top兩種不同方式對(duì)比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05Go語(yǔ)言學(xué)習(xí)技巧之命名規(guī)范
最近在學(xué)習(xí)go語(yǔ)言,發(fā)現(xiàn)了不少需要整理的知識(shí)點(diǎn),所以整理下分享出來(lái),下面這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言學(xué)習(xí)技巧之命名規(guī)范的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-12-12Golang?中的?strconv?包常用函數(shù)及用法詳解
strconv是Golang中一個(gè)非常常用的包,主要用于字符串和基本數(shù)據(jù)類(lèi)型之間的相互轉(zhuǎn)換,這篇文章主要介紹了Golang中的strconv包,需要的朋友可以參考下2023-06-06