最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go?net?http超時應(yīng)用場景全面詳解

 更新時間:2024年01月04日 11:27:57   作者:Go語言教程  
HTTP是一個復(fù)雜的多階段協(xié)議,因此沒有一個一刀切的超時解決方案,在這篇文章中,我將分解您可能需要應(yīng)用超時的各個階段,并研究在服務(wù)器端和客戶端上執(zhí)行超時的不同方法

一、前言

在Go中編寫HTTP服務(wù)器或客戶端時,超時是最容易出錯、最微妙的事情之一:有很多選擇,錯誤在很長一段時間內(nèi)都不會產(chǎn)生任何后果,直到網(wǎng)絡(luò)出現(xiàn)故障,進(jìn)程掛起。

二、超時時間

2.1 SetDeadline

首先,您需要了解Go為實現(xiàn)超時而公開的網(wǎng)絡(luò)原語:Deadlines。

由net.Conn使用Set[Read|Write]Deadline(time.time)方法公開,Deadlines是一個絕對時間,當(dāng)達(dá)到該時間時,所有I/O操作都會失敗并出現(xiàn)超時錯誤。

Deadlines不是超時。一旦設(shè)置,它們將永遠(yuǎn)有效(或直到下一次調(diào)用SetDeadline),無論在此期間是否以及如何使用連接。因此,要使用SetDeadline構(gòu)建超時,您必須在每次讀/寫操作之前調(diào)用它。

您可能不想自己調(diào)用SetDeadline,而是讓net/http使用其更高級別的超時為您調(diào)用它。但是,請記住所有超時都是根據(jù)Deadlines實現(xiàn)的,因此它們不會在每次發(fā)送或接收數(shù)據(jù)時重置。

2.2 Server Timeouts

因此你想在互聯(lián)網(wǎng)上公開Go的帖子發(fā)現(xiàn)更多關(guān)于服務(wù)器超時的信息,特別是關(guān)于HTTP/2和Go 1.7錯誤的信息:

對于暴露在Internet上的HTTP服務(wù)器來說,強(qiáng)制客戶端連接超時是至關(guān)重要的。否則,速度非常慢或正在消失的客戶端可能會泄漏文件描述符,并最終導(dǎo)致以下情況:

http: Accept error: accept tcp [::]:80: accept4: 
too many open files; retrying in 5ms

在http.Server中公開了兩個超時:ReadTimeout和WriteTimeout。您可以通過顯式使用服務(wù)器來設(shè)置它們:

srv := &http.Server{
    ReadTimeout: 5 * time.Second,
    WriteTimeout: 10 * time.Second,
}
log.Println(srv.ListenAndServe())

ReadTimeout涵蓋了從接受連接到完全讀取請求正文的時間(如果您確實讀取了正文,否則到標(biāo)頭末尾)。它是通過在Accept之后立即調(diào)用SetReadDeadline在net/http中實現(xiàn)的。

WriteTimeout通常通過在readRequest結(jié)束時調(diào)用SetWriteDeadline來覆蓋從請求標(biāo)頭讀取結(jié)束到響應(yīng)寫入結(jié)束的時間(也稱為ServeHTTP的生存期)。

但是,當(dāng)連接是HTTPS時,在Accept之后會立即調(diào)用SetWriteDeadline,以便它也覆蓋作為TLS握手一部分寫入的數(shù)據(jù)包。令人煩惱的是,這意味著(僅在這種情況下)WriteTimeout最終包括頭讀取和第一個字節(jié)等待。

當(dāng)你處理不受信任的客戶端和/或網(wǎng)絡(luò)時,你應(yīng)該設(shè)置這兩個超時,這樣客戶端就不會因為寫或讀速度慢而中斷連接。

最后是http.TimeoutHandler。它不是Server參數(shù),而是一個限制ServeHTTP調(diào)用最長持續(xù)時間的Handler包裝器。它的工作方式是緩沖響應(yīng),如果超過最后期限,則發(fā)送504網(wǎng)關(guān)超時。請注意,它在1.6中被提出,在1.6.2中。

三、http.ListenAndServe 做的是錯誤的

順便說一句,這意味著繞過http.Server的包級便利功能,如http.ListenAndServe、http.Listen AndServeTLS和http.Serve,不適合公共Internet服務(wù)器。

這些函數(shù)將Tmeouts保留為默認(rèn)的off值,無法啟用它們,因此如果使用它們,很快就會出現(xiàn)連接泄漏和文件描述符用完的情況。我至少犯過六次這個錯誤。

相反,使用ReadTimeout和WriteTimeout創(chuàng)建一個http.Server實例,并使用其相應(yīng)的方法,就像上面幾段中的示例一樣。

3.1 streaming

非常令人惱火的是,沒有辦法從ServeHTTP訪問底層的net.Conn,因此打算流式傳輸響應(yīng)的服務(wù)器被迫取消設(shè)置WriteTimeout(這也可能是它們默認(rèn)為0的原因)。這是因為如果沒有net.Conne訪問,就無法在每次寫入之前調(diào)用SetWriteDeadline來實現(xiàn)適當(dāng)?shù)目臻e(而不是絕對)超時。

此外,無法取消被阻止的ResponseWriter.Write,因為沒有記錄ResponseWriter.Close(您可以通過接口升級訪問)來取消阻止并發(fā)寫入。因此,也沒有辦法用Timer手動構(gòu)建超時。

可悲的是,這意味著流媒體服務(wù)器無法真正保護(hù)自己免受慢速閱讀客戶端的攻擊。

3.2 Client Timeouts

客戶端超時可能更簡單,也可能更復(fù)雜,這取決于您使用的超時,但對于防止資源泄漏或陷入困境同樣重要。

最容易使用的是http.Client的Timeout字段。它涵蓋了整個交換,從Dial(如果不重用連接)到讀取主體。

c := &http.Client{
    Timeout: 15 * time.Second,
}
resp, err := c.Get("https://blog.filippo.io/")

與上面的服務(wù)器端案例一樣,包級別的函數(shù)(如http.Get請求客戶端在沒有超時的情況下使用,因此在開放式互聯(lián)網(wǎng)上使用是危險的。

為了進(jìn)行更精細(xì)的控制,您可以設(shè)置許多其他更具體的超時

  • net.Dialer.Timeout限制建立TCP連接所花費的時間(如果需要新的連接)。
  • http.Transport.TLS握手超時限制執(zhí)行TLS握手所花費的時間
  • http.Transport.ResponseHeaderTimeout限制讀取響應(yīng)標(biāo)頭所花費的時間。
  • http.Transport.ExpectContinueTimeout限制客戶端在發(fā)送包含Expect:100 continue的請求標(biāo)頭和接收發(fā)送正文的批準(zhǔn)之間等待的時間。
c := &http.Client{
    Transport: &http.Transport{
        Dial: (&net.Dialer{
                Timeout:   30 * time.Second,
                KeepAlive: 30 * time.Second,
        }).Dial,
        TLSHandshakeTimeout:   10 * time.Second,
        ResponseHeaderTimeout: 10 * time.Second,
        ExpectContinueTimeout: 1 * time.Second,
    }
}

據(jù)我所知,沒有辦法具體限制發(fā)送請求所花費的時間。讀取請求正文所花費的時間可以通過time.Timer手動控制,因為它發(fā)生在Client方法返回之后(有關(guān)如何取消請求,請參閱下文)。

最后,1.7中新增了http.Transport.IdleConnTimeout。它不控制客戶端請求的阻塞階段,而是控制空閑連接在連接池中保持的時間。

請注意,客戶端默認(rèn)情況下會遵循重定向。http.Client.Timeout包括重定向后花費的所有時間,而細(xì)粒度超時是針對每個請求的,因為http.Transport是一個沒有重定向概念的較低級別系統(tǒng)。

3.3 Cancel and Context

nethttp提供了兩種取消客戶端請求的方法:request.cancel和1.7中新增的Context。

Request.Cancel是一個可選通道,當(dāng)設(shè)置并關(guān)閉時,會導(dǎo)致請求中止,就像達(dá)到Request.Timeout一樣。(它們實際上是通過相同的機(jī)制實現(xiàn)的,在寫這篇文章時,我在1.7中發(fā)現(xiàn)了一個錯誤,所有取消都會作為超時錯誤返回。)

我們可以使用Request.Cancel和time.Timer來構(gòu)建一個更精細(xì)的超時,允許流式傳輸,每次我們成功從Body讀取一些數(shù)據(jù)時都會將截止日期向后推:

package main
import (
  "io"
  "io/ioutil"
  "log"
  "net/http"
  "time"
)
func main() {
  c := make(chan struct{})
  timer := time.AfterFunc(5*time.Second, func() {
    close(c)
  })
        // Serve 256 bytes every second.
  req, err := http.NewRequest("GET", "http://httpbin.org/range/2048?duration=8&chunk_size=256", nil)
  if err != nil {
    log.Fatal(err)
  }
  req.Cancel = c
  log.Println("Sending request...")
  resp, err := http.DefaultClient.Do(req)
  if err != nil {
    log.Fatal(err)
  }
  defer resp.Body.Close()
  log.Println("Reading body...")
  for {
    timer.Reset(2 * time.Second)
                // Try instead: timer.Reset(50 * time.Millisecond)
    _, err = io.CopyN(ioutil.Discard, resp.Body, 256)
    if err == io.EOF {
      break
    } else if err != nil {
      log.Fatal(err)
    }
  }
}

在上面的例子中,我們在請求的Do階段設(shè)置了5秒的超時,但隨后讀取正文,每次超時2秒??梢杂肋h(yuǎn)這樣流媒體,而不會有陷入困境的風(fēng)險。如果在超過2秒的時間內(nèi)沒有收到正文數(shù)據(jù),那么io.CopyN將返回net/http:requestcancelled。

在1.7中,上下文包升級為標(biāo)準(zhǔn)庫。關(guān)于上下文有很多需要學(xué)習(xí)的地方,但就目的而言,您應(yīng)該知道它們會取代和棄用Request.Cancel。

要使用Contexts取消請求,我們只需獲取一個新的Context及其帶有Context.WithCancel的cancel()函數(shù),并使用request.WithContext創(chuàng)建一個綁定到它的request。當(dāng)我們想取消請求時,我們通過調(diào)用cancel來取消Context:

ctx, cancel := context.WithCancel(context.TODO())
timer := time.AfterFunc(5*time.Second, func() {
  cancel()
})
req, err := http.NewRequest("GET", "http://httpbin.org/range/2048?duration=8&chunk_size=256", nil)
if err != nil {
  log.Fatal(err)
}
req = req.WithContext(ctx)

以上就是Go net http超時應(yīng)用場景全面詳解的詳細(xì)內(nèi)容,更多關(guān)于Go net http超時的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 9個Golang中map常用示例分享

    9個Golang中map常用示例分享

    這篇文章主要和大家分享9個Golang中map可能是常用的使用案例,從1到9,越來越厲害。文中的示例代碼講解詳細(xì),希望對大家學(xué)習(xí)Golang有一定的幫助
    2023-02-02
  • 利用Go語言實現(xiàn)簡單Ping過程的方法

    利用Go語言實現(xiàn)簡單Ping過程的方法

    相信利用各種語言實現(xiàn)Ping已經(jīng)是大家喜聞樂見的事情了,網(wǎng)絡(luò)上利用Golang實現(xiàn)Ping已經(jīng)有比較詳細(xì)的代碼示例,但大多是僅僅是實現(xiàn)了Request過程,而對Response的回顯內(nèi)容并沒有做接收。而Ping程序不僅僅是發(fā)送一個ICMP,更重要的是如何接收并進(jìn)行統(tǒng)計。
    2016-09-09
  • Go代碼檢查的推薦工具及使用詳解

    Go代碼檢查的推薦工具及使用詳解

    這篇文章主要為大家介紹了Go代碼檢查的推薦工具及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • golang切片拷貝的實現(xiàn)

    golang切片拷貝的實現(xiàn)

    在Golang中,切片的淺拷貝只復(fù)制指向?qū)ο蟮闹羔?而深拷貝則復(fù)制數(shù)據(jù)本身,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-10-10
  • 創(chuàng)建第一個Go語言程序Hello,Go!

    創(chuàng)建第一個Go語言程序Hello,Go!

    這篇文章主要介紹了創(chuàng)建第一個Go語言程序Hello,Go!本文詳細(xì)的給出項目創(chuàng)建、代碼編寫的過程,同時講解了GOPATH、Go install等內(nèi)容,需要的朋友可以參考下
    2014-10-10
  • 如何在Go中使用Casbin進(jìn)行訪問控制

    如何在Go中使用Casbin進(jìn)行訪問控制

    這篇文章主要介紹了如何在Go中使用Casbin進(jìn)行訪問控制,Casbin是一個強(qiáng)大的、高效的開源訪問控制框架,其權(quán)限管理機(jī)制支持多種訪問控制模型,Casbin只負(fù)責(zé)訪問控制
    2022-08-08
  • 詳解golang RWMutex讀寫互斥鎖源碼分析

    詳解golang RWMutex讀寫互斥鎖源碼分析

    這篇文章主要介紹了詳解golang RWMutex讀寫互斥鎖源碼分析,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-06-06
  • Go中Context使用源碼解析

    Go中Context使用源碼解析

    這篇文章主要為大家介紹了Go中Context使用源碼解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • go與go mod命令使用方式以及遇到的問題

    go與go mod命令使用方式以及遇到的問題

    這篇文章主要介紹了go與go mod命令使用方式以及遇到的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Go Asynq異步任務(wù)處理的實現(xiàn)

    Go Asynq異步任務(wù)處理的實現(xiàn)

    Asynq是一個新興的異步任務(wù)處理解決方案,它提供了輕量級的、易于使用的API,本文主要介紹了Go Asynq異步任務(wù)處理的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2023-06-06

最新評論

民县| 闽清县| 吉木乃县| 抚顺市| 甘南县| 乐昌市| 平邑县| 山丹县| 平山县| 芜湖市| 科技| 岢岚县| 玛纳斯县| 泸水县| 云霄县| 本溪| 游戏| 自贡市| 和林格尔县| 玉田县| 武隆县| 鱼台县| 云和县| 中西区| 乐陵市| 扎囊县| 建昌县| 报价| 若尔盖县| 宁城县| 罗山县| 禄丰县| 洪洞县| 汝南县| 伊春市| 郑州市| 田东县| 黎川县| 志丹县| 综艺| 辽宁省|