在使用 Golang 進行 HTTP 程式設計時,我們需要經常考慮如何關閉連線。關閉連線可以有效避免資源浪費、提升效能,減少網路問題帶來不必要的麻煩。本文將詳細介紹 Golang 中如何關閉 HTTP 連接,並解析其中的一些細節問題。
一、HTTP 連線的關閉方式
Go 語言中的 HTTP 用戶端和服務端實作了一系列的底層處理來管理 HTTP 連線。這些底層處理通常不會向使用者暴露出來,而是被 HTTP 用戶端和服務端隱藏在內部實作中。那麼在 HTTP 用戶端和服務端中,如何關閉連線呢?
- HTTP 用戶端
在HTTP 用戶端中,我們有幾種方式可以關閉連線:
- 使用defer 關鍵字來手動關閉連線:客戶端呼叫介面後,一般會自動關閉連線。但如果當前客戶端需要多次請求接口,可以考慮手動控制連接關閉,使用defer延遲關閉連接,代碼如下:
package main import ( "net/http" "io/ioutil" "fmt" "log" ) func main() { client := &http.Client{} req, err := http.NewRequest("GET", "http://www.baidu.com", nil) if err != nil { log.Fatal(err) } defer client.CloseIdleConnections() // 当函数返回时释放连接 resp, err := client.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() // 当函数返回时关闭body body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(string(body)[:50]) }
- 使用Transport 類別的MaxIdleConns 或MaxIdleConnsPerHost 來控制連接池中的連線上限:Go 語言的http.Transport 包含了預設的連線池,用於管理HTTP 連線。我們可以使用其 MaxIdleConns 和 MaxIdleConnsPerHost 兩個參數來指定最大空閒連線數和最大空閒主機連線數。當達到這個空閒數時,Transport 會自動關閉多餘的連線。程式碼如下:
package main import ( "net/http" "io/ioutil" "fmt" "log" ) func main() { transport := &http.Transport{ MaxIdleConns: 10, // 最大空闲连接数 MaxIdleConnsPerHost: 3, // 每个域名地址最大空闲连接数 } client := &http.Client{Transport: transport} req, err := http.NewRequest("GET", "http://www.baidu.com", nil) if err != nil { log.Fatal(err) } resp, err := client.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(string(body)[:50]) }
- HTTP 服務端
在 HTTP 服務端中,連線管理通常由伺服器實作自動管理。我們只需要建立伺服器並在不需要使用連接時關閉它。通常情況下,伺服器在處理完一個請求後會自動關閉連線。但有幾種情況比較特殊,需要我們手動控制連線的關閉:
- 在一個HTTP 處理器中使用conn.Close() 關閉連線:在處理器處理HTTP 要求時,如果處理器需要關閉連接,則可以使用conn.Close() 方法關閉連接。程式碼如下:
package main import ( "fmt" "net/http" ) func handler(w http.ResponseWriter, req *http.Request) { // 需要关闭连接时,使用conn.Close() conn, _, _ := w.(http.Hijacker).Hijack() conn.Close() } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) }
- 使用 Keep-Alive:在使用 Keep-Alive 時,連線的生命週期由伺服器管理。伺服器可以定義一個 keep-alive 時間,來控制連線在閒置時間後應關閉。這個時間一般在 HTTP header 中設定。程式碼如下:
package main import ( "log" "net/http" ) func handler(w http.ResponseWriter, req *http.Request) { w.Header().Set("Connection", "keep-alive") // 定义keep-alive时间 w.Write([]byte("hello world")) } func main() { http.HandleFunc("/", handler) log.Fatal(http.ListenAndServe(":8080", nil)) }
二、HTTP 連線的回收機制
當連線使用完畢後,我們需要為連接回收資源,防止資源外洩、效能下降等問題。 HTTP 連線資源的回收機制通常需要考慮以下問題:
- HTTP 長連線的最大存在時間:在連線空閒一段時間後,伺服器會立刻回收這個連線。這個時間可以由伺服器決定,在建立伺服器物件時設定連線逾時時間即可。
- HTTP 連線的最大連線數:在一段時間內,允許連線在連線池中的最大數量。當連接池中出現超出連接池大小的連接時,它們將自動關閉。
- HTTP 連線的複用機制:連線複用是指在同一時間多個請求共用一個連線。這可以減少長時間等待狀態下不必要的資源佔用。但是需要注意的是,如果連線逾時時間較短,可能會導致一次具有網路瞬時性波動的請求失敗,從而影響系統的穩定性。
三、HTTP 連接池的管理
在大型高並發的系統中,我們需要使用連接池來管理 HTTP 連接,以提升系統的效能和穩定性。當呼叫 HTTP 請求時,連線池可以提供一個空閒的網路連線從而避免了頻繁地建立銷毀連線的開銷。連接池通常以常規佇列來管理,以確保最先進入佇列的元素最先被使用,即 FIFO 佇列。以下是使用 Go 語言實作 HTTP 連線池的程式碼:
package main import ( "fmt" "log" "net/http" "sync" "time" ) type MyHttpClient struct { client *http.Client // http客户端对象 Transport *http.Transport // transport对象,用于管理http连接池 } var once sync.Once var myClient *MyHttpClient func GetMyHttpClient() *MyHttpClient { once.Do(func() { myClient = &MyHttpClient{ Transport: &http.Transport{ Dial: func(network, addr string) (net.Conn, error) { conn, err := net.DialTimeout(network, addr, 10*time.Second) if err != nil { return nil, err } return conn, nil }, MaxIdleConns: 100, // 连接池中最多拥有的连接数 MaxIdleConnsPerHost: 2, // 每个域名最多拥有的连接数 IdleConnTimeout: 60 * time.Second, // 连接在闲置多久后被关闭 TLSHandshakeTimeout: 10 * time.Second, // TLS握手时限 ExpectContinueTimeout: 1 * time.Second, // 100-continue超时时限 }, client: &http.Client{}, } }) return myClient } func main() { client := GetMyHttpClient().client req, err := http.NewRequest("GET", "http://www.baidu.com", nil) if err != nil { log.Fatal(err) } defer client.CloseIdleConnections() resp, err := client.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Println(string(body)[:50]) }
四、總結
HTTP 連線的控制和回收是一個關鍵的效能最佳化點。在 Golang 中,我們可以透過手動控制、使用 Transport 類別的參數設定、使用連接池等方式來管理 HTTP 連接,以提升系統的效能和穩定性。除此之外,我們還需要考慮到連接回收機制、HTTP 連接池的管理等問題,以做好系統的維護與最佳化。
以上是golang http 關閉連接的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本文演示了創建模擬和存根進行單元測試。 它強調使用接口,提供模擬實現的示例,並討論最佳實踐,例如保持模擬集中並使用斷言庫。 文章

本文探討了GO的仿製藥自定義類型約束。 它詳細介紹了界面如何定義通用功能的最低類型要求,從而改善了類型的安全性和代碼可重複使用性。 本文還討論了局限性和最佳實踐

本文使用跟踪工具探討了GO應用程序執行流。 它討論了手冊和自動儀器技術,比較諸如Jaeger,Zipkin和Opentelemetry之類的工具,並突出顯示有效的數據可視化

本文討論了GO的反思軟件包,用於運行時操作代碼,對序列化,通用編程等有益。它警告性能成本,例如較慢的執行和更高的內存使用,建議明智的使用和最佳

本文討論了通過go.mod,涵蓋規範,更新和衝突解決方案管理GO模塊依賴關係。它強調了最佳實踐,例如語義版本控制和定期更新。

本文討論了GO中使用表驅動的測試,該方法使用測試用例表來測試具有多個輸入和結果的功能。它突出了諸如提高的可讀性,降低重複,可伸縮性,一致性和A


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。