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

Golang中基于HTTP協(xié)議的網(wǎng)絡(luò)服務(wù)

 更新時間:2023年04月13日 11:22:44   作者:鯤鵬飛九萬里  
HTTP協(xié)議是基于TCP/IP協(xié)議棧的,并且它也是一個面向普通文本的協(xié)議。這篇文章主要詳細(xì)介紹了Golang中基于HTTP協(xié)議的網(wǎng)絡(luò)服務(wù),感興趣的小伙伴可以借鑒一下

一、HTTP協(xié)議的網(wǎng)絡(luò)服務(wù)

HTTP協(xié)議是基于TCP/IP協(xié)議棧的,并且它也是一個面向普通文本的協(xié)議。

只要搞清楚了HTTP請求的報文(報文的頭部(header)和主體(body))應(yīng)該包含的內(nèi)容,使用任何一個文本編譯器,就餓可以編寫一個完整的HTTP請求報文。

在這種情況下,直接使用net.Dial函數(shù),就可以。

使用net/http代碼包中的程序?qū)嶓w,可以更便捷的訪問基于HTTP協(xié)議的網(wǎng)絡(luò)服務(wù)。其中最便捷的是使用http.Get函數(shù)。

1.1 使用http.Get函數(shù)訪問HTTP協(xié)議的網(wǎng)絡(luò)服務(wù)

package main

import (
	"fmt"
	"net/http"
)

func main() {
	url1 := "http://www.google.cn/"
	fmt.Printf("Send request to %q with method GET ... \n", url1)
	response1, err := http.Get(url1)
	if err != nil {
		fmt.Printf("request sending error: %v\n", err)
	}
	defer response1.Body.Close()
	line1 := response1.Proto + " " + response1.Status
	fmt.Printf("The first line of response: \n %s \n", line1)
}

http.Get函數(shù)會返回兩個結(jié)果值:

  • 第一個結(jié)果值的類型是*http.Response,它是網(wǎng)絡(luò)服務(wù)給我們傳回來的響應(yīng)內(nèi)容的結(jié)構(gòu)化表示。
  • 第二個結(jié)果值是error類型。它代表了在創(chuàng)建和發(fā)送HTTP請求,以及接受和解析HTTP響應(yīng)的過程中可能發(fā)生的錯誤。

http.Get函數(shù)內(nèi)部會使用缺省的HTTP客戶端,并調(diào)用它的Get方法以完成功能。缺省客戶端類型是*http.Client,由公開變量DefaultClient代表。

1.2 使用缺省客戶端DefaultClient(類型為*http.Client )

package main

import (
	"fmt"
	"net/http"
)

func main() {
	url1 := "http://www.google.cn/"
	fmt.Printf("Send request to %q with method GET ... \n", url1)
	// response1, err := http.Get(url1)
	response1, err := http.DefaultClient.Get(url1)
	if err != nil {
		fmt.Printf("request sending error: %v\n", err)
	}
	defer response1.Body.Close()
	line1 := response1.Proto + " " + response1.Status
	fmt.Printf("The first line of response: \n %s \n", line1)
}

它的基本類型(http.Client)可以開箱即用。

1.3 使用http.Client訪問HTTP協(xié)議的網(wǎng)絡(luò)服務(wù)

package main

import (
	"fmt"
	"net/http"
)

func main() {
	url1 := "http://www.google.cn/"
	fmt.Printf("Send request to %q with method GET ... \n", url1)
	// response1, err := http.Get(url1)
	// response1, err := http.DefaultClient.Get(url1)
	var oneClient http.Client
	response1, err := oneClient.Get(url1)
	if err != nil {
		fmt.Printf("request sending error: %v\n", err)
	}
	defer response1.Body.Close()
	line1 := response1.Proto + " " + response1.Status
	fmt.Printf("The first line of response: \n %s \n", line1)
}

http.Client是一個結(jié)構(gòu)體類型,并且它包含的字段是公開的。之所以該類型的零值仍然可以使用,是因為它的這些字段要么存在著響應(yīng)的缺省值,要么其零值直接可以使用,且代表著特定的含義。

二、http.Client中的Transport字段

http.Client類型中的Transport字段代表著:向網(wǎng)絡(luò)服務(wù)發(fā)送HTTP請求,并從網(wǎng)絡(luò)服務(wù)接收HTTP響應(yīng)的操作過程。

Transport字段的RoundTrip方法實現(xiàn)單次HTTP事務(wù)(或者說基于HTTP協(xié)議的單詞交互)需要的所有步驟。

 Transport 字段是http.RoundTrip接口類型,它有一個缺省值,這個缺省值的變量名為DefaultTransport。DefaultTransport的實際類型為*http.Transport,*http.Transport可以被復(fù)用,并且是線程安全的。

如果沒有顯式的為http.Client中的Transport字段賦值,這個Client就會直接使DefaultTransport。

 http.Client中的Timeout字段,代表前面所說的單詞HTTP事務(wù)的超時時間,它time.Duration類型,它的零值是可用的,用于表示沒有設(shè)置超時時間。

(1)http.Transport類型中的DialContext字段

http.Transport類型,在內(nèi)部使用一個net.Dialer類型的值,并且會把該值的Timeout字段的值,設(shè)定為30秒。

也就是說,這個Dialer值如果在30秒內(nèi)還沒有建立好網(wǎng)絡(luò)連接,那么就會被判定為操作超時。

在DefaultTransport的值被初始化的時候,這樣的Dialer值的DialContext方法會被賦給前者DialContext字段:

var DefaultTransport RoundTripper = &Transport{
	Proxy: ProxyFromEnvironment,
	DialContext: defaultTransportDialContext(&net.Dialer{
		Timeout:   30 * time.Second,
		KeepAlive: 30 * time.Second,
	}),
	ForceAttemptHTTP2:     true,
	MaxIdleConns:          100,
	IdleConnTimeout:       90 * time.Second,
	TLSHandshakeTimeout:   10 * time.Second,
	ExpectContinueTimeout: 1 * time.Second,
}

func defaultTransportDialContext(dialer *net.Dialer) func(context.Context, string, string) (net.Conn, error) {
	return dialer.DialContext
}

KeepAlive的背后是一種針對網(wǎng)絡(luò)連接(更確切地說,是TCP連接)的存活探測機制。它的值用于表示每隔多長時間發(fā)送一次探測包。當(dāng)該值不大于0時,則表示不開啟這種機制。

DefaultTransport會把這個字段的值設(shè)定為30秒。

(2)http.Transport類型中的其它字段

一些是關(guān)于超時操作

  • IdleConnTimeout:含義是空閑的連接在多久之后就應(yīng)該關(guān)閉。

 DefaultTransport 會把該字段的值設(shè)定為90秒。

如果該值為0,那么就表示不關(guān)閉空閑連接。注意,這樣可能會造成資源的泄露。

  • ResponseHeaderTimeout:含義是,從客戶端把請求完全遞交給操作系統(tǒng)到從操作系統(tǒng)那里接收到響應(yīng)報文頭到最長時長。

 DefaultTransport并沒有設(shè)定該字段的值。

  •  ExpectContinueTimeout:含義是,在客戶端提交了請求報文頭之后,等待接收第一個響應(yīng)報文頭的最長時間。

 DefaultTransport 把該字段的值設(shè)定為1秒。

在客戶端想要使用HTTP的“POST”方法把一個很大的報文體發(fā)送給服務(wù)端的時候,它可以先通過發(fā)送一個包含了“Expect: 100-continue”的請求報文頭,來詢問服務(wù)端是否愿意接受這個大報文體。這個字段就是用于設(shè)定在這種情況下的超時時間的。

注意,如果該字段的值不大于0,那么無論多大的請求報文體都將會被立即發(fā)送出去。

TLSHandshakeTimeout:TLS是Transport Layer Security 的縮寫,可以被翻譯為傳輸層安全。這個字段代表了基于TLS協(xié)議的連接在被建立時的握手階段的超時時間。

DefaultTransport 把該字段的值設(shè)置為10秒。

若該值為0,則表示對這個值不設(shè)限。

一些與IdleConnTimeout相關(guān)的字段值

  • MaxIdleConns:用于控制訪問所有主機的最大空閑連接。如果為0,不做限制。

DefaultTransport 把MaxIdleConns設(shè)定為100。

MaxIdleConns字段只會對空閑連接的總數(shù)做出限定。

  • MaxIdleConnsPerHost: 控制Transport值訪問每一個網(wǎng)絡(luò)服務(wù)的最大空閑連接數(shù)。如果為0,將使用缺省值2, 這個缺省值由DefaultMaxIdleConnsPerHost所代表。

也就是說,默認(rèn)情況下,對于某一個Transport值訪問的每一個網(wǎng)絡(luò)服務(wù),它的空閑連接數(shù)都最多只能由兩個。

  • MaxConnsPerHost:針對某一個Transport值訪問的每一個網(wǎng)絡(luò)服務(wù)的最大連接數(shù),不論這些連接是否是空閑的。

該字段沒有缺省值,零值表示不限定。

MaxIdleConns和MaxIdleConnsPerHost兩個與空閑連接數(shù)有關(guān)的字段的值應(yīng)該是聯(lián)動的,所以,有時需要根據(jù)實際情況定制它們,可以參考DefaultTransport變量的聲明。

三、為什么會出現(xiàn)空閑的連接

3.1 空閑連接的產(chǎn)生

HTTP協(xié)議有一個請求報文頭,叫做“Connection”。在HTTP協(xié)議的1.1 版本中,這個報文頭的值默認(rèn)是“keep-alive”。

在這種情況下,網(wǎng)絡(luò)連接都是持久連接,它們會在當(dāng)前的HTTP事務(wù)完成后仍然保持著連通性,因此是可以被復(fù)用的。

連接的可復(fù)用,帶來兩種可能:

  • 一種可能是,針對同一個網(wǎng)絡(luò)服務(wù),有新的HTTP請求被提交,該連接被再次使用。
  • 另一種可能是,不再有對該網(wǎng)絡(luò)服務(wù)的HTTP請求,該連接被閑置。(產(chǎn)生空閑的連接)

后一種情況就產(chǎn)生了空閑連接。另外,如果分配給某一個網(wǎng)絡(luò)服務(wù)的連接過多的話,也可能會導(dǎo)致空閑連接的產(chǎn)生。因為每一個新遞交的HTTP請求,都只會征用一個空閑的連接。所以,為空閑連接設(shè)定限制,在大多數(shù)情況下都是很有必要的,也是需要斟酌的。

3.2 杜絕空閑連接的產(chǎn)生

如果想徹底杜絕空閑連接的產(chǎn)生,那么可以在初始化的時候,把它的DisableKeepAlives字段的值設(shè)定為true。這時,HTTP請求的“Connection”報文頭的值就會被設(shè)置為“close”。這會告訴網(wǎng)絡(luò)服務(wù),這個網(wǎng)絡(luò)連接不必保持,當(dāng)前的HTTP事務(wù)完成后就可以斷開它。

如此一來,每當(dāng)一個HTTP請求被遞交時,就會產(chǎn)生一個新的網(wǎng)絡(luò)連接。這樣做會明顯地加重網(wǎng)絡(luò)服務(wù)以及客戶端的負(fù)載。所以,在一般情況下,我們都不要去設(shè)置這個DisableKeepAlive字段。

在net.Dialer類型中,也有一個看起來很相似的字段KeepAlive。不過,它與前面所說的HTTP 持久連接不是一個概念,KeepAlive是直接作用在底層的socket上的。

KeepAlive的背后是一種針對網(wǎng)絡(luò)連接(更確切地說,是TCP連接)的存活探測機制。它的值用于表示每隔多長時間發(fā)送一次探測包。當(dāng)該值不大于0時,則表示不開啟這種機制。DefaultTransport會把這個字段的值設(shè)定為30秒。

四、http.Server

http.Server類型與http.Client相對應(yīng)。http.Server代表的是基于HTTP協(xié)議的服務(wù)端,或者網(wǎng)絡(luò)服務(wù)。

4.1 http.Server類型的ListenAndServe方法

http.Server類型的ListenAndServe方法的功能是:監(jiān)聽一個基于TCP協(xié)議的網(wǎng)絡(luò)地址,并對接收到的HTTP請求進行處理。

  • 這個方法默認(rèn)會開啟針對網(wǎng)絡(luò)連接的存活探測機制,以保證連接是持久的。
  • 同時,該方法會一直執(zhí)行,直到有嚴(yán)重的錯誤發(fā)生或被外界關(guān)掉。

當(dāng)被外界關(guān)掉時,它會返回一個由http.ErrServerClosed變量代表的錯誤值。

4.2 ListenAndServe方法主要做的事情

func (srv *Server) ListenAndServe() error {
	if srv.shuttingDown() {
		return ErrServerClosed
	}
	addr := srv.Addr
	if addr == "" {
		addr = ":http"
	}
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	return srv.Serve(ln)
}

ListenAndServe方法主要會做下面的事情:

  • 檢查當(dāng)前的http.Server類型的值的Addr字段。

該字段的值代表了當(dāng)前的網(wǎng)絡(luò)服務(wù)需要使用的網(wǎng)絡(luò)地址。即:IP地址和端口號。如果這個字段的值為空字符串,那么就用":http"代替。

也就是說,使用任何可以代表本機的域名和IP地址,并且端口號為80.

  • 通過調(diào)用net.Listen函數(shù)在已確定的網(wǎng)絡(luò)地址上啟動基于TCP協(xié)議的監(jiān)聽。
  • 檢查net.Listen 函數(shù)返回的錯誤值。

如果該錯誤值不為nil,那么就直接返回該值。否則,通過調(diào)用當(dāng)前值的Serve方法準(zhǔn)備接受和處理將要到來的HTTP請求。

4.3 (衍生問題)net.Listen 函數(shù)都做了哪些事情

net.Listen函數(shù)做的事情:

  • 解析參數(shù)值中包含的網(wǎng)絡(luò)地址隱含的IP地址和端口號;
  • 根據(jù)給定的網(wǎng)絡(luò)協(xié)議,確定監(jiān)聽的方法,并開始進行監(jiān)聽;

這里還可以延伸到net.socket函數(shù),以及socket相關(guān)的知識。

4.4 (衍生問題)http.Server類型的Serve方法是怎么接受和處理HTTP請求的

在一個for循環(huán)中,網(wǎng)絡(luò)監(jiān)聽的Accept方法會被不斷的調(diào)用,

	for {
		rw, err := l.Accept()
  }

該方法會返回兩個結(jié)果值:

  • 第一個結(jié)果值是net.Conn 類型,代表包含了新到來的HTTP請求的網(wǎng)絡(luò)連接;
  • 第二個結(jié)果值是error類型值,代表可能發(fā)生的錯誤。

如果錯誤不為nil,除非它代表了一個暫時性的錯誤,否則循環(huán)都會被終止。如果是暫時性的錯誤,那么循環(huán)的下一次迭代將會在一段時間之后開始執(zhí)行。

如果這里的Accept方法沒有返回非nil的錯誤值,那么這里的程序?qū)阉牡谝粋€結(jié)果值包裝成一個*http.conn類型的值,然后通過在新的goroutine中調(diào)用這個*http.conn 類型值的serve方法,來對當(dāng)前的HTTP請求進行處理。

HTTP請求相關(guān)的,更多的衍生問題:

  • 這個*http.conn類型值的狀態(tài)有幾種,分別代表著處理的哪個階段?
  • 處理的過程中會用到哪些讀取器和寫入器,它們的作用分別是什么?
  • 這里的程序是怎么調(diào)用我們自定義的處理函數(shù)的?

五、思考:怎么優(yōu)雅地停止基于HTTP協(xié)議的網(wǎng)絡(luò)服務(wù)程序?

srv.Shutdown(context.Background()) 的方式停止服務(wù),通過RegisterOnShutdown可添加服務(wù)停止時的調(diào)用。

以上就是Golang中基于HTTP協(xié)議的網(wǎng)絡(luò)服務(wù)的詳細(xì)內(nèi)容,更多關(guān)于Golang HTTP協(xié)議的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • GO語言延遲函數(shù)defer用法詳解

    GO語言延遲函數(shù)defer用法詳解

    本文主要介紹了GO語言延遲函數(shù)defer用法詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • 一文帶你掌握Go語言中文件的寫入操作

    一文帶你掌握Go語言中文件的寫入操作

    這篇文章主要和大家分享一下Go語言中文件的寫入操作,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Go語言有一定的幫助,需要的小伙伴可以參考一下
    2022-12-12
  • go slice不同初始化方式性能及數(shù)組比較詳解

    go slice不同初始化方式性能及數(shù)組比較詳解

    這篇文章主要為大家介紹了go slice不同初始化方式性能及數(shù)組比較示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • 揭秘Go Json.Unmarshal精度丟失之謎

    揭秘Go Json.Unmarshal精度丟失之謎

    我們知道在json反序列化時是沒有整型和浮點型的區(qū)別,數(shù)字都使用同一種類型,在go語言的類型中這種共同類型就是float64,下面我們就來探討一下Json.Unmarshal精度丟失之謎吧
    2023-08-08
  • 深入探索Go?1.21中的?maps工具庫

    深入探索Go?1.21中的?maps工具庫

    隨著?Go?1.21.0?版本的發(fā)布,新增了兩個實用的泛型工具庫:maps?和?slices,下面小編就帶大家一起學(xué)習(xí)一下?maps?工具庫的相關(guān)知識吧
    2023-08-08
  • golang文件讀取-按指定BUFF大小讀取方式

    golang文件讀取-按指定BUFF大小讀取方式

    這篇文章主要介紹了golang文件讀取-按指定BUFF大小讀取方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go語言讀取文本文件的三種方式總結(jié)

    Go語言讀取文本文件的三種方式總結(jié)

    工作中時不時需要讀取文本,文本文件是最常見的文件類型。本文將利用Go語言從逐行、逐個單詞和逐個字符三個方法讀取文件,感興趣的可以了解一下
    2023-01-01
  • 一文教你打造一個簡易的Golang日志庫

    一文教你打造一個簡易的Golang日志庫

    這篇文章主要為大家詳細(xì)介紹了如何使用不超過130行的代碼,通過一系列g(shù)olang的特性,來打造一個簡易的golang日志庫,感興趣的小伙伴可以了解一下
    2023-06-06
  • 線上golang grpc服務(wù)資源泄露問題排查

    線上golang grpc服務(wù)資源泄露問題排查

    這篇文章主要介紹了線上golang grpc服務(wù)資源泄露問題排查,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Go 切片導(dǎo)致內(nèi)存泄露的幾種原因

    Go 切片導(dǎo)致內(nèi)存泄露的幾種原因

    某些情況下,對一個已存在的切片或數(shù)組進行切分操作可能會導(dǎo)致內(nèi)存泄漏,本文主要介紹了Go 切片導(dǎo)致內(nèi)存泄露的幾種原因,感興趣的可以了解一下
    2023-05-05

最新評論

达孜县| 大同县| 卓资县| 永吉县| 岳池县| 普洱| 永川市| 东乌珠穆沁旗| 庄河市| 保康县| 原阳县| 吴忠市| 西吉县| 晴隆县| 中江县| 婺源县| 开封县| 海盐县| 顺义区| 赤峰市| 柳林县| 疏附县| 嘉峪关市| 秦皇岛市| 辉县市| 廊坊市| 育儿| 孝感市| 辽阳市| 呈贡县| 周口市| 张掖市| 凤庆县| 河西区| 乐山市| 博野县| 博白县| 环江| 灵武市| 平定县| 旺苍县|