欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語言的http/2服務(wù)器功能及客戶端使用

 更新時間:2018年09月10日 15:15:51   投稿:daisy  
Golang 有一個很棒的自帶 http 服務(wù)器軟件包,不用說就是: net/http, 它非常簡單,但是功能非常強(qiáng)大。下面這篇文章主要給大家介紹了關(guān)于Go語言的http/2服務(wù)器功能及客戶端使用的相關(guān)資料,需要的朋友可以參考下

前言

大家都知道,Go的標(biāo)準(zhǔn)庫HTTP服務(wù)器默認(rèn)支持HTTP/2。那么,在這篇文章中,我們將首先展示Go的http/2服務(wù)器功能,并解釋如何將它們作為客戶端使用。

在這篇文章中,我們將首先展示Go的http/2服務(wù)器功能,并解釋如何將它們作為客戶端使用。Go的標(biāo)準(zhǔn)庫HTTP服務(wù)器默認(rèn)支持HTTP/2。

下面話不多說了,來一起看看詳細(xì)的介紹吧

HTTP/2 服務(wù)器

首先,讓我們在Go中創(chuàng)建一個http/2服務(wù)器!根據(jù)http/2文檔,所有東西都是為我們自動配置的,我們甚至不需要導(dǎo)入Go的標(biāo)準(zhǔn)庫http2包:

HTTP/2強(qiáng)制使用TLS。為了實(shí)現(xiàn)這一點(diǎn),我們首先需要一個私鑰和一個證書。在Linux上,下面的命令執(zhí)行這個任務(wù)。

openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.crt

該命令將生成兩個文件:server.key 以及 server.crt

現(xiàn)在,對于服務(wù)器代碼,以最簡單的形式,我們將使用Go的標(biāo)準(zhǔn)庫HTTP服務(wù)器,并啟用TLS與生成的SSL文件。

package main

import (
 "log"
 "net/http"
)
 
func main() {
 // 在 8000 端口啟動服務(wù)器
 // 確切地說,如何運(yùn)行HTTP/1.1服務(wù)器。

 srv := &http.Server{Addr:":8000", Handler: http.HandlerFunc(handle)}
 // 用TLS啟動服務(wù)器,因?yàn)槲覀冞\(yùn)行的是http/2,它必須是與TLS一起運(yùn)行。
 // 確切地說,如何使用TLS連接運(yùn)行HTTP/1.1服務(wù)器。
 log.Printf("Serving on https://0.0.0.0:8000")
 log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key"))
}

func handle(w http.ResponseWriter, r *http.Request) {
 // 記錄請求協(xié)議
 log.Printf("Got connection: %s", r.Proto)
 // 向客戶發(fā)送一條消息
 w.Write([]byte("Hello"))
}

HTTP/2 客戶端

在go中,標(biāo)準(zhǔn) http.Client 也用于http/2請求。惟一的區(qū)別是在客戶端的Transport字段,使用 http2.Transport 代替 http.Transport。

我們生成的服務(wù)器證書是“自簽名”的,這意味著它不是由一個已知的證書頒發(fā)機(jī)構(gòu)(CA)簽署的。這將導(dǎo)致我們的客戶端不相信它:

package main

import (
 "fmt"
 "net/http"
)

const url = "https://localhost:8000"

func main() {
 _, err := http.Get(url)
 fmt.Println(err)
}

讓我們試著運(yùn)行它:

$ go run h2-client.go 
Get https://localhost:8000: x509: certificate signed by unknown authority

在服務(wù)器日志中,我們還將看到客戶端(遠(yuǎn)程)有一個錯誤:

http: TLS handshake error from [::1]:58228: remote error: tls: bad certificate

為了解決這個問題,我們可以用定制的TLS配置去配置我們的客戶端。我們將把服務(wù)器證書文件添加到客戶端“證書池”中,因?yàn)槲覀冃湃嗡?,即使它不是由已知CA簽名的。

我們還將添加一個選項(xiàng),根據(jù)命令行標(biāo)志在HTTP/1.1和HTTP/2傳輸之間進(jìn)行選擇。

package main

import (
 "crypto/tls"
 "crypto/x509"
 "flag"
 "fmt"
 "io/ioutil"
 "log"
 "net/http"
 "golang.org/x/net/http2"
)
 
const url = "https://localhost:8000"

var httpVersion = flag.Int("version", 2, "HTTP version")

func main() {
 flag.Parse()
 client := &http.Client{}
 // Create a pool with the server certificate since it is not signed
 // by a known CA
 caCert, err := ioutil.ReadFile("server.crt")
 if err != nil {
 log.Fatalf("Reading server certificate: %s", err)
 }
 caCertPool := x509.NewCertPool()
 caCertPool.AppendCertsFromPEM(caCert)
 // Create TLS configuration with the certificate of the server
 tlsConfig := &tls.Config{
 RootCAs: caCertPool,
 }

 // Use the proper transport in the client
 switch *httpVersion {
 case 1:
 client.Transport = &http.Transport{
 TLSClientConfig: tlsConfig,
 }
 case 2:
 client.Transport = &http2.Transport{
 TLSClientConfig: tlsConfig,
 }
 }
 // Perform the request
 resp, err := client.Get(url)

 if err != nil {
 log.Fatalf("Failed get: %s", err)
 }
 defer resp.Body.Close()
 body, err := ioutil.ReadAll(resp.Body)
 if err != nil {
 log.Fatalf("Failed reading response body: %s", err)
 }
 fmt.Printf(
 "Got response %d: %s %s\n",
 resp.StatusCode, resp.Proto, string(body)
 )
}

這一次我們得到了正確的回應(yīng):

$ go run h2-client.go 
Got response 200: HTTP/2.0 Hello

在服務(wù)器日志中,我們將看到正確的日志線:獲得連接:Got connection: HTTP/2.0!!
但是當(dāng)我們嘗試使用HTTP/1.1傳輸時,會發(fā)生什么呢?

$ go run h2-client.go -version 1
Got response 200: HTTP/1.1 Hello

我們的服務(wù)器對HTTP/2沒有任何特定的東西,所以它支持HTTP/1.1連接。這對于向后兼容性很重要。此外,服務(wù)器日志表明連接是HTTP/1.1:Got connection: HTTP/1.1。

HTTP/2 高級特性

我們創(chuàng)建了一個HTTP/2客戶機(jī)-服務(wù)器連接,并且我們正在享受安全有效的連接帶來的好處。但是HTTP/2提供了更多的特性,讓我們來研究它們!

服務(wù)器推送

HTTP/2允許服務(wù)器推送“使用給定的目標(biāo)構(gòu)造一個合成請求”。
這可以很容易地在服務(wù)器處理程序中實(shí)現(xiàn)(在github上的視圖):

func handle(w http.ResponseWriter, r *http.Request) {
 // Log the request protocol
 log.Printf("Got connection: %s", r.Proto)
 // Handle 2nd request, must be before push to prevent recursive calls.
 // Don't worry - Go protect us from recursive push by panicking.
 if r.URL.Path == "/2nd" {
 log.Println("Handling 2nd")
 w.Write([]byte("Hello Again!"))
 return
 }

 // Handle 1st request
 log.Println("Handling 1st")
 // Server push must be before response body is being written.
 // In order to check if the connection supports push, we should use
 // a type-assertion on the response writer.
 // If the connection does not support server push, or that the push
 // fails we just ignore it - server pushes are only here to improve
 // the performance for HTTP/2 clients.
 pusher, ok := w.(http.Pusher)

 if !ok {
 log.Println("Can't push to client")
 } else {
 err := pusher.Push("/2nd", nil)
  if err != nil {
 log.Printf("Failed push: %v", err)
 }
 }
 // Send response body
 w.Write([]byte("Hello"))
}

使用服務(wù)器推送

讓我們重新運(yùn)行服務(wù)器,并測試客戶機(jī)。

對于HTTP / 1.1客戶端:

$ go run ./h2-client.go -version 1
Got response 200: HTTP/1.1 Hello

服務(wù)器日志將顯示:

Got connection: HTTP/1.1Handling 1st
Can't push to client

HTTP/1.1客戶端傳輸連接產(chǎn)生一個 http.ResponseWriter 沒有實(shí)現(xiàn)http.Pusher,這是有道理的。在我們的服務(wù)器代碼中,我們可以選擇在這種客戶機(jī)的情況下該做什么。

對于HTTP/2客戶:

go run ./h2-client.go -version 2
Got response 200: HTTP/2.0 Hello

服務(wù)器日志將顯示:

Got connection: HTTP/2.0Handling 1st
Failed push: feature not supported

這很奇怪。我們的HTTP/2傳輸?shù)目蛻舳酥坏玫搅说谝粋€“Hello”響應(yīng)。日志表明連接實(shí)現(xiàn)了 http.Pusher 接口——但是一旦我們實(shí)際調(diào)用 Push() 函數(shù)——它就失敗了。

排查發(fā)現(xiàn),HTTP/2客戶端傳輸設(shè)置了一個HTTP/2設(shè)置標(biāo)志,表明推送是禁用的。

因此,目前沒有選擇使用Go客戶機(jī)來使用服務(wù)器推送。

作為一個附帶說明,google chrome作為一個客戶端可以處理服務(wù)器推送。

服務(wù)器日志將顯示我們所期望的,處理程序被調(diào)用兩次,路徑 / 和 /2nd,即使客戶實(shí)際上只對路徑 /:

Got connection: HTTP/2.0Handling 1st
Got connection: HTTP/2.0Handling 2nd

全雙工通信

Go HTTP/2演示頁面有一個echo示例,它演示了服務(wù)器和客戶機(jī)之間的全雙工通信。

讓我們先用CURL來測試一下:

$ curl -i -XPUT --http2 https://http2.golang.org/ECHO -d hello
HTTP/2 200 
content-type: text/plain; charset=utf-8
date: Tue, 24 Jul 2018 12:20:56 GMT

HELLO 

我們把curl配置為使用HTTP/2,并將一個PUT/ECHO發(fā)送給“hello”作為主體。服務(wù)器以“HELLO”作為主體返回一個HTTP/2 200響應(yīng)。但我們在這里沒有做任何復(fù)雜的事情,它看起來像是一個老式的HTTP/1.1半雙工通信,有不同的頭部。讓我們深入研究這個問題,并研究如何使用HTTP/2全雙工功能。

服務(wù)器實(shí)現(xiàn)

下面是HTTP echo處理程序的簡化版本(不使用響應(yīng))。它使用 http.Flusher 接口,HTTP/2添加到http.ResponseWriter。

type flushWriter struct {
 w io.Writer
}

func (fw flushWriter) Write(p []byte) (n int, err error) {
 n, err = fw.w.Write(p)
 // Flush - send the buffered written data to the client
 if f, ok := fw.w.(http.Flusher); ok {
 f.Flush()
 }
  return
}

func echoCapitalHandler(w http.ResponseWriter, r *http.Request) {
 // First flash response headers
 if f, ok := w.(http.Flusher); ok {
 f.Flush()
 }
 // Copy from the request body to the response writer and flush
 // (send to client)
 io.Copy(flushWriter{w: w}, r.Body)
}

服務(wù)器將從請求正文讀取器復(fù)制到寫入ResponseWriter和 Flush() 的“沖洗寫入器”。同樣,我們看到了笨拙的類型斷言樣式實(shí)現(xiàn),沖洗操作將緩沖的數(shù)據(jù)發(fā)送給客戶機(jī)。

請注意,這是全雙工,服務(wù)器讀取一行,并在一個HTTP處理程序調(diào)用中重復(fù)寫入一行。

GO客戶端實(shí)現(xiàn)

我試圖弄清楚一個啟用了HTTP/2的go客戶端如何使用這個端點(diǎn),并發(fā)現(xiàn)了這個Github問題。提出了類似于下面的代碼。

const url = "https://http2.golang.org/ECHO"

func main() {
  // Create a pipe - an object that implements `io.Reader` and `io.Writer`. 
  // Whatever is written to the writer part will be read by the reader part.

  pr, pw := io.Pipe() 
  // Create an `http.Request` and set its body as the reader part of the
  // pipe - after sending the request, whatever will be written to the pipe,
  // will be sent as the request body.  // This makes the request content dynamic, so we don't need to define it
  // before sending the request.
 req, err := http.NewRequest(http.MethodPut, url, ioutil.NopCloser(pr))

 if err != nil {
 log.Fatal(err)
 }
 
  // Send the request
 resp, err := http.DefaultClient.Do(req) if err != nil {
   log.Fatal(err)
   }
 log.Printf("Got: %d", resp.StatusCode) 
 // Run a loop which writes every second to the writer part of the pipe
 // the current time.
 go func() { for { 
 time.Sleep(1 * time.Second)
 fmt.Fprintf(pw, "It is now %v\n", time.Now())
 }
 }() 

  // Copy the server's response to stdout.
 _, err = io.Copy(os.Stdout, res.Body)

 log.Fatal(err)
}

總結(jié)

Go支持與服務(wù)器推送和全雙工通信的HTTP/2連接,這也支持HTTP/1.1與標(biāo)準(zhǔn)庫的標(biāo)準(zhǔn)TLS服務(wù)器的連接——這太不可思議了。對于標(biāo)準(zhǔn)的庫HTTP客戶端,它不支持服務(wù)器推送,但是支持標(biāo)準(zhǔn)庫的標(biāo)準(zhǔn)HTTP的全雙工通信。以上就是本篇的內(nèi)容,大家有什么疑問可以在文章下面留言溝通。

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • Golang實(shí)現(xiàn)http server提供壓縮文件下載功能

    Golang實(shí)現(xiàn)http server提供壓縮文件下載功能

    這篇文章主要介紹了Golang實(shí)現(xiàn)http server提供壓縮文件下載功能,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Go 協(xié)程超時控制的實(shí)現(xiàn)

    Go 協(xié)程超時控制的實(shí)現(xiàn)

    本文主要介紹了Go 協(xié)程超時控制的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Golang優(yōu)雅保持main函數(shù)不退出的辦法

    Golang優(yōu)雅保持main函數(shù)不退出的辦法

    很多時候我們需要讓main函數(shù)不退出,讓它在后臺一直執(zhí)行,下面這篇文章主要給大家介紹了關(guān)于Golang優(yōu)雅保持main函數(shù)不退出的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • Golang交叉編譯之跨平臺編譯使用詳解

    Golang交叉編譯之跨平臺編譯使用詳解

    這篇文章主要為大家介紹了Golang交叉編譯之跨平臺編譯使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • go-cqhttp環(huán)境配置及安裝過程

    go-cqhttp環(huán)境配置及安裝過程

    這篇文章主要介紹了go-cqhttp環(huán)境配置,包括go-cqhttp安裝及簡單介紹,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-09-09
  • GoLang RabbitMQ TTL與死信隊(duì)列以及延遲隊(duì)列詳細(xì)講解

    GoLang RabbitMQ TTL與死信隊(duì)列以及延遲隊(duì)列詳細(xì)講解

    這篇文章主要介紹了GoLang RabbitMQ TTL與死信隊(duì)列以及延遲隊(duì)列,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-12-12
  • 三種Golang數(shù)組拷貝的實(shí)現(xiàn)方式與性能分析

    三種Golang數(shù)組拷貝的實(shí)現(xiàn)方式與性能分析

    在?Golang?中,有多種方式可以進(jìn)行數(shù)組的拷貝,本文將對其中的三種方式進(jìn)行性能分析,并比較它們的優(yōu)缺點(diǎn),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-06-06
  • 使用Go語言開發(fā)短鏈接服務(wù)的方法

    使用Go語言開發(fā)短鏈接服務(wù)的方法

    短鏈接一般是通過映射關(guān)系,將長長的一串網(wǎng)址,映射到幾個字符的短鏈接上,建立好這種映射關(guān)系之后保存到數(shù)據(jù)庫里,用戶每次訪問短鏈接的時候,這篇文章主要介紹了使用Go語言開發(fā)一個短鏈接服務(wù),需要的朋友可以參考下
    2024-03-03
  • Go語言內(nèi)置包的使用

    Go語言內(nèi)置包的使用

    本文主要介紹了Go語言內(nèi)置包的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Golang線上內(nèi)存爆掉問題排查(pprof)與解決

    Golang線上內(nèi)存爆掉問題排查(pprof)與解決

    這篇文章主要介紹了Golang線上內(nèi)存爆掉問題排查(pprof)與解決,涉及到數(shù)據(jù)敏感,文中代碼是我模擬線上故障的一個情況,好在我們程序都有添加pprof監(jiān)控,于是直接通過go tool pprof分析,需要的朋友可以參考下
    2024-04-04

最新評論