nginx 作為反向代理服務(wù)器中的 keepalive
- 在
nginx
中, 對(duì)于 http1.0 和 http1.1 是支持長(zhǎng)連接的, http 請(qǐng)求是基于 tcp 協(xié)議之上的, 那么當(dāng)客戶端發(fā)起請(qǐng)求前, 需要先與服務(wù)器建立 tcp 連接, 而每次的 tcp 連接是需要三次握手來(lái)確定的, 如果客戶端與服務(wù)端之間的網(wǎng)絡(luò)差了一點(diǎn), 那么這三次握手的時(shí)間消耗就比較多, 同時(shí)也會(huì)帶來(lái)不必要的流量消耗,當(dāng)然斷開連接還要有四次的揮手端開的交互;
- 在 HTTP 協(xié)議中, 請(qǐng)求是請(qǐng)求與應(yīng)答的模式, 如果我們可以在一個(gè)連接上; 響應(yīng)多個(gè)請(qǐng)求, 那么這個(gè)就是所謂的長(zhǎng)連接;
- 我們來(lái)看看 HTTP協(xié)議在響應(yīng)的主體 body 的長(zhǎng)度的描述
http1.0: 如果請(qǐng)求中有 Content-Length 頭, 則以 Content-length 的數(shù)值作為 body的長(zhǎng)度, 客戶端在接收完 body 時(shí), 就可以依照這個(gè)長(zhǎng)度來(lái)接收數(shù)據(jù), 接收完就表示這個(gè)請(qǐng)求完成了, 如果沒(méi)有這個(gè)字段來(lái)標(biāo)示, 那么客戶端會(huì)一直接收數(shù)據(jù), 知道服務(wù)器主動(dòng)關(guān)閉連接
http1.1: 如果響應(yīng)頭中的 Transfer-encoding 為 chunked 傳輸, 則表示 body 是流式傳輸, body 會(huì)被分割為多個(gè) chunk; 每個(gè)chunk的開始會(huì)標(biāo)識(shí)出當(dāng)前塊的長(zhǎng)度, 此時(shí)body 不需要通過(guò)長(zhǎng)度來(lái)制定了, 如果是非chunked 傳輸, 而且有content-length 的字段, 那么就會(huì)按照這個(gè)字段的長(zhǎng)度來(lái)接收數(shù)據(jù), 如果不是 chunked, 又沒(méi)有 Content-length 這個(gè)字段, 那么就會(huì)一直接收到服務(wù)器主動(dòng)關(guān)閉連接
- 當(dāng)服務(wù)器傳輸完 body 之后, 會(huì)考慮使用
長(zhǎng)連接
, 能否使用長(zhǎng)連接, 也有條件限制, 如果客戶端的請(qǐng)求頭中的 connection 為 close; 則標(biāo)識(shí)客戶端需要關(guān)閉長(zhǎng)連接, 如果為 keep-alive; 則客戶端需要打開長(zhǎng)連接, 如果請(qǐng)求頭中沒(méi)有這個(gè)字段, 根據(jù)協(xié)議: 1.0 默認(rèn)為 close; 1.1 默認(rèn)為 keep-alive; 那么nginx 在傳輸完響應(yīng)體后, 會(huì)設(shè)置當(dāng)前連接的 keepalive 屬性, 然后等待客戶端下一次請(qǐng)求, 當(dāng)然 nginx 不可能會(huì)一直的等待, 當(dāng) nginx 設(shè)置 keepalive 等待下一次的請(qǐng)求時(shí), 會(huì)設(shè)置一個(gè)最大的等待時(shí)間, 通過(guò) keepalive_timeout 來(lái)配置, 如果配置為 0 ; 則表示關(guān)閉 keepalive; 此時(shí) http 版本不管是 1.0, 還是 1.1; 客戶端的 connection 不管是 close 還是 keepalive; 都會(huì)強(qiáng)制設(shè)置為 close
- 如果 connection 為 close; 那么在 nginx 響應(yīng)完數(shù)據(jù)后, 會(huì)主動(dòng)關(guān)閉連接, 那么對(duì)請(qǐng)求比較大的 nginx 來(lái)說(shuō), 關(guān)掉 keepalive 最后會(huì)產(chǎn)生比較多的 time-wait 狀態(tài)的 socket; 一般來(lái)說(shuō), 當(dāng)客戶端的一次訪問(wèn), 需要多次訪問(wèn)同一個(gè) server 時(shí), 打開 keepalive 的優(yōu)勢(shì)非常大,
nginx 使用反向代理時(shí); 保持長(zhǎng)連接
- 長(zhǎng)連接的優(yōu)勢(shì)就是在一個(gè) tcp 連接上可以傳輸多個(gè) HTTP 請(qǐng)求, 減少建立連接和關(guān)閉連接的消耗和延遲
-
- 當(dāng) nginx 作為反向代理時(shí);
-
從 Client 到 Nginx 的連接是長(zhǎng)連接;
http { # 客戶端連接的超時(shí)時(shí)間, 為 0 時(shí)禁用長(zhǎng)連接, keepalive_timeout 120s; # 在一個(gè)長(zhǎng)連接上可以服務(wù)的最大請(qǐng)求數(shù)目, 當(dāng)達(dá)到最大請(qǐng)求數(shù)目且所有已有請(qǐng)求結(jié)束后, 連接被關(guān)閉, 默認(rèn)為 100, 即每個(gè)連接的最大請(qǐng)求數(shù) keepalive_request 10000; }
-
從 Nginx 到 Server(upstream) 的長(zhǎng)連接
http { upstream backend { server 192.168.0.1:8080 weight=1 max_fails=2 fail_timeout=30s; server 192.168.0.2:8080 weight=1 max_fails=2 fail_timeout=30s; # 這個(gè)參數(shù)非常重要 keepalive 300 } }
keepalive: 這個(gè)參數(shù)是 nginx 連接后端的連接池中的最大空閑連接數(shù), 比如: 設(shè)置為 300; 如果 nginx 為了滿足請(qǐng)求的 qps; 創(chuàng)建了 1000 個(gè)連接的連接池, 這個(gè)時(shí)候只有 500 個(gè)請(qǐng)求多來(lái), 那么 1000- 500 = 500; 那么就會(huì)多出 500 個(gè)空閑的連接, 那么 500 > 300; 那么 nginx 就會(huì)根據(jù)這個(gè)配置; 斷開 200 個(gè)請(qǐng)求連接; 那么這個(gè)時(shí)候就只有 800 個(gè)連接的連接池, 如果下次過(guò)來(lái)了 1000 個(gè)請(qǐng)求, 那么 nginx 又會(huì)開始創(chuàng)建連接; 所有這個(gè)數(shù)值的配置要小心配置