不過如果web服務(wù)器并且開啟了keep-alive的話,當(dāng)達(dá)到超時時長服務(wù)器也會主動關(guān)閉。(我這里并不是說TCP/IP詳解錯了,而是它在那一節(jié)主要是針對TCP來說,并沒有引入HTTP,而且它說的是通常而不是一定)
我使用Nginx做測試,并且在配置文件中設(shè)置了keepalive_timeout 65s;
,Nginx的默認(rèn)設(shè)置是75s,設(shè)置為0表示禁用keepalive,如下圖:
下面我使用Chrom瀏覽器訪問這個Nginx默認(rèn)提供的主頁,并通過抓包程序來監(jiān)控整個通信過程,如下圖:
從上圖可以看出來在有效數(shù)據(jù)傳送完畢后,中間出現(xiàn)了Keep-Alive標(biāo)記的通信,并且在65秒內(nèi)沒有請求后服務(wù)器主動斷開連接,這種情況你在Nginx的服務(wù)器上就會看到TIME_WAIT的狀態(tài)。
有人說Nginx監(jiān)聽80或者443,客戶端都是連接這個端口,服務(wù)端怎么會端口耗盡呢?就像下圖一樣(忽略圖中的TIME_WAIT,產(chǎn)生這個的原因上面已經(jīng)說過了是因為Nginx的keepalive_timeout設(shè)置導(dǎo)致的)
其實,這取決于Nginx工作模式,我們使用Nginx通常都是讓其工作在代理模式,這就意味著真正的資源或者數(shù)據(jù)在后端Web應(yīng)用程序上,比如Tomcat。代理模式的特點是代理服務(wù)器代替用戶去后端獲取數(shù)據(jù),那么此時相對于后端服務(wù)器來說,Nginx就是一個客戶端,這時候Nginx就會使用隨機端口來向后端發(fā)起請求,而系統(tǒng)可用隨機端口范圍是一定的,可以使用sysctl net.ipv4.ip_local_port_range
命令來查看服務(wù)器上的隨機端口范圍。
通過我們之前介紹的延遲確認(rèn)、Nagle算法以及代理模式下Nginx充當(dāng)后端的客戶端角色并使用隨機端口連接后端,這就意味著服務(wù)端的端口耗盡風(fēng)險是存在的。隨機端口釋放速度如果比與后端建立連接的速度慢就有可能出現(xiàn)。不過一般不會出現(xiàn)這個情況,至少我們公司的Nginx我沒有發(fā)現(xiàn)有這種現(xiàn)象產(chǎn)生。因為首先是靜態(tài)資源都在CDN上;其次后端大部分都是REST接口提供用戶認(rèn)證或者數(shù)據(jù)庫操作,這些操作其實后端如果沒有瓶頸的話基本都很快。不過話說回來如果后端真的有瓶頸且擴容或者改架構(gòu)成本比較高的話,那么當(dāng)面對大量并發(fā)的時候你應(yīng)該做的是限流防止后端被打死。
我們說過HTTP通信依賴TCP連接,一個TCP連接就是一個套接字,對于類Unix系統(tǒng)來說,打開一個套接字就是打開一個文件,如果有100個請求連接服務(wù)端,那么一旦連接建立成功服務(wù)端就會打開100個文件,而Linux系統(tǒng)中一個進(jìn)程可以打開的文件數(shù)量是有限的ulimit -f
,所以如果這個數(shù)值設(shè)置的太小那么也會影響HTTP連接。而對以代理模式運行的Nginx或者其他HTTP程序來說,通常一個連接它就要打開2個套接字也就會占用2個文件(命中Nginx本地緩存或者Nginx直接返回數(shù)據(jù)的除外)。所以對于代理服務(wù)器這個進(jìn)程可打開的文件數(shù)量也要設(shè)置的大一點。
首先我們要知道keepalive可以設(shè)置在2個層面上,且2個層面意義不同。TCP的keepalive是一種探活機制,比如我們常說的心跳信息,表示對方還在線,而這種心跳信息的發(fā)送由有時間間隔的,這就意味著彼此的TCP連接要始終保持打開狀態(tài);而HTTP中的keep-alive是一種復(fù)用TCP連接的機制,避免頻繁建立TCP連接。所以一定明白TCP的Keepalive和HTTP的Keep-alive不是一回事。
非持久連接會在每個HTTP事務(wù)完成后斷開TCP連接,下一個HTTP事務(wù)則會再重新建立TCP連接,這顯然不是一種高效機制,所以在HTTP/1.1以及HTTP/1.0的增強版本中允許HTTP在事務(wù)結(jié)束后將TCP連接保持打開狀態(tài),以便后續(xù)的HTTP事務(wù)可以復(fù)用這個連接,直到客戶端或者服務(wù)器主動關(guān)閉該連接。持久連接減少了TCP連接建立的次數(shù)同時也最大化的規(guī)避了TCP慢啟動帶來的流量限制。
相關(guān)教程:HTTP視頻教程
再來看一下這張圖,圖中的keepalive_timeout 65s
設(shè)置了開啟http的keep-alive特性并且設(shè)置了超時時長為65秒,其實還有比較重要的選項是keepalive_requests 100;
它表示同一個TCP連接最多可以發(fā)起多少個HTTP請求,默認(rèn)是100個。
在HTTP/1.0中keep-alive并不是默認(rèn)使用的,客戶端發(fā)送HTTP請求時必須帶有Connection: Keep-alive
的首部來試圖激活keep-alive,如果服務(wù)器不支持那么將無法使用,所有請求將以常規(guī)形式進(jìn)行,如果服務(wù)器支持那么在響應(yīng)頭中也會包括Connection: Keep-alive
的信息。
在HTTP/1.1中默認(rèn)就使用Keep-alive,除非特別說明,否則所有連接都是持久的。如果要在一個事務(wù)結(jié)束后關(guān)閉連接,那么HTTP的響應(yīng)頭中必須包含Connection: CLose
首部,否則該連接會始終保持打開狀態(tài),當(dāng)然也不能總是打開,也必須關(guān)閉空閑連接,就像上面Nginx的設(shè)置一樣最多保持65秒的空閑連接,超過后服務(wù)端將會主動斷開該連接。
在Linux上沒有一個統(tǒng)一的開關(guān)去開啟或者關(guān)閉TCP的Keepalive功能,查看系統(tǒng)keepalive的設(shè)置sysctl -a | grep tcp_keepalive
,如果你沒有修改過,那么在Centos系統(tǒng)上它會顯示:
net.ipv4.tcp_keepalive_intvl = 75 # 兩次探測直接間隔多少秒 net.ipv4.tcp_keepalive_probes = 9 # 探測頻率 net.ipv4.tcp_keepalive_time = 7200 # 表示多長時間進(jìn)行一次探測,單位秒,這里也就是2小時
按照默認(rèn)設(shè)置,那么上面的整體含義就是2小時探測一次,如果第一次探測失敗,那么過75秒再探測一次,如果9次都失敗就主動斷開連接。
如何開啟Nginx上的TCP層面的Keepalive,在Nginx中有一個語句叫做listen
它是server段里面用于設(shè)置Nginx監(jiān)聽在哪個端口的語句,其實它后面還有其他參數(shù)就是用來設(shè)置套接字屬性的,看下面幾種設(shè)置:
# 表示開啟,TCP的keepalive參數(shù)使用系統(tǒng)默認(rèn)的 listen 80 default_server so_keepalive=on; # 表示顯式關(guān)閉TCP的keepalive listen 80 default_server so_keepalive=off; # 表示開啟,設(shè)置30分鐘探測一次,探測間隔使用系統(tǒng)默認(rèn)設(shè)置,總共探測10次,這里的設(shè) # 置將會覆蓋上面系統(tǒng)默認(rèn)設(shè)置 listen 80 default_server so_keepalive=30m::10;
所以是否要在Nginx上設(shè)置這個so_keepalive,取決于特定場景,千萬不要把TCP的keepalive和HTTP的keepalive搞混淆,因為Nginx不開啟so_keepalive也不影響你的HTTP請求使用keep-alive特性。如果客戶端和Nginx直接或者Nginx和后端服務(wù)器之間有負(fù)載均衡設(shè)備的話而且是響應(yīng)和請求都會經(jīng)過這個負(fù)載均衡設(shè)備,那么你就要注意這個so_keepalive了。比如在LVS的直接路由模式下就不受影響,因為響應(yīng)不經(jīng)過
LVS,不過要是NAT模式就需要留意,因為LVS保持TCP會話也有一個時長,如果該時長小于后端返回數(shù)據(jù)的時長那么LVS就會在客戶端還沒有收到數(shù)據(jù)的情況下斷開這條TCP連接。
TCP擁塞控制有一些算法,其中就包括TCP慢啟動、擁塞避免等算法?
有些地方也叫做IP分片但都是一個意思,至于為什么分片簡單來說就是受限于數(shù)據(jù)鏈路層,不同的數(shù)據(jù)鏈路其MTU不同,以太網(wǎng)的是1500字節(jié),在某些場景會是1492字節(jié);FDDI的MTU又是另外一種大小,單純考慮IP層那么IP數(shù)據(jù)包最大是65535字節(jié)?
在《HTTP權(quán)威指南》P90頁中并沒有說的特別清楚,這種情況是相對于客戶端來說還是服務(wù)端,因為很有可能讓人誤解,當(dāng)然并不是說服務(wù)端不會出現(xiàn)端口耗盡的情況,所以我這里才增加了2項內(nèi)容?
最長不會超過2分鐘?
相關(guān)教程:HTTP視頻教程
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com