自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

有關(guān)Http持久連接的一切,卷給你看

網(wǎng)絡(luò) 通信技術(shù)
HTTP Keep-Alive 是在應(yīng)用層對(duì)TCP連接進(jìn)行滑動(dòng)續(xù)約復(fù)用, 如果客戶端/服務(wù)器穩(wěn)定續(xù)約,就成了名副其實(shí)的長(zhǎng)連接。

[[438351]]

上文中我的結(jié)論是: HTTP Keep-Alive 是在應(yīng)用層對(duì)TCP連接進(jìn)行滑動(dòng)續(xù)約復(fù)用, 如果客戶端/服務(wù)器穩(wěn)定續(xù)約,就成了名副其實(shí)的長(zhǎng)連接。

目前所有的Http網(wǎng)絡(luò)庫都默認(rèn)開啟了HTTP Keep-Alive,今天我們從底層TCP連接和排障角度撕碎HTTP持久連接。

“我只是一個(gè)寫web程序的猿,我為什么要知道這么多??????”。

使用go語言倒騰一個(gè)httpServer/httpClient,粗略聊一聊go的使用風(fēng)格。

使用go語言net/http包快速搭建httpserver,注入用于記錄請(qǐng)求日志的Handler

  1. package main 
  2.  
  3. import ( 
  4.  "fmt" 
  5.  "log" 
  6.  "net/http" 
  7.  
  8. // IndexHandler記錄請(qǐng)求的基本信息: 請(qǐng)關(guān)注r.RemoteAddr 
  9. func Index(w http.ResponseWriter, r *http.Request) { 
  10.  fmt.Println("receive a request from:", r.RemoteAddr, r.Header) 
  11.  w.Write([]byte("ok")) 
  12.  
  13. // net/http 默認(rèn)開啟持久連接 
  14. func main() {  
  15.  fmt.Printf("Starting server at port 8081\n"
  16.  if err := http.ListenAndServe(":8081", http.HandlerFunc(Index)); err != nil { 
  17.   log.Fatal(err) 
  18.  } 

ListenAndServe創(chuàng)建了默認(rèn)的httpServer服務(wù)器,go通過首字母大小寫來控制訪問權(quán)限,如果首字母大寫,則可以被外部包訪問, 類比C#全局函數(shù)、靜態(tài)函數(shù)。

  1. func ListenAndServe(addr string, handler Handler) error { 
  2.  server := &Server{Addr: addr, Handler: handler} 
  3.  return server.ListenAndServe() 

net/http服務(wù)器默認(rèn)開啟了Keep-Alive, 由Server的私有變量disableKeepAlives體現(xiàn)。

  1. type  Server  struct { 
  2.   ... 
  3.   disableKeepAlives int32     // accessed atomically.  
  4.   ... 

使用者也可以手動(dòng)關(guān)閉Keep-Alive, SetKeepAlivesEnabled()會(huì)修改私有變量disableKeepAlives的值

  1. s := &http.Server{ 
  2.   Addr:           ":8081"
  3.   Handler: http.HandlerFunc(Index), 
  4.   ReadTimeout:    10 * time.Second
  5.   WriteTimeout:   10 * time.Second
  6.   MaxHeaderBytes: 1 << 20, 
  7.  } 
  8.  s.SetKeepAlivesEnabled(true
  9.  if err := s.ListenAndServe(); err != nil { 
  10.   log.Fatal(err) 
  11.  } 

以上也是go語言包的基本制作/使用風(fēng)格。

請(qǐng)注意我在httpserver插入了IndexHander,記錄httpclient的基本信息。

這里有個(gè)知識(shí)點(diǎn):如果httpclient建立新的TCP連接,系統(tǒng)會(huì)按照一定規(guī)則給你分配隨機(jī)端口。

啟動(dòng)服務(wù)器程序,瀏覽器訪問localhost:8081,

服務(wù)器會(huì)收到如下日志, 圖中紅圈處表明瀏覽器使用了系統(tǒng)隨機(jī)的固定端口建立tcp連接。

使用net/http編寫客戶端:間隔1s向服務(wù)器發(fā)起HTTP請(qǐng)求

  1. package main 
  2.  
  3. import ( 
  4.  "fmt" 
  5.  "io/ioutil" 
  6.  "log" 
  7.  "net/http" 
  8.  "time" 
  9.  
  10. func main() { 
  11.  client := &http.Client{ 
  12.   Timeout: 10 * time.Second
  13.  } 
  14.  for { 
  15.   requestWithClose(client) 
  16.   time.Sleep(time.Second * 1) 
  17.  } 
  18.  
  19. func requestWithClose(client *http.Client) { 
  20.  
  21.  resp, err := client.Get("http://127.0.0.1:8081"
  22.  
  23.  if err != nil { 
  24.   fmt.Printf("error occurred while fetching page, error: %s", err.Error()) 
  25.   return 
  26.  } 
  27.  defer resp.Body.Close() 
  28.  
  29.  c, err := ioutil.ReadAll(resp.Body) 
  30.  if err != nil { 
  31.   log.Fatalf("Couldn't parse response body. %+v", err) 
  32.  } 
  33.  
  34.  fmt.Println(string(c)) 

服務(wù)器收到的請(qǐng)求日志如下:

圖中紅框顯示httpclient使用固定端口61799發(fā)起了http請(qǐng)求,客戶端/服務(wù)器維持了HTTP Keep-alive。

使用netstat -an | grep 127.0.0.1:8081可圍觀系統(tǒng)針對(duì)特定ip的TCP連接:客戶端系統(tǒng)中針對(duì) 服務(wù)端也只建立了一個(gè)tcp連接,tcp連接的端口是61799,與上文呼應(yīng)。

使用Wireshark查看localhost網(wǎng)卡發(fā)生的tcp連接

可以看到每次http請(qǐng)求/響應(yīng)之前均沒有tcp三次握手

tcp每次發(fā)包后,對(duì)端需要回ACK確認(rèn)包

反面教材-高能預(yù)警

go的net/http明確提出:

If the Body is not both read to EOF and closed, the Client's underlying RoundTripper (typically Transport) may not be able to re-use a persistent TCP connection to the server for a subsequent "keep-alive" request.

也就是說:httpclient客戶端在每次請(qǐng)求結(jié)束后,如果不讀完body或者沒有關(guān)閉body, 可能會(huì)導(dǎo)致Keep-alive失效,也會(huì)導(dǎo)致goroutine泄露。

  1. //  下面的代碼沒有讀完body,導(dǎo)致Keep-alive失效 
  2. func requestWithClose(client *http.Client) { 
  3.    resp, err := client.Get("http://127.0.0.1:8081"
  4.    if err != nil { 
  5.     fmt.Printf("error occurred while fetching page, error: %s", err.Error()) 
  6.     return 
  7.    } 
  8.    defer resp.Body.Close() 
  9.    //_, err = ioutil.ReadAll(resp.Body) 
  10.    fmt.Println("ok"

此次服務(wù)端日志如下:

上圖紅框顯示客戶端持續(xù)使用新的隨機(jī)端口建立了TCP連接。

查看客戶端系統(tǒng)建立的tcp連接:

Wireshark抓包結(jié)果:

圖中紅框顯示每次HTTP請(qǐng)求/響應(yīng) 前后均發(fā)生了三次握手、四次揮手。

全文梳理

目前已知的httpclient、httpServer均默認(rèn)開啟keep-alive

禁用keep-alive或者keep-alive失效,會(huì)導(dǎo)致客戶端、服務(wù)器頻繁建立tcp連接, 可通過 netstat -an | grep {ip} 查看客戶機(jī)上建立的tcp連接

 

Wireshark抓包, 明確keep-alive和非Keep-alive的抓包效果

 

責(zé)任編輯:武曉燕 來源: 精益碼農(nóng)
相關(guān)推薦

2022-04-02 09:38:00

CSS3flex布局方式

2022-04-27 09:28:11

HTTPExpires

2019-08-01 07:56:43

安全數(shù)據(jù)網(wǎng)絡(luò)安全安全分析

2017-12-30 00:23:10

容器開源

2017-12-29 10:29:34

HTTP驅(qū)動(dòng)程序

2018-01-09 20:35:11

Swift編程語言

2019-08-20 09:24:54

Python編程語言Java

2012-12-31 11:22:58

開源開放

2020-09-11 10:55:10

useState組件前端

2011-04-11 10:14:09

服務(wù)器虛擬化

2018-06-13 12:22:37

康普智能樓宇智慧建筑

2017-03-23 14:51:21

HTTP緩存CDN緩存

2021-02-28 09:47:54

軟件架構(gòu)軟件開發(fā)軟件設(shè)計(jì)

2017-09-29 16:39:33

2017-03-23 15:05:50

HTTP緩存Cookie

2018-11-23 11:17:24

負(fù)載均衡分布式系統(tǒng)架構(gòu)

2021-02-19 23:08:27

軟件測(cè)試軟件開發(fā)

2015-08-21 09:56:15

物聯(lián)網(wǎng)

2016-08-31 17:24:05

大數(shù)據(jù)分析

2021-11-07 23:41:39

Windows 11Windows微軟
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)