日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

【Nginx08】Nginx學(xué)習(xí):HTTP核心模塊(五)長(zhǎng)連接與連接處理

 硬核項(xiàng)目經(jīng)理 2023-07-14 發(fā)布于湖南

Nginx學(xué)習(xí):HTTP核心模塊(五)長(zhǎng)連接與連接處理

HTTP 基礎(chǔ)知識(shí)大家掌握的怎么樣呀?對(duì)于長(zhǎng)連接這一塊的內(nèi)容應(yīng)該也不是什么新鮮東西了吧。畢竟 HTTP1.1 都已經(jīng)發(fā)布這么久了。今天主要來(lái)看的就是長(zhǎng)連接相關(guān)的配置,另外還會(huì)介紹幾個(gè)和連接有關(guān)的內(nèi)容。同時(shí),今天的內(nèi)容除了 HTTP 外,還需要一點(diǎn) TCP 的知識(shí)。沒(méi)辦法,畢竟 Ngxin 本身就是一個(gè)網(wǎng)絡(luò)代理服務(wù)器軟件,離不開(kāi)的就是各種網(wǎng)絡(luò)相關(guān)的知識(shí)。相信大家肯定沒(méi)問(wèn)題的,畢竟很早前在短視頻中就說(shuō)過(guò),基礎(chǔ)能比我差的程序員估計(jì)在全國(guó)范圍內(nèi)都找不到幾個(gè)了。

但是不要臉和硬著頭皮啃的水平咱還是有的,因此,如果有遺漏或錯(cuò)誤的地方,也懇請(qǐng)各位大佬在評(píng)論區(qū)指出。

好了,不多廢話了,進(jìn)入主題吧。

長(zhǎng)連接

關(guān)于長(zhǎng)連接的知識(shí),屬于 HTTP 的基礎(chǔ)知識(shí)了,咱們不多說(shuō),不了解的小伙伴可以去查閱下相關(guān)資料。簡(jiǎn)單來(lái)說(shuō),一次 HTTP 連接,就要經(jīng)歷 TCP 的三次握手四次揮手,畢竟它是處于網(wǎng)絡(luò)的第七層,同時(shí)也是基于第四層的 TCP 來(lái)實(shí)現(xiàn)的。如果請(qǐng)求很多,需要不停地建立 TCP 連接,效率明顯下降。而長(zhǎng)連接則是一次連接后保持這個(gè)連接一段時(shí)間,如果有其它的請(qǐng)求就可以復(fù)用這條連接,從而減少網(wǎng)絡(luò)連接開(kāi)銷(xiāo),提升效率。比如很多門(mén)戶(hù)或者電商站,一打開(kāi)就是一大堆的 JS、圖片之類(lèi)的請(qǐng)求。如果每一個(gè)都要單獨(dú)建立連接,勢(shì)必會(huì)影響頁(yè)面的整體打開(kāi)速度。

同時(shí),在進(jìn)行反向代理的時(shí)候,也可以啟用長(zhǎng)連接功能,減少后端代理的連接次數(shù)。反向代理相關(guān)的配置我們?cè)诤竺鎸W(xué)習(xí)反向代理相關(guān)的內(nèi)容時(shí)再說(shuō),現(xiàn)在學(xué)習(xí)的主要是針對(duì) http、server、location 模塊的長(zhǎng)連接配置。

在 Nginx 中,有完整的長(zhǎng)連接配置。

keepalive_disable

指定哪些瀏覽器不使用長(zhǎng)連接功能,或者說(shuō)是針對(duì)行為異常的瀏覽器關(guān)閉長(zhǎng)連接功能。

keepalive_disable none | browser ...;

默認(rèn) msie6 , 值為 msie6 表示在遇到POST請(qǐng)求時(shí),關(guān)閉與老版本 MSIE 瀏覽器建立長(zhǎng)連接。 值為 safari 表示在遇到 Mac OS X 和類(lèi) Mac OS X 操作系統(tǒng)下的 Safari 瀏覽器和類(lèi) Safari 瀏覽器時(shí),不與瀏覽器建立長(zhǎng)連接。 值為none表示為所有瀏覽器開(kāi)啟長(zhǎng)連接功能。

在 nginx 1.1.18 版本及以前,safari 將匹配所有操作系統(tǒng)上的 Safari 和類(lèi) Safari 瀏覽器,并默認(rèn)不與這些瀏覽器建立長(zhǎng)連接。

我本地是 Mac 電腦,因此,直接設(shè)置一個(gè) safari 的配置。

http {
  ……
  keepalive_disable safari;
 ……
}

配置完成后,使用 Safari 和 Chrome 分別測(cè)試,可以看到 Safari 的 Response Header 中的 Connection 的值變成了 close ,而 Chrome 還是正常的 keep-alive 。

keepalive_requests

設(shè)置通過(guò)一個(gè)長(zhǎng)連接可以處理的最大請(qǐng)求數(shù)。 請(qǐng)求數(shù)超過(guò)此值,長(zhǎng)連接將關(guān)閉。

keepalive_requests number;

在版本1.19.10之前,默認(rèn)值為100,現(xiàn)在默認(rèn)值是 1000 。定期關(guān)閉連接對(duì)于釋放每個(gè)連接的內(nèi)存分配是必要的。因此,使用過(guò)高的最大請(qǐng)求數(shù)可能會(huì)導(dǎo)致內(nèi)存使用過(guò)多,因此不建議使用。

我們直接配置一個(gè),將它的 number 設(shè)置為 2 ,然后建立一個(gè) html 頁(yè)面以及一堆空的 js 文件。

// nginx.conf
http {
  ……
  keepalive_requests 2;
 ……
}

// testkeepalive1.html
~
~
"testkeepalive1.html" 23L, 461C                                                                                                                                                  20,19-26      All
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>

This is testkeepalive1.html

<script src="js1/1.js"></script>
<script src="js1/2.js"></script>
<script src="js1/3.js"></script>
<script src="js1/4.js"></script>
<script src="js1/5.js"></script>

</body>
</html>

好了,現(xiàn)在訪問(wèn) http://192.168.56.88/testkeepalive1.html 頁(yè)面,查看所有的請(qǐng)求,目前我們算上這個(gè) html 頁(yè)面,一共會(huì)有 6 個(gè)請(qǐng)求。你會(huì)發(fā)現(xiàn)有的請(qǐng)求的 Connection 會(huì)變成 Close ,也就是說(shuō)一條長(zhǎng)連接在請(qǐng)求數(shù)量達(dá)到設(shè)置的值之后就斷了,然后又是一個(gè)新的請(qǐng)求連接。

一般情況下不需要刻意設(shè)置這個(gè)值,上面文檔的說(shuō)明中也說(shuō)過(guò)了使用過(guò)高的最大請(qǐng)求數(shù)可能會(huì)導(dǎo)致內(nèi)存使用過(guò)多,正常來(lái)說(shuō) 1000 已經(jīng)相當(dāng)夠用了,即使是淘寶這樣的網(wǎng)站,首頁(yè)上的請(qǐng)求數(shù)也沒(méi)多少,畢竟大家還會(huì)合并請(qǐng)求及圖片來(lái)進(jìn)行連接的優(yōu)化。

keepalive_time

限制通過(guò)一個(gè)保持活動(dòng)連接處理請(qǐng)求的最長(zhǎng)時(shí)間。

keepalive_time time;

達(dá)到此時(shí)間后,連接在后續(xù)請(qǐng)求處理后關(guān)閉,默認(rèn)值是 1h 。它是 Nginx 1.19.10 之后新出的配置,咱們就不做詳細(xì)的測(cè)試了,如果想要測(cè)試的同學(xué),可以根據(jù)下面的 keepalive_timeout 測(cè)試,然后訪問(wèn)一個(gè)動(dòng)態(tài)能夠 sleep 的請(qǐng)求路徑,讓 sleep 時(shí)間超過(guò)這個(gè)配置的時(shí)間,接著使用一個(gè)靜態(tài)頁(yè)面來(lái)定時(shí)發(fā)送 ajax 請(qǐng)求查看連接復(fù)用情況。比較麻煩,日常估計(jì)使用的小伙伴也不會(huì)很多,它默認(rèn)的 1h 估計(jì)很多耗時(shí)連接也不可能去做這么長(zhǎng)時(shí)間的操作。

keepalive_timeout

設(shè)置客戶(hù)端的長(zhǎng)連接在服務(wù)器端保持的最長(zhǎng)時(shí)間

keepalive_timeout timeout [header_timeout];

在 timeout 設(shè)置的時(shí)間內(nèi),客戶(hù)端未發(fā)起新請(qǐng)求,則長(zhǎng)連接關(guān)閉。第二個(gè)參數(shù)為可選項(xiàng),設(shè)置 “Keep-Alive: timeout=time” 響應(yīng)頭的值,可以為這兩個(gè)參數(shù)設(shè)置不同的值?!癒eep-Alive: timeout=time” 響應(yīng)頭可以被 Mozilla 和 Konqueror 瀏覽器識(shí)別和處理,MSIE 瀏覽器在大約 60 秒后會(huì)關(guān)閉長(zhǎng)連接。

默認(rèn)安裝完成之后的 Nignx 配置中,這個(gè)選項(xiàng)被設(shè)置為 65 。如果發(fā)現(xiàn) Nginx 占用服務(wù)器的 CPU 特別高,可以嘗試調(diào)低這個(gè)時(shí)間,或者直接設(shè)置成 0 ,設(shè)置成 0 后將整個(gè)關(guān)閉 keepalive 長(zhǎng)連接的功能。

現(xiàn)在我們一起來(lái)進(jìn)行測(cè)試,首先添加如下配置。

http {
  ……
  keepalive_timeout  0;
 ……
}

重載配置后使用一個(gè) Linux 命令查看連接情況。

[root@localhost html]# netstat -nat|grep -i "80"
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN

看來(lái)目前還沒(méi)有連接過(guò)來(lái),我們可以訪問(wèn)之前的 /testkeepalive1.html ,馬上就能看到有新的連接建立了。

[root@localhost html]# netstat -nat|grep -i "80"
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
tcp        0      0 192.168.56.88:80        192.168.56.1:49816      TIME_WAIT
tcp        0      0 192.168.56.88:80        192.168.56.1:49811      TIME_WAIT
tcp        0      0 192.168.56.88:80        192.168.56.1:49810      TIME_WAIT
tcp        0      0 192.168.56.88:80        192.168.56.1:49814      TIME_WAIT
tcp        0      0 192.168.56.88:80        192.168.56.1:49805      TIME_WAIT
tcp        0      0 192.168.56.88:80        192.168.56.1:49812      TIME_WAIT
tcp        0      0 192.168.56.88:80        192.168.56.1:49813      TIME_WAIT

因?yàn)槲覀儗?keepalive_timeout 設(shè)置成 0 了,所以現(xiàn)在有 7 條連接建立成功,注意,我使用的是 Chrome ,所以還會(huì)自帶一個(gè) /favicon.ico 請(qǐng)求,加上前面的 html 以及 5 個(gè) js ,正好 7 個(gè)連接。如果速度快點(diǎn)過(guò)來(lái)查看的話,可以看到連接是 ESTABLISHED 狀態(tài),表示連接正在使用,TIME_WAIT 表示連接在等待中。

接下來(lái),我們修改 keepalive_timeout 為 5 ,意思就是 5 秒,如果沒(méi)有使用,就會(huì)用新的連接。現(xiàn)在再次訪問(wèn),會(huì)看到依然建立了 5 個(gè)連接,畢竟我們相當(dāng)于同時(shí)請(qǐng)求本地的虛擬機(jī),速度還是夠快的,只有兩個(gè)連接被復(fù)用了,其它的還是建立了連接。另外,默認(rèn) Chrome 可以同時(shí)建立 6 個(gè)連接,你可以測(cè)試再多加幾個(gè) js ,然后試試,最多它就只能建立 6 個(gè)連接,前面的 js 沒(méi)有加載完,后面的就會(huì)等待加載,這里和長(zhǎng)連接無(wú)關(guān),即使不使用長(zhǎng)連接,也會(huì)在 6 個(gè)連接中的某一個(gè)連接釋放之后才會(huì)建立新的連接。

[root@localhost html]# netstat -nat|grep -i "80"
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
tcp        0      0 192.168.56.88:80        192.168.56.1:52469      ESTABLISHED
tcp        0      0 192.168.56.88:80        192.168.56.1:52471      ESTABLISHED
tcp        0      0 192.168.56.88:80        192.168.56.1:52470      ESTABLISHED
tcp        0      0 192.168.56.88:80        192.168.56.1:52472      ESTABLISHED
tcp        0      0 192.168.56.88:80        192.168.56.1:52465      ESTABLISHED

在 5 秒內(nèi),刷新頁(yè)面,不會(huì)有新的連接出現(xiàn),但是等待 5 秒后,再次刷新,就會(huì)發(fā)現(xiàn)又有新的連接建立了。

[root@localhost html]# netstat -nat|grep -i "80"
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN
tcp        0      0 192.168.56.88:80        192.168.56.1:52469      TIME_WAIT
tcp        0      0 192.168.56.88:80        192.168.56.1:52471      TIME_WAIT
tcp        0      0 192.168.56.88:80        192.168.56.1:52692      ESTABLISHED
tcp        0      0 192.168.56.88:80        192.168.56.1:52691      ESTABLISHED
tcp        0      0 192.168.56.88:80        192.168.56.1:52690      ESTABLISHED
tcp        0      0 192.168.56.88:80        192.168.56.1:52686      ESTABLISHED
tcp        0      0 192.168.56.88:80        192.168.56.1:52693      ESTABLISHED
tcp        0      0 192.168.56.88:80        192.168.56.1:52470      TIME_WAIT
tcp        0      0 192.168.56.88:80        192.168.56.1:52472      TIME_WAIT
tcp        0      0 192.168.56.88:80        192.168.56.1:52465      TIME_WAIT

再等待一段時(shí)間后,所有連接全部關(guān)閉。這里關(guān)閉連接的時(shí)間是操作系統(tǒng)決定的,與操作系統(tǒng)被動(dòng)斷開(kāi) TCP 連接的配置有關(guān),主要是 net.ipv4.tcp_tw_reuse 這個(gè)配置,大家可以自己查閱相關(guān)的資料。正常情況下是在 TIME_WAIT 狀態(tài)后等待大約 2 分鐘,最低可以修改為 1 分鐘,通過(guò)下面的命令。這個(gè)是操作系統(tǒng)的固定值,最低只能是 60 秒,也就是這個(gè) 1 分鐘。

[root@localhost html]# sysctl net.ipv4.tcp_tw_reuse=1
[root@localhost html]# sysctl -p

這樣一分鐘以后這些連接信息就會(huì)消失了。設(shè)置成 0 不管用的,一樣會(huì)等待,客戶(hù)端關(guān)掉瀏覽器也沒(méi)用。這個(gè)命令真實(shí)的作用其實(shí)是如果連接是安全可控的,可以復(fù)用 TIME_WAIT 的連接為新的連接所用。它可以快速?gòu)?fù)用處于 TIME_WAIT 狀態(tài)的 TCP 連接,也就相當(dāng)于縮短 TIME_WAIT 狀態(tài)的持續(xù)時(shí)間。只有客戶(hù)端主動(dòng)關(guān)閉連接才會(huì)讓服務(wù)器的正常關(guān)閉,使用 curl 命令測(cè)試就可以看到效果,你不會(huì)看到任何等待的連接。

關(guān)于 TIME_WAIT ,其實(shí)是為了能夠正確、自然地進(jìn)行 TCP 四次揮手而預(yù)留的等待時(shí)間,更具體的內(nèi)容,大家可以再自行查閱 WSL(最大報(bào)文生產(chǎn)周期) 相關(guān)的知識(shí)點(diǎn)。同時(shí),net.ipv4.tcp_tw_reuse 也要慎用,當(dāng)客戶(hù)端與服務(wù)端主機(jī)時(shí)間不同步時(shí),客戶(hù)端的發(fā)送的消息有可能會(huì)被直接拒絕掉。正式環(huán)境使用時(shí),建議:別動(dòng)!保持默認(rèn)就好。

長(zhǎng)連接總結(jié)

關(guān)于長(zhǎng)連接的內(nèi)容寫(xiě)了這么多,但其實(shí)也僅僅只是四個(gè)配置指令而已。更重要的其實(shí)是對(duì)于 HTTP 基礎(chǔ)知識(shí)的學(xué)習(xí),長(zhǎng)連接現(xiàn)在在 Nginx 中是默認(rèn)打開(kāi)的,這幾個(gè)選項(xiàng)也都是有默認(rèn)值配置好的。所以平常其實(shí)我們不太需要去關(guān)心他們的配置。就像上面說(shuō)的,如果發(fā)現(xiàn) CPU 莫名升高,而且是因?yàn)?Nginx 的話,那么可以適當(dāng)調(diào)節(jié)部分參數(shù)。但 CPU 的問(wèn)題也不一定僅僅是連接的問(wèn)題,gzip 同樣也會(huì)帶來(lái) CPU 的壓力。因此,調(diào)優(yōu)是一個(gè)綜合的活,要找到問(wèn)題所在才好應(yīng)對(duì),比如我們還可以查看連接中 TIME_WAIT 的情況來(lái)看是不是連接非常多,這時(shí)更好的方案其實(shí)是要做負(fù)載均衡分散壓力了。

連接處理

連接處理主要是針對(duì) Nginx 如何來(lái)關(guān)閉客戶(hù)端連接的一些配置操作。Nginx 在接收客戶(hù)端的請(qǐng)求時(shí)可能由于客戶(hù)端或服務(wù)端出錯(cuò)了,要立即響應(yīng)錯(cuò)誤信息給客戶(hù)端,而 Nginx 在響應(yīng)錯(cuò)誤信息后大分部情況下是需要關(guān)閉當(dāng)前連接的。Nginx 執(zhí)行完 write() 系統(tǒng)調(diào)用(操作系統(tǒng)函數(shù),參考網(wǎng)絡(luò)編程或操作系統(tǒng)相關(guān)資料)把錯(cuò)誤信息發(fā)送給客戶(hù)端,write() 系統(tǒng)調(diào)用返回成功并不表示數(shù)據(jù)已經(jīng)發(fā)送到客戶(hù)端,有可能還在 tcp 連接的 write buffer 里。所以當(dāng)在某些場(chǎng)景下出現(xiàn) tcp write buffer 里的數(shù)據(jù)在 write() 系統(tǒng)調(diào)用之后到 close() 系統(tǒng)調(diào)用執(zhí)行之前沒(méi)有發(fā)送完畢,且 tcp read buffer 里面還有數(shù)據(jù)沒(méi)有讀,close() 系統(tǒng)調(diào)用會(huì)導(dǎo)致客戶(hù)端收到 RST 報(bào)文且不會(huì)拿到服務(wù)端發(fā)送過(guò)來(lái)的錯(cuò)誤信息數(shù)據(jù)。

所以,解決問(wèn)題的重點(diǎn)是,讓服務(wù)端別發(fā) RST 包?;蛘哒f(shuō)延遲發(fā)送,這就是下面要講的 lingering_close 所要解決的問(wèn)題。

上面的概念看著就很暈吧,如何測(cè)試我也沒(méi)找到相關(guān)的資料,自己也嘗試了半天沒(méi)有什么效果。所以對(duì)這一塊有了解的同學(xué)可以評(píng)論區(qū)留言哦。在實(shí)際應(yīng)用中,是否應(yīng)該打開(kāi) lingering_close 呢?這個(gè)就沒(méi)有固定的推薦值了,lingering_close 的主要作用是保持更好的客戶(hù)端兼容性,但是卻需要消耗更多的額外資源(比如連接會(huì)一直占著)。因此,秉承對(duì)于不懂的東西,默認(rèn)的就是最好的原則,咱們保持默認(rèn)狀態(tài)就好了。將來(lái)如果學(xué)習(xí)或者接觸到這一塊的內(nèi)容了,再寫(xiě)文章和錄視頻進(jìn)行詳細(xì)的學(xué)習(xí)吧。

lingering_close

控制 Nginx 如何關(guān)閉客戶(hù)端連接。

lingering_close off | on | always;

它的默認(rèn)值是 on ,指示 Nginx 在完成關(guān)閉連接前等待和處理客戶(hù)端發(fā)來(lái)的額外數(shù)據(jù)。但只有在預(yù)測(cè)客戶(hù)端可能發(fā)送更多數(shù)據(jù)的情況才會(huì)做此處理。為了控制關(guān)閉HTTP/2連接,必須在 server 下(1.19.1)指定該指令。

  • always 指示 Nginx 無(wú)條件等待和處理客戶(hù)端的額外數(shù)據(jù)。
  • off 指示nginx立即關(guān)閉連接,而絕不等待客戶(hù)端傳送額外數(shù)據(jù)。 這樣做破壞了協(xié)議,所以正常條件下不應(yīng)使用。

lingering_time

lingering_close 生效時(shí)(非off),這條指令定義 Nginx 處理(讀取但忽略)客戶(hù)端額外數(shù)據(jù)的最長(zhǎng)時(shí)間。

lingering_time time;

默認(rèn)值是 30s,超過(guò)這段時(shí)間后,Nginx 將關(guān)閉連接,不論是否還有更多數(shù)據(jù)待處理。

lingering_timeout

lingering_close 生效時(shí)(非off),這條指令定義 Nginx 等待客戶(hù)端更多數(shù)據(jù)到來(lái)的最長(zhǎng)時(shí)間。

lingering_timeout time;

默認(rèn)值是 5s ,如果在這段時(shí)間內(nèi),Nginx 沒(méi)有接收到數(shù)據(jù),Nginx 將關(guān)閉連接。否則,Nginx 將接收數(shù)據(jù),忽略它,然后再等待更多數(shù)據(jù)。 這個(gè)“等待——接收——忽略”的循環(huán)一直重復(fù),但總時(shí)間不會(huì)超過(guò) lingering_time 指令定義的時(shí)間。

總結(jié)

怎么說(shuō)呢,學(xué)這些真的想回去好好再補(bǔ)補(bǔ)網(wǎng)絡(luò)知識(shí)了。就這么點(diǎn)內(nèi)容,也已經(jīng)是邊查資料邊測(cè)試邊寫(xiě)了,后面還有那么多配置以及牽涉到的相關(guān)知識(shí),想想都頭大。不過(guò)沒(méi)關(guān)系,誰(shuí)讓自己喜歡這行呢,各位同學(xué)是不是也感覺(jué)到每次看完文章或者視頻也會(huì)跟我一樣多少會(huì)有一點(diǎn)點(diǎn)的進(jìn)步呢?

長(zhǎng)連接一般我們都會(huì)簡(jiǎn)單配置一下,通常也是以 keepalive_time 和 keepalive_time_out 的配置為主,其它兩個(gè)說(shuō)實(shí)話,沒(méi)學(xué)之前我都不知道有這倆貨。另外一個(gè)連接處理相關(guān)的配置更是從來(lái)沒(méi)用過(guò)。但是,現(xiàn)在起碼我們了個(gè)印象,將來(lái)或許哪天它們就能為我們解決大問(wèn)題呢。

參考文檔:

http:///en/docs/http/ngx_http_core_module.html

    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多