使用Singleflight實現(xiàn)Golang代碼優(yōu)化
介紹
有許多方法可以優(yōu)化代碼以提高效率,減少運行進程就是其中之一。在本文中,我們將看到如何通過使用一個Go包Singleflight來減少重復(fù)進程,從而優(yōu)化Go代碼。
問題
假設(shè)你有一個web應(yīng)用,它每秒有10個請求(RPS)。根據(jù)您所知道的數(shù)據(jù),其中一些請求具有相同的模式,實際上可以生成相同的結(jié)果,這意味著實際上存在冗余流程。
從上面的插圖中,我們知道用戶1和用戶2想要相同的東西,但最終,我們(大多數(shù)情況下)分別處理這兩個請求。
解決方案
Singleflight是可以解決這類問題的Go包之一,如文檔中所述,它提供了重復(fù)函數(shù)調(diào)用抑制機制。
很酷,如果我們知道我們要調(diào)用的函數(shù)是重復(fù)的,我們就可以減少處理的函數(shù)的數(shù)量,讓我們看看在現(xiàn)實世界中如何使用它。
實現(xiàn)
我們將創(chuàng)建兩個程序,server.go
和 client.go
。
server.go — 將作為web服務(wù),可以接收 /api/v1/get_something
的請求,參數(shù)名為name
// server.go package main import ( "fmt" "net/http" ) func main() { http.HandleFunc("/api/v1/get_something", func(w http.ResponseWriter, r *http.Request) { name := r.URL.Query().Get("name") response := processingRequest(name) _, _ = fmt.Fprint(w, response) }) err := http.ListenAndServe(":15001", nil) if err != nil { fmt.Println(err) } } func processingRequest(name string) string { fmt.Println("[DEBUG] processing request..") return "Hi there! You requested " + name }
client.go — 將作為一個客戶端,向web服務(wù)發(fā)出5個并發(fā)請求(你可以在變量totalRequests中設(shè)置這個數(shù)字)。
// client.go package main import ( "io" "log" "net/http" "sync" ) func main() { var wg sync.WaitGroup endpoint := "http://localhost:15001/api/v1/get_something?name=something" totalRequests := 5 for i := 0; i < totalRequests; i++ { wg.Add(1) go func(i int) { defer wg.Done() makeAPICall(endpoint) }(i) } wg.Wait() } func makeAPICall(endpoint string) { resp, err := http.Get(endpoint) if err != nil { log.Fatalln(err) } body, err := io.ReadAll(resp.Body) if err != nil { log.Fatalln(err) } result := string(body) log.Printf(result) }
首先,我們可以運行 server.go,然后繼續(xù)執(zhí)行 client.go。我們將在服務(wù)器腳本的終端中看到如下內(nèi)容:
[DEBUG] processing request..
[DEBUG] processing request..
[DEBUG] processing request..
[DEBUG] processing request..
[DEBUG] processing request..
客戶端的輸出是這樣的:
2023/09/05 10:29:34 Hi there! You requested something
2023/09/05 10:29:34 Hi there! You requested something
2023/09/05 10:29:34 Hi there! You requested something
2023/09/05 10:29:34 Hi there! You requested something
2023/09/05 10:29:34 Hi there! You requested something
這是正確的,因為我們從客戶端發(fā)送了五個請求,并在服務(wù)器中處理了這五個請求。
現(xiàn)在讓我們在代碼中實現(xiàn)Singleflight
,這樣它會更有效率。
// server.go package main import ( "fmt" "net/http" "golang.org/x/sync/singleflight" ) var g = singleflight.Group{} func main() { http.HandleFunc("/api/v1/get_something", func(w http.ResponseWriter, r *http.Request) { name := r.URL.Query().Get("name") response, _, _ := g.Do(name, func() (interface{}, error) { result := processingRequest(name) return result, nil }) _, _ = fmt.Fprint(w, response) }) err := http.ListenAndServe(":15001", nil) if err != nil { fmt.Println(err) } } func processingRequest(name string) string { fmt.Println("[DEBUG] processing request..") return "Hi there! You requested " + name }
重新啟動服務(wù)器并再次運行客戶端程序后,服務(wù)器的終端顯示如下:
[DEBUG] processing request..
[DEBUG] processing request..
客戶端的輸出還是沒有變化:
2023/09/05 10:32:49 Hi there! You requested something
2023/09/05 10:32:49 Hi there! You requested something
2023/09/05 10:32:49 Hi there! You requested something
2023/09/05 10:32:49 Hi there! You requested something
2023/09/05 10:32:49 Hi there! You requested something
太好了!所有客戶端都得到了預(yù)期的響應(yīng),但是現(xiàn)在我們的服務(wù)器只處理了兩個請求。想象一下,如果您處理數(shù)千個類似的請求,您將帶來多大的效率,這是驚人的!
結(jié)論
在本文中,我們了解了Singleflight
在優(yōu)化代碼方面的強大功能。不僅僅是處理一個web
請求,你還可以將它的用例擴展到其他事情上,比如從數(shù)據(jù)庫中獲取數(shù)據(jù)等等。
還有一些我在本文中沒有涉及的內(nèi)容,例如Singleflight
的過程失敗會怎樣,以及我們?nèi)绾尉彺嫠?/p>
以上就是使用Singleflight實現(xiàn)Golang代碼優(yōu)化的詳細內(nèi)容,更多關(guān)于go Singleflight代碼優(yōu)化的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
go中string、int、float相互轉(zhuǎn)換的實現(xiàn)示例
本文主要介紹了go中string、int、float相互轉(zhuǎn)換的實現(xiàn)示例,文中根據(jù)實例編碼詳細介紹的十分詳盡,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03golang中g(shù)in框架接入jwt使用token驗證身份
本文主要介紹了golang中g(shù)in框架接入jwt使用token驗證身份,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12