HTTP Keep-Alive 学习
面試某家互聯(lián)網(wǎng)公司時,問道HTTP中Keep-Alive,平時經(jīng)常會在http 頭文件看到?
Connection:
keep-alive, 但要我講它的用途,確實(shí)不知道!
以下是介紹HTTP中Keep-Alive的文章,轉(zhuǎn)自?現(xiàn)代魔法學(xué)院
?
- section 01?HTTP Keep-Alive是什么?如何工作?
HTTP Keep-Alive
在http早期,每個http請求都要求打開一個tpc socket連接,并且使用一次之后就斷開這個tcp連接。
使用keep-alive可以改善這種狀態(tài),即在一次TCP連接中可以持續(xù)發(fā)送多份數(shù)據(jù)而不會斷開連接。通過使用keep-alive機(jī)制,可以減少tcp連接建立次數(shù),也意味著可以減少TIME_WAIT狀態(tài)連接,以此提高性能和提高h(yuǎn)ttpd服務(wù)器的吞吐率(更少的tcp連接意味著更少的系統(tǒng)內(nèi)核調(diào)用,socket的accept()和close()調(diào)用)。
但是,keep-alive并不是免費(fèi)的午餐,長時間的tcp連接容易導(dǎo)致系統(tǒng)資源無效占用。配置不當(dāng)?shù)膋eep-alive,有時比重復(fù)利用連接帶來的損失還更大。所以,正確地設(shè)置keep-alive timeout時間非常重要。
keepalvie timeout
Httpd守護(hù)進(jìn)程,一般都提供了keep-alive timeout時間設(shè)置參數(shù)。比如nginx的keepalive_timeout,和Apache的KeepAliveTimeout。這個keepalive_timout時間值意味著:一個http產(chǎn)生的tcp連接在傳送完最后一個響應(yīng)后,還需要hold住keepalive_timeout秒后,才開始關(guān)閉這個連接。
當(dāng)httpd守護(hù)進(jìn)程發(fā)送完一個響應(yīng)后,理應(yīng)馬上主動關(guān)閉相應(yīng)的tcp連接,設(shè)置 keepalive_timeout后,httpd守護(hù)進(jìn)程會想說:”再等等吧,看看瀏覽器還有沒有請求過來”,這一等,便是keepalive_timeout時間。如果守護(hù)進(jìn)程在這個等待的時間里,一直沒有收到瀏覽發(fā)過來http請求,則關(guān)閉這個http連接。
下面寫一個腳本,方便測試:
| 1 | sleep(60);??//為了便于分析測試,會根據(jù)測試進(jìn)行調(diào)整 |
| 2 | echo?"www.example.com"; |
1. 當(dāng)keepalive_timeout時間為0時,即不啟用Keep-Alive時,一個tcp連接的生命周期:
| 01 | #tcpdump -n host 218.1.57.236 and port 80 |
| 02 | 20:36:50.792731 IP 218.1.57.236.43052 > 222.73.211.215.http: S 1520902589:1520902589(0) win 65535 |
| 03 | 20:36:50.792798 IP 222.73.211.215.http > 218.1.57.236.43052: S 290378256:290378256(0) ack 1520902590 win 5840 |
| 04 | 20:36:50.801629 IP 218.1.57.236.43052 > 222.73.211.215.http: . ack 1 win 32768 |
| 05 | ? |
| 06 | 20:36:50.801838 IP 218.1.57.236.43052 > 222.73.211.215.http: P 1:797(796) ack 1 win 32768 |
| 07 | 20:36:50.801843 IP 222.73.211.215.http > 218.1.57.236.43052: . ack 797 win 59 |
| 08 | ? |
| 09 | 20:37:50.803230 IP 222.73.211.215.http > 218.1.57.236.43052: P 1:287(286) ack 797 win 59 |
| 10 | 20:37:50.803289 IP 222.73.211.215.http > 218.1.57.236.43052: F 287:287(0) ack 797 win 59 |
| 11 | 20:37:50.893396 IP 218.1.57.236.43052 > 222.73.211.215.http: . ack 288 win 32625 |
| 12 | 20:37:50.894249 IP 218.1.57.236.43052 > 222.73.211.215.http: F 797:797(0) ack 288 win 32625 |
| 13 | 20:37:50.894252 IP 222.73.211.215.http > 218.1.57.236.43052: . ack 798 win 59 |
- 第1~3行建立tcp三次握手,建立連接。用時8898μs
- 第4~5行通過建立的連接發(fā)送第一個http請求,服務(wù)端確認(rèn)收到請求。用時5μs
- 第5~6行,可以知道腳本執(zhí)行用時60s1387μs,與php腳本相符。
- 第6、8行服務(wù)端發(fā)送http響應(yīng)。發(fā)送響應(yīng)用時90166μs。
- 第7行,表明由服務(wù)端守護(hù)進(jìn)程主動關(guān)閉連接。結(jié)合第6、8行,說明http響應(yīng)一旦發(fā)送完畢,服務(wù)端馬上關(guān)閉這個tcp連接
- 第7、9、10說明tcp連接順序關(guān)閉,用時90963μs。需要注意,這里socket資源并沒有立即釋放,需要等待2MSL時間(60s)后才被真正釋放。
由此可見,在沒有設(shè)置 keepalive_timeout 情況下,一個socket資源從建立到真正釋放需要經(jīng)過的時間是:建立tcp連接 + 傳送http請求 + php腳本執(zhí)行 + 傳送http響應(yīng) + 關(guān)閉tcp連接 + 2MSL 。(注:這里的時間只能做參考,具體的時間主要由網(wǎng)絡(luò)帶寬,和響應(yīng)大小而定)
2. 當(dāng)keepalive_timeout時間大于0時,即啟用Keep-Alive時,一個tcp連接的生命周期。為了便于分析,我們將keepalive_timeout設(shè)置為300s
| 01 | #tcpdump -n host 218.1.57.236 and port 80 |
| 02 | 21:38:05.471129 IP 218.1.57.236.54049 > 222.73.211.215.http: S 1669618600:1669618600(0) win 65535 |
| 03 | 21:38:05.471140 IP 222.73.211.215.http > 218.1.57.236.54049: S 4166993862:4166993862(0) ack 1669618601 win 5840 |
| 04 | 21:38:05.481731 IP 218.1.57.236.54049 > 222.73.211.215.http: . ack 1 win 32768 |
| 05 | 21:38:05.481976 IP 218.1.57.236.54049 > 222.73.211.215.http: P 1:797(796) ack 1 win 32768 |
| 06 | 21:38:05.481985 IP 222.73.211.215.http > 218.1.57.236.54049: . ack 797 win 59 |
| 07 | ? |
| 08 | 21:38:07.483626 IP 222.73.211.215.http > 218.1.57.236.54049: P 1:326(325) ack 797 win 59 |
| 09 | 21:38:07.747614 IP 218.1.57.236.54049 > 222.73.211.215.http: . ack 326 win 32605 |
| 10 | 21:43:07.448454 IP 222.73.211.215.http > 218.1.57.236.54049: F 326:326(0) ack 797 win 59 |
| 11 | 21:43:07.560316 IP 218.1.57.236.54049 > 222.73.211.215.http: . ack 327 win 32605 |
| 12 | 21:43:11.759102 IP 218.1.57.236.54049 > 222.73.211.215.http: F 797:797(0) ack 327 win 32605 |
| 13 | 21:43:11.759111 IP 222.73.211.215.http > 218.1.57.236.54049: . ack 798 win 59 |
- 我們先看一下,第6~8行,跟上次示例不一樣的是,服務(wù)端httpd守護(hù)進(jìn)程發(fā)完響應(yīng)后,沒有立即主動關(guān)閉tcp連接。
- 第8行,結(jié)合第6行,我們可以看到,5分鐘(300s)后,服務(wù)端主動關(guān)閉這個tcp連接。這個時間,正是我們設(shè)置的keepalive_timeout的時間。
- 由此可見,設(shè)置了keepalive_timout時間情況下,一個socket建立到釋放需要的時間是多了keepalive_timeout時間。
3. 當(dāng)keepalive_timeout時間大于0,并且在同一個tcp連接發(fā)送多個http響應(yīng)。這里為了便于分析,我們將keepalive_timeout設(shè)置為180s
通過這個測試,我們想弄清楚,keepalive_timeout是從第一個響應(yīng)結(jié)束開啟計(jì)時,還是最后一個響應(yīng)結(jié)束開啟計(jì)時。測試結(jié)果證實(shí)是后者,這里,我們每隔120s發(fā)一次請求,通過一個tcp連接發(fā)送了3個請求。
| 01 | # tcpdump -n host 218.1.57.236 and port 80 |
| 02 | 22:43:57.102448 IP 218.1.57.236.49955 > 222.73.211.215.http: S 4009392741:4009392741(0) win 65535 |
| 03 | 22:43:57.102527 IP 222.73.211.215.http > 218.1.57.236.49955: S 4036426778:4036426778(0) ack 4009392742 win 5840 |
| 04 | 22:43:57.111337 IP 218.1.57.236.49955 > 222.73.211.215.http: . ack 1 win 32768 |
| 05 | ? |
| 06 | 22:43:57.111522 IP 218.1.57.236.49955 > 222.73.211.215.http: P 1:797(796) ack 1 win 32768 |
| 07 | 22:43:57.111530 IP 222.73.211.215.http > 218.1.57.236.49955: . ack 797 win 59 |
| 08 | 22:43:59.114663 IP 222.73.211.215.http > 218.1.57.236.49955: P 1:326(325) ack 797 win 59 |
| 09 | 22:43:59.350143 IP 218.1.57.236.49955 > 222.73.211.215.http: . ack 326 win 32605 |
| 10 | ? |
| 11 | 22:45:59.226102 IP 218.1.57.236.49955 > 222.73.211.215.http: P 1593:2389(796) ack 650 win 32443 |
| 12 | 22:45:59.226109 IP 222.73.211.215.http > 218.1.57.236.49955: . ack 2389 win 83 |
| 13 | 22:46:01.227187 IP 222.73.211.215.http > 218.1.57.236.49955: P 650:974(324) ack 2389 win 83 |
| 14 | 22:46:01.450364 IP 218.1.57.236.49955 > 222.73.211.215.http: . ack 974 win 32281 |
| 15 | ? |
| 16 | 22:47:57.377707 IP 218.1.57.236.49955 > 222.73.211.215.http: P 3185:3981(796) ack 1298 win 32119 |
| 17 | 22:47:57.377714 IP 222.73.211.215.http > 218.1.57.236.49955: . ack 3981 win 108 |
| 18 | 22:47:59.379496 IP 222.73.211.215.http > 218.1.57.236.49955: P 1298:1622(324) ack 3981 win 108 |
| 19 | 22:47:59.628964 IP 218.1.57.236.49955 > 222.73.211.215.http: . ack 1622 win 32768 |
| 20 | ? |
| 21 | 22:50:59.358537 IP 222.73.211.215.http > 218.1.57.236.49955: F 1622:1622(0) ack 3981 win 108 |
| 22 | 22:50:59.367911 IP 218.1.57.236.49955 > 222.73.211.215.http: . ack 1623 win 32768 |
| 23 | 22:50:59.686527 IP 218.1.57.236.49955 > 222.73.211.215.http: F 3981:3981(0) ack 1623 win 32768 |
| 24 | 22:50:59.686531 IP 222.73.211.215.http > 218.1.57.236.49955: . ack 3982 win 108 |
- 第一組,三個ip包表示tcp三次握手建立連接,由瀏覽器建立。
- 第二組,發(fā)送第一次http請求并且得到響應(yīng),服務(wù)端守護(hù)進(jìn)程輸出響應(yīng)之后,并沒馬上主動關(guān)閉tcp連接。而是啟動keepalive_timout計(jì)時。
- 第三組,2分鐘后,發(fā)送第二次http請求并且得到響應(yīng),同樣服務(wù)端守護(hù)進(jìn)程也沒有馬上主動關(guān)閉tcp連接,重新啟動keepalive_timout計(jì)時。
- 第四組,又2分鐘后,發(fā)送了第三次http請求并且得到響應(yīng)。服務(wù)器守護(hù)進(jìn)程依然沒有主動關(guān)地閉tcp連接(距第一次http響應(yīng)有4分鐘了,大于keepalive_timeout值),而是重新啟動了keepalive_timout計(jì)時。
- 第五組,跟最后一個響應(yīng)keepalive_timeout(180s)內(nèi),守護(hù)進(jìn)程再沒有收到請求。計(jì)時結(jié)束,服務(wù)端守護(hù)進(jìn)程主動關(guān)閉連接。4次揮手后,服務(wù)端進(jìn)入TIME_WAIT狀態(tài)。
這說明,當(dāng)設(shè)定了keepalive_timeout,一個socket由建立到釋放,需要時間是:tcp建立 + (最后一個響應(yīng)時間 – 第一個請求時間) + tcp關(guān)閉 + 2MSL。紅色加粗表示每一次請求發(fā)送時間、每一次請求腳本執(zhí)行時間、每一次響應(yīng)發(fā)送時間,還有兩兩請求相隔時間。進(jìn)一步測試,正在關(guān)閉或者TIME_WAIT狀態(tài)的tcp連接,不能傳輸http請求和響應(yīng)。即,當(dāng)一個連接結(jié)束keepalive_timeout計(jì)時,服務(wù)端守護(hù)進(jìn)程發(fā)送第一個FIN標(biāo)志ip包后,該連接不能再使用了。
http keep-alive與tcp keep-alive
http keep-alive與tcp keep-alive,不是同一回事,意圖不一樣。http keep-alive是為了讓tcp活得更久一點(diǎn),以便在同一個連接上傳送多個http,提高socket的效率。而tcp keep-alive是TCP的一種檢測TCP連接狀況的保鮮機(jī)制。tcp keep-alive保鮮定時器,支持三個系統(tǒng)內(nèi)核配置參數(shù):
| 1 | echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time |
| 2 | echo 15 > /proc/sys/net/ipv4/tcp_keepalive_intvl |
| 3 | echo 5 > /proc/sys/net/ipv4/tcp_keepalive_probes |
keepalive是TCP保鮮定時器,當(dāng)網(wǎng)絡(luò)兩端建立了TCP連接之后,閑置idle(雙方?jīng)]有任何數(shù)據(jù)流發(fā)送往來)了tcp_keepalive_time后,服務(wù)器內(nèi)核就會嘗試向客戶端發(fā)送偵測包,來判斷TCP連接狀況(有可能客戶端崩潰、強(qiáng)制關(guān)閉了應(yīng)用、主機(jī)不可達(dá)等等)。如果沒有收到對方的回答(ack包),則會在 tcp_keepalive_intvl后再次嘗試發(fā)送偵測包,直到收到對對方的ack,如果一直沒有收到對方的ack,一共會嘗試 tcp_keepalive_probes次,每次的間隔時間在這里分別是15s, 30s, 45s, 60s, 75s。如果嘗試tcp_keepalive_probes,依然沒有收到對方的ack包,則會丟棄該TCP連接。TCP連接默認(rèn)閑置時間是2小時,一般設(shè)置為30分鐘足夠了。
也就是說,僅當(dāng)nginx的keepalive_timeout值設(shè)置高于tcp_keepalive_time,并且距此tcp連接傳輸?shù)淖詈笠粋€http響應(yīng),經(jīng)過了tcp_keepalive_time時間之后,操作系統(tǒng)才會發(fā)送偵測包來決定是否要丟棄這個TCP連接。一般不會出現(xiàn)這種情況,除非你需要這樣做。
keep-alive與TIME_WAIT
使用http keep-alvie,可以減少服務(wù)端TIME_WAIT數(shù)量(因?yàn)橛煞?wù)端httpd守護(hù)進(jìn)程主動關(guān)閉連接)。道理很簡單,相較而言,啟用keep-alive,建立的tcp連接更少了,自然要被關(guān)閉的tcp連接也相應(yīng)更少了。
最后
我想用一張示意圖片來說明使用啟用keepalive的不同。另外,http keepalive是客戶端瀏覽器與服務(wù)端httpd守護(hù)進(jìn)程協(xié)作的結(jié)果,所以,我們另外安排篇幅介紹不同瀏覽器的各種情況對keepalive的利用。
- section 02?了解HTTP Keep-Alive的基本情況
Keep-Alive是HTTP協(xié)議中非常重要的一個屬性。大家知道HTTP構(gòu)建在TCP之上。在HTTP早期實(shí)現(xiàn)中,每個HTTP請求都要打開一個socket連接。這種做效率很低,因?yàn)橐粋€Web 頁面中的很多HTTP請求都指向同一個服務(wù)器。例如,很多為Web頁面中的圖片發(fā)起的請求都指向一個通用的圖片服務(wù)器。持久連接的引入解決了多對已請求服務(wù)器導(dǎo)致的socket連接低效性的問題。它使瀏覽器可以再一個單獨(dú)的連接上進(jìn)行多個請求。瀏覽器和服務(wù)器使用Connection頭ilai指出對Keep-Alive的支持。
HTTP是一個請求<->響應(yīng)模式的典型范例,即客戶端向服務(wù)器發(fā)送一個請求信息,服務(wù)器來響應(yīng)這個信息。在老的HTTP版本中,每個請求都將被創(chuàng)建一個新的客戶端->服務(wù)器的連接,在這個連接上發(fā)送請求,然后接收請求。這樣的模式有一個很大的優(yōu)點(diǎn)就是,它很簡單,很容易理解和編程實(shí)現(xiàn);它也有一個很大的缺點(diǎn)就是,它效率很低,因此Keep-Alive被提出用來解決效率低的問題。
HTTP/1.0
HTTP 1.0中默認(rèn)是關(guān)閉的,需要在http頭加入"Connection: Keep-Alive",才能啟用Keep-Alive;HTTP 1.1中默認(rèn)啟用Keep-Alive,如果加入"Connection: close",才關(guān)閉。
在HTTP/1.0版本中,并沒有官方的標(biāo)準(zhǔn)來規(guī)定Keep-Alive如何工作,因此實(shí)際上它是被附加到HTTP/1.0協(xié)議上,如果客戶端瀏覽器支持Keep-Alive,那么就在HTTP請求頭中添加一個字段 Connection: Keep-Alive,當(dāng)服務(wù)器收到附帶有Connection: Keep-Alive的請求時,它也會在響應(yīng)頭中添加一個同樣的字段來使用Keep-Alive。這樣一來,客戶端和服務(wù)器之間的HTTP連接就會被保持,不會斷開(超過Keep-Alive規(guī)定的時間,意外斷電等情況除外),當(dāng)客戶端發(fā)送另外一個請求時,就使用這條已經(jīng)建立的連接。
HTTP/1.1
目前大部分瀏覽器都是用HTTP?1.1協(xié)議,也就是說默認(rèn)會啟用Keep-Alive的連接請求。列舉以下瀏覽器的并發(fā)數(shù)作參考:IE6,7在HTTP/1.0中默認(rèn)最大并發(fā)連接數(shù)為4,在HTTP/1.1中默認(rèn)最大并發(fā)連接數(shù)為2,IE8都為6,Firefox2在HTTP/1.0中默認(rèn)最大并發(fā)連接數(shù)為2 在HTTP/1.1中默認(rèn)最大并發(fā)連接數(shù)為8,firefox 3默認(rèn)都是6。
在HTTP/1.1版本中,官方規(guī)定的Keep-Alive使用標(biāo)準(zhǔn)和在HTTP/1.0版本中有些不同,默認(rèn)情況下所在HTTP1.1中所有連接都被保持,除非在請求頭或響應(yīng)頭中指明要關(guān)閉:Connection: Close ,這也就是為什么Connection: Keep-Alive字段再沒有意義的原因。另外,還添加了一個新的字段Keep-Alive:,因?yàn)檫@個字段并沒有詳細(xì)描述用來做什么,可忽略它。
Not reliable(不可靠)
HTTP是一個無狀態(tài)協(xié)議,這意味著每個請求都是獨(dú)立的,Keep-Alive沒能改變這個結(jié)果。另外,Keep-Alive也不能保證客戶端和服務(wù)器之間的連接一定是活躍的,在HTTP1.1版本中也如此。唯一能保證的就是當(dāng)連接被關(guān)閉時你能得到一個通知,所以不應(yīng)該讓程序依賴于Keep-Alive的保持連接特性,否則會有意想不到的后果。
Keep-Alive和POST
在HTTP1.1細(xì)則中規(guī)定了在一個POST消息體后面不能有任何字符,還指出了對于某一個特定的瀏覽器可能并不遵循這個標(biāo)準(zhǔn)(比如在POST消息體的后面放置一個CRLF符)。而據(jù)我所知,大部分瀏覽器在POST消息體后都會自動跟一個CRLF符再發(fā)送,如何解決這個問題呢?根據(jù)上面的說明在POST請求頭中禁止使用Keep-Alive,或者由服務(wù)器自動忽略這個CRLF,大部分服務(wù)器都會自動忽略,但是在未經(jīng)測試之前是不可能知道一個服務(wù)器是否會這樣做。
一些容易犯的誤區(qū):
?
在 Apache 服務(wù)器中,Keep-Alive 是一個布爾值,On 代表打開,Off 代表關(guān)閉,這個指令在其他眾多的 HTTPD 服務(wù)器中都是存在的。
Keep-Alive?配置指令決定當(dāng)處理完用戶發(fā)起的 HTTP 請求后是否立即關(guān)閉 TCP 連接,如果 Keep-Alive 設(shè)置為On,那么用戶完成一次訪問后,不會立即斷開連接,如果還有請求,那么會繼續(xù)在這一次 TCP 連接中完成,而不用重復(fù)建立新的 TCP 連接和關(guān)閉TCP 連接,可以提高用戶訪問速度。
那么我們考慮3種情況:
對于上面3中情況,我認(rèn)為:1 最適合打開 Keep-Alive ,2 隨意,3 最適合關(guān)閉 Keep-Alive
下面我來分析一下原因。
在 Apache 中,打開和關(guān)閉 Keep-Alive 功能,服務(wù)器端會有什么異同呢?
先看看理論分析。
打開 Keep-Alive 后,意味著每次用戶完成全部訪問后,都要保持一定時間后才關(guān)閉會關(guān)閉 TCP 連接,那么在關(guān)閉連接之前,必然會有一個Apache 進(jìn)程對應(yīng)于該用戶而不能處理其他用戶,假設(shè) Keep-Alive 的超時時間為 10 秒種,服務(wù)器每秒處理 50個獨(dú)立用戶訪問,那么系統(tǒng)中 Apache 的總進(jìn)程數(shù)就是 10 * 50 = 500 個,如果一個進(jìn)程占用 4M 內(nèi)存,那么總共會消耗 2G內(nèi)存,所以可以看出,在這種配置中,相當(dāng)消耗內(nèi)存,但好處是系統(tǒng)只處理了 50次 TCP 的握手和關(guān)閉操作。
如果關(guān)閉 Keep-Alive,如果還是每秒50個用戶訪問,如果用戶每次連續(xù)的請求數(shù)為3個,那么 Apache 的總進(jìn)程數(shù)就是 50 * 3= 150 個,如果還是每個進(jìn)程占用 4M 內(nèi)存,那么總的內(nèi)存消耗為 600M,這種配置能節(jié)省大量內(nèi)存,但是,系統(tǒng)處理了 150 次 TCP的握手和關(guān)閉的操作,因此又會多消耗一些 CPU 資源。
再看看實(shí)踐的觀察。
我在一組大量處理動態(tài)網(wǎng)頁內(nèi)容的服務(wù)器中,起初打開 Keep-Alive功能,經(jīng)常觀察到用戶訪問量大時Apache進(jìn)程數(shù)也非常多,系統(tǒng)頻繁使用交換內(nèi)存,系統(tǒng)不穩(wěn)定,有時負(fù)載會出現(xiàn)較大波動。關(guān)閉了 Keep-Alive功能后,看到明顯的變化是: Apache 的進(jìn)程數(shù)減少了,空閑內(nèi)存增加了,用于文件系統(tǒng)Cache的內(nèi)存也增加了,CPU的開銷增加了,但是服務(wù)更穩(wěn)定了,系統(tǒng)負(fù)載也比較穩(wěn)定,很少有負(fù)載大范圍波動的情況,負(fù)載有一定程度的降低;變化不明顯的是:訪問量較少的時候,系統(tǒng)平均負(fù)載沒有明顯變化。
總結(jié)一下:
在內(nèi)存非常充足的服務(wù)器上,不管是否關(guān)閉 Keep-Alive 功能,服務(wù)器性能不會有明顯變化;
如果服務(wù)器內(nèi)存較少,或者服務(wù)器有非常大量的文件系統(tǒng)訪問時,或者主要處理動態(tài)網(wǎng)頁服務(wù),關(guān)閉 Keep-Alive 后可以節(jié)省很多內(nèi)存,而節(jié)省出來的內(nèi)存用于文件系統(tǒng)Cache,可以提高文件系統(tǒng)訪問的性能,并且系統(tǒng)會更加穩(wěn)定。
補(bǔ)充1:
關(guān)于是否應(yīng)該關(guān)閉 Keep-Alive 選項(xiàng),我覺得可以基于下面的一個公式來判斷。
在理想的網(wǎng)絡(luò)連接狀況下,系統(tǒng)的 Apache 進(jìn)程數(shù)和內(nèi)存使用可以用如下公式表達(dá):
HttpdProcessNumber = KeepAliveTimeout * TotalRequestPerSecond / Average(KeepAliveRequests)
HttpdUsedMemory = HttpdProcessNumber * MemoryPerHttpdProcess
換成中文:
總Apache進(jìn)程數(shù) = KeepAliveTimeout * 每秒種HTTP請求數(shù) / 平均KeepAlive請求
Apache占用內(nèi)存 = 總Apache進(jìn)程數(shù) * 平均每進(jìn)程占用內(nèi)存數(shù)
需要特別說明的是:
[平均Keep-Alive請求] 數(shù),是指每個用戶連接上服務(wù)器后,持續(xù)發(fā)出的 HTTP 請求數(shù)。當(dāng) Keep-AliveTimeout 等 0或者 Keep-Alive 關(guān)閉時,Keep-AliveTimeout 不參與乘的運(yùn)算從上面的公式看,如果 [每秒用戶請求]多,[Keep-AliveTimeout] 的值大,[平均Keep-Alive請求] 的值小,都會造成 [Apache進(jìn)程數(shù)] 多和 [內(nèi)存]多,但是當(dāng) [平均Keep-Alive請求] 的值越大時,[Apache進(jìn)程數(shù)] 和 [內(nèi)存] 都是趨向于減少的。
基于上面的公式,我們就可以推算出當(dāng) 平均Keep-Alive請求 <= Keep-AliveTimeout 時,關(guān)閉 Keep-Alive 選項(xiàng)是劃算的,否則就可以考慮打開。
補(bǔ)充2:??Keep-Alive 該參數(shù)控制Apache是否允許在一個連接中有多個請求,默認(rèn)打開。但對于大多數(shù)論壇類型站點(diǎn)來說,通常設(shè)置為off以關(guān)閉該支持。?
補(bǔ)充3:??如果服務(wù)器前跑有應(yīng)用squid服務(wù),或者其它七層設(shè)備,Keep-Alive On 設(shè)定要開啟持續(xù)長連接
實(shí)際在前端有 squid 的情況下, Keep-Alive 很關(guān)鍵。記得 On
section 04?HTTP協(xié)議中的長連接與短連接長連接與短連接
- 長連接:client方與server方先建立連接,連接建立后不斷開,然后再進(jìn)行報文發(fā)送和接收。這種方式下由于通訊連接一直存在。此種方式常用于P2P通信。
- 短連接:Client方與server每進(jìn)行一次報文收發(fā)交易時才進(jìn)行通訊連接,交易完畢后立即斷開連接。此方式常用于一點(diǎn)對多點(diǎn)通訊。C/S通信。
長連接與短連接的操作過程
短連接的操作步驟是:
建立連接——數(shù)據(jù)傳輸——關(guān)閉連接...建立連接——數(shù)據(jù)傳輸——關(guān)閉連接
長連接的操作步驟是:
建立連接——數(shù)據(jù)傳輸...(保持連接)...數(shù)據(jù)傳輸——關(guān)閉連接
長連接與短連接的使用時機(jī)
短連接多用于操作頻繁,點(diǎn)對點(diǎn)的通訊,而且連接數(shù)不能太多的情況。每個TCP連接的建立都需要三次握手,每個TCP連接的斷開要四次握手。
如果每次操作都要建立連接然后再操作的話處理速度會降低,所以每次操作后,下次操作時直接發(fā)送數(shù)據(jù)就可以了,不用再建立TCP連接。例如:數(shù)據(jù)庫的連接用長連接,如果用短連接頻繁的通信會造成socket錯誤,頻繁的socket創(chuàng)建也是對資源的浪費(fèi)。
Web網(wǎng)站的http服務(wù)一般都用短連接,因?yàn)殚L連接對于服務(wù)器來說要耗費(fèi)一定的資源。像web網(wǎng)站這么頻繁的成千上萬甚至上億客戶端的連接用短連接更省一些資源。試想如果都用長連接,而且同時用成千上萬的用戶,每個用戶都占有一個連接的話,可想而知服務(wù)器的壓力有多大。所以并發(fā)量大,但是每個用戶又不需頻繁操作的情況下需要短連接。
總之:長連接和短連接的選擇要根據(jù)需求而定。
長連接和短連接的產(chǎn)生在于client和server采取的關(guān)閉策略,具體的應(yīng)用場景采用具體的策略,沒有十全十美的選擇,只有合適的選擇。
HTTP協(xié)議長連接、短連接總結(jié)
長連接與短連接的不同主要在于client和server采取的關(guān)閉策略不同。短連接在建立連接以后只進(jìn)行一次數(shù)據(jù)傳輸就關(guān)閉連接,而長連接在建立連接以后會進(jìn)行多次數(shù)據(jù)數(shù)據(jù)傳輸直至關(guān)閉連接(長連接中關(guān)閉連接通過Connection:closed頭部字段)。
二者關(guān)閉策略的不同,就產(chǎn)生了長連接的優(yōu)點(diǎn):
- 通過開啟、關(guān)閉更少的TCP連接,節(jié)約CPU時間和內(nèi)存
- 通過減少TCP開啟引起的包的數(shù)目,降低網(wǎng)絡(luò)阻塞。
二者所應(yīng)用的具體場景不同。短連接多用于操作頻繁、點(diǎn)對點(diǎn)的通訊,且連接數(shù)不能太多的情況。數(shù)據(jù)庫的連接則采用長連接。
轉(zhuǎn)自?現(xiàn)代魔法學(xué)院
總結(jié)
以上是生活随笔為你收集整理的HTTP Keep-Alive 学习的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机主板bos不存信息的原因,电脑主板
- 下一篇: 监理工程师证书怎么考?