005_關於HTTP協議中的保持連接
緣起
中午在群裏討論,用ab
測試 一臺只提供靜態文件服務, 不與其他任何系統交互的時候,為什麽也會產生大量的TIME WAIT
狀態的。
首先,我們可以簡單的理解,在TCP連接的兩端,誰主動斷開連接(先發送FIN
包),誰進入TIME WAIT
,誰被動斷開連接(後發送FIN
包),誰進入CLOSE WAIT
狀態。
那麽,由此可以推斷,在這個場景中,server是主動斷開連接的一方,那麽server為什麽會主動斷開呢, 這就涉及到HTTP裏關於keepalive的內容了。
我們常常聽說keepalive
能提高webserver的性能, 但是為什麽呢? 這裏暫且不解釋,說完下面的內容,就清楚了。
分析
在HTTP協議中, 除了需要服務器支持並打開keepalive之外, 還有一個重要的請求頭Connection
我們來看下面一個請求:
GET /? HTTP/1.1
Accept: */*
Cache-Control: no-cache
Connection: close
Host: 127.0.0.1
User-Agent: Apache-HttpClient/4.3.2 (java 1.5)
Accept-Encoding: gzip,deflate
這是我通過Idea 的REST Client 插件發送的一個請求, 我們看到 Connection
頭的值是close
,抓包看一下請求過程
可以看到, 在server響應完成後, 發送了FIN
包, 主動斷開連接, 這很好理解。
在來看一個請求:
GET /? HTTP/1.1 Accept: */* Cache-Control: no-cache Connection: keep-alive Keep-Alive: 5 Host: 127.0.0.1 User-Agent: Apache-HttpClient/4.3.2 (java 1.5) Accept-Encoding: gzip,deflate
可以看到, 這個請求裏, Connection
的值變成了keep-alive
, 並且多了一個Keep-Alive
頭,值為5。再抓包看看這次請求:
可以看到, server在響應完成後,並沒有發送FIN
包關閉連接, 而是一段時間後,客戶端發送FIN
包,關閉連接, 如果你看第二列, time會發現,正好是大約5秒後,客戶端發送了FIN
包, 這個數值正好是 Keep-Alive
頭的值。事實上,Keep-Alive
頭的語義就是客戶端保持連接多少秒。
以上的測試, server配的keepalive都是65s
, 我們來把它0, 再來測試一遍看看。
客戶端Connection
頭為close
的情況:
客戶端Connection
keep-alive
, Keep-Alive
為5
的情況
可以看到,server主動斷開連接。
最後一個場景, server配置keepalive
為3, client Connection
為keep-alive
, Keep-Alive
為5
的情況
可以看到,請求結束大約3
秒後(主要時間戳),server發送FIN
主動斷開連接。
結論
說了這麽多,是時候總結一下了,關於keepalive主要有一下幾點:
Connection
頭控制客戶端是否開啟,close
不開啟,keep-alive
開啟Keep-Alive
頭控制客戶端保持連接的時間- 在開啟
keepalive
的時候, 誰先到保持連接的時間,誰先發FIN
包,主動關閉連接。
005_關於HTTP協議中的保持連接