http 請求超時 ,你用 golang 是如何解決的?

在 Golang 中,當進行 HTTP 請求時,處理超時是很重要的,尤其在網絡不穩定或服務器響應緩慢的情況下。Golang 提供了靈活的方式來處理 HTTP 請求的超時問題。常見的方式有通過設置http.Client的超時屬性、使用上下文(context.Context)進行超時控制,以及使用自定義的http.Transport

解決 HTTP 請求超時的幾種方式

1. 使用 http.Client 的超時設置

Golang 的 http.Client 有一個 Timeout 字段,可以用來控制整個請求的超時時間。如果該時間內沒有得到響應,請求就會自動取消,並返回超時錯誤。

package main
import (
    "fmt"
    "net/http"
    "time"
)
func main() {
    // 創建一個帶有超時的 HTTP 客戶端
    client := &http.Client{
        Timeout: 5 * time.Second, // 設置請求超時時間爲 5 秒
    }
    // 發起 HTTP GET 請求
    resp, err := client.Get("https://example.com")
    if err != nil {
        fmt.Println("Request failed:", err)
        return
    }
    defer resp.Body.Close()
    fmt.Println("Response status:", resp.Status)
}

2. 使用 context.Context 控制請求超時

context.Context 提供了一種更精細的控制方式,允許對請求的某些部分(如連接、讀取響應等)進行超時控制。

package main
import (
    "context"
    "fmt"
    "net/http"
    "time"
)
func main() {
    // 創建一個帶有 5 秒超時的上下文
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel() // 請求完成後調用 cancel() 釋放資源
    // 創建請求
    req, err := http.NewRequestWithContext(ctx, "GET", "https://example.com", nil)
    if err != nil {
        fmt.Println("Request creation failed:", err)
        return
    }
    // 創建一個 HTTP 客戶端併發送請求
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("Request failed:", err)
        return
    }
    defer resp.Body.Close()
    fmt.Println("Response status:", resp.Status)
}

3. 使用 http.Transport 來控制連接和響應的超時

http.Client 使用了 http.Transport 來管理 HTTP 連接的底層實現,通過設置 http.Transport 可以更細粒度地控制超時行爲,比如設置連接超時、TLS 握手超時、請求響應超時等。

package main
import (
    "fmt"
    "net"
    "net/http"
    "time"
)
func main() {
    // 自定義 HTTP Transport
    transport := &http.Transport{
        DialContext: (&net.Dialer{
            Timeout: 5 * time.Second, // 連接超時時間
        }).DialContext,
        TLSHandshakeTimeout: 5 * time.Second, // TLS 握手超時時間
        IdleConnTimeout:     90 * time.Second, // 空閒連接超時時間
    }
    // 創建帶有自定義 Transport 的 HTTP 客戶端
    client := &http.Client{
        Transport: transport,
        Timeout:   10 * time.Second, // 總超時時間(包括連接、TLS握手、請求和響應)
    }
    // 發起 HTTP GET 請求
    resp, err := client.Get("https://example.com")
    if err != nil {
        fmt.Println("Request failed:", err)
        return
    }
    defer resp.Body.Close()
    fmt.Println("Response status:", resp.Status)
}

常見的 HTTP 請求超時場景

  1. 連接超時:通過DialContext設置連接建立的超時時間,避免因爲網絡連接問題導致的長時間等待。

  2. 讀取超時:通過Timeout字段或上下文控制整體讀取時間,防止服務器長時間不響應導致的阻塞。

  3. 響應時間過長:如果服務器響應過慢(如傳輸數據時延遲過大),可以通過控制http.Client.Timeoutcontext.Context來確保應用不會無限期等待。

總結

在 Golang 中,處理 HTTP 請求超時可以通過以下幾種方式:

根據具體的需求,選擇合適的方式來實現 HTTP 請求的超時處理,可以提高應用的健壯性,避免長時間的阻塞或無響應。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/Hi1qD6HBTa0ZS2pLGBa9Uw