nginx keepalive的具體使用
默認(rèn)http1.1協(xié)議的請求頭是默認(rèn)開啟keepalive,如圖:
那什么是keepalive?作用是什么?
keepalive是在TCP中一個可以檢測死連接的機制,作用是保持socket長連接不被斷開,屬于tcp層的功能,并不屬于應(yīng)用層。
TCP層怎么做到保持長連接的呢?
先看keepalive的用法:有三個參數(shù),開放給應(yīng)用層使用
sk->keepalive_probes:探測次數(shù),重試次數(shù) sk->keepalive_time 探測的心跳間隔,TCP鏈接在多少秒之后沒有數(shù)據(jù)報文傳輸啟動探測報文 sk->keepalive_intvl 探測間隔,未收到回復(fù)時,重試的時間間隔
默認(rèn)配置查看:
[***@*** ~]$ cat /proc/sys/net/ipv4/tcp_keepalive_time 7200 [***@*** ~]$ cat /proc/sys/net/ipv4/tcp_keepalive_intvl 75 [***@*** ~]$ cat /proc/sys/net/ipv4/tcp_keepalive_probes 9
使用方法:
int keepalive = 1; // 開啟keepalive屬性 int keepidle = 60; // 如該連接在60秒內(nèi)沒有任何數(shù)據(jù)往來,則進行探測 int keepinterval = 5; // 探測時發(fā)包的時間間隔為5 秒 int keepcount = 3; // 探測嘗試的次數(shù)。如果第1次探測包就收到響應(yīng)了,則后2次的不再發(fā)。并且清零該計數(shù) setsockopt(rs, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepalive , sizeof(keepalive )); setsockopt(rs, SOL_TCP, TCP_KEEPIDLE, (void*)&keepidle , sizeof(keepidle )); setsockopt(rs, SOL_TCP, TCP_KEEPINTVL, (void *)&keepinterval , sizeof(keepinterval )); setsockopt(rs, SOL_TCP, TCP_KEEPCNT, (void *)&keepcount , sizeof(keepcount ));
應(yīng)用層這么設(shè)置后,會把默認(rèn)配置覆蓋,走手動設(shè)置的配置。
對于一個已經(jīng)建立的tcp連接。如果在keepalive_time時間內(nèi)雙方?jīng)]有任何的數(shù)據(jù)包傳輸,則開啟keepalive功能的一端將發(fā)送 keepalive數(shù)據(jù)心跳包,若沒有收到應(yīng)答,則每隔keepalive_intvl時間再發(fā)送該數(shù)據(jù)包,發(fā)送keepalive_probes次。一直沒有 收到應(yīng)答,則發(fā)送rst包關(guān)閉連接。若收到應(yīng)答,則將計時器清零。
抓包驗證tcp心跳包內(nèi)容
根據(jù)抓包繼續(xù)分析keepalive發(fā)送及回復(fù)的心跳包內(nèi)容:
tcp頭部結(jié)構(gòu)體源碼為:
typedef struct _TCP_HEADER { short m_sSourPort; // 源端口號16bit short m_sDestPort; // 目的端口號16bit unsigned int m_uiSequNum; // req字段 序列號32bit unsigned int m_uiAcknowledgeNum; //ack字段 確認(rèn)號32bit short m_sHeaderLenAndFlag; // 前4位:TCP頭長度;中6位:保留;后6位:標(biāo)志位 short m_sWindowSize; //win字段 窗口大小16bit short m_sCheckSum; // 檢驗和16bit short m_surgentPointer; // 緊急數(shù)據(jù)偏移量16bit }__attribute__((packed))TCP_HEADER, *PTCP_HEADER;
看發(fā)送的心跳包內(nèi)容:
0000 d4 6d 50 f5 02 7f f4 5c 89 cb 35 29 08 00 //mac頭 14字節(jié): 45 00 // ip頭 20字節(jié) : 0010 00 28 10 f4 00 00 40 06 5b dd ac 19 42 76 0a b3 0020 14 bd e4 4a 1f 7c 32 7e 7a cb 4c bc 55 08 50 10 // tcp頭 20字節(jié) 0030 10 00 3f 00 00 00 //分析tcp頭部內(nèi)容 e4 4a //源端口號16bit 10進制為:58442 1f 7c //目的端口號16bit 10進制為 : 8060 32 7e 7a cb // req字段 序列號32bit 10進制為 : 4c bc 55 08 // ack字段 確認(rèn)號32bit 5 // 前4位:TCP頭長度 5*4 =20 字節(jié) 沒問題 0 10 /// 中6位:保留;后6位:標(biāo)志位 10 代表倒數(shù)第5位為1, 標(biāo)識改tcp包為 ACK 確認(rèn)包 0030 10 00 3f 00 00 00
繼續(xù)看回復(fù)的心跳包內(nèi)容 :
0000 f4 5c 89 cb 35 29 d4 6d 50 f5 02 7f 08 00 45 00 0010 00 34 47 28 40 00 36 06 ef 9c 0a b3 14 bd ac 19 0020 42 76 // 前面數(shù)據(jù)不解讀 1f 7c e4 4a 4c bc 55 08 32 7e 7a cc 8// TCP頭長度為8 * 4 = 32 除了頭部 還有 選項數(shù)據(jù) 12字節(jié) 0 10 // 中6位:保留;后6位:標(biāo)志位 10 代表倒數(shù)第5位為1, 標(biāo)識該tcp包為 ACK 確認(rèn)包 0030 01 3f //win字段 窗口大小16bit 4e 0d // 檢驗和16bit 00 00 // 緊急數(shù)據(jù)偏移量16bit 01 01 08 0a 00 59 be 1c 39 13 0040 cf 12 // 選項數(shù)據(jù) 12字節(jié)
由上可以看出,tcp維持長連接的心跳包是由瀏覽器向服務(wù)器先出發(fā)送一個ACK包,然后服務(wù)器再回復(fù)一個ACK包,且?guī)Я诉x項數(shù)據(jù)
nginx會怎么處理keepalive請求,都會做哪些事情?
首先做的是版本判斷 :http協(xié)議版本低于1.1時,該鏈接的keepalive置為0 if (r->http_version < NGX_HTTP_VERSION_11) { r->keepalive = 0; } ngx_http_process_connection 函數(shù)中 ngx_http_request_t 中帶有keep-alive則把改鏈接標(biāo)識起來 if (ngx_strcasestrn(h->value.data, "keep-alive", 10 - 1)) { r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE; } ngx_http_handler函數(shù)中對r->headers_in.connection_type 判斷,給r->keepalive賦值為1 switch (r->headers_in.connection_type) { case NGX_HTTP_CONNECTION_KEEP_ALIVE: r->keepalive = 1; break; } ngx_configure_listening_sockets函數(shù)中,當(dāng)keepalive為1時,對該連接開啟KEEPALIVE,之后tcp底層就會對該連接fd做檢測死連接的機制,保持長連接,不斷開。 if (ls[i].keepalive) { value = (ls[i].keepalive == 1) ? 1 : 0; if (setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,//開啟keepalive功能 (const void *) &value, sizeof(int)) == -1) }
nginx什么時候長連接會斷開呢?
在nginx通過 setsockopt(ls[i].fd, SOL_SOCKET, SO_KEEPALIVE,(const void *) &value, sizeof(int))開啟keepalive后,會始終和客戶端保持長連接,如此會出現(xiàn)一個很嚴(yán)峻的問題,每個woker的能保持的連接數(shù)是有限的(ep = epoll_create(cycle->connection_n / 2); cycle->connection_n / 2 為epoll能管理的fd上限),如此一來,連接數(shù)很快就被耗盡,這時候nginx應(yīng)該怎么處理 ?
為了找到這個答案,我們來看nginx關(guān)于keeoalive的兩個配置參數(shù)
keepalive_timeout
keepalive_timeout timeout [header_timeout];
第一個參數(shù):設(shè)置keep-alive客戶端連接在服務(wù)器端保持開啟的超時值(默認(rèn)75s);值為0會禁用keep-alive客戶端連接;
第二個參數(shù):可選、在響應(yīng)的header域中設(shè)置一個值“Keep-Alive: timeout=time”;通??梢圆挥迷O(shè)置;
注:keepalive_timeout默認(rèn)75s
keepalive_requests
keepalive_requests指令用于設(shè)置一個keep-alive連接上可以服務(wù)的請求的最大數(shù)量,當(dāng)最大請求數(shù)量達(dá)到時,連接被關(guān)閉,值為0會也禁用keep-alive客戶端連接;。默認(rèn)是100。
答案顯而易見,通過 keepalive_timeout keepalive_requests 來管理長連接,
- 當(dāng)一個tcp連接存活時間超過 keepalive_timeout 時則會被close掉,nginx的具體實現(xiàn),是通過定時器來做的
- 當(dāng)一個tcp連接最大情書數(shù)超過 keepalive_requests 時則也會被close掉
通過這兩個機制來保證每個worker的連接數(shù)不會超過epoll所能管理的數(shù)目。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Nginx中報錯:Permission denied與Connection refused的解決
這篇文章主要給大家介紹了在Nginx中報錯:13: Permission denied與111: Connection refused的解決方法,文中介紹的非常詳細(xì),相信對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-04-04為高負(fù)載網(wǎng)絡(luò)優(yōu)化Nginx和Node.js的方法
如果不先對Nginx和Node.js的底層傳輸機制有所了解,并進行針對性優(yōu)化,可能對兩者再細(xì)致的調(diào)優(yōu)也會徒勞無功。一般情況下,Nginx通過TCP socket來連接客戶端與上游應(yīng)用2013-02-02Nginx+Tomcat負(fù)載均衡集群安裝配置案例詳解
Nginx是一款非常優(yōu)秀的http服務(wù)器軟件,它能夠支持高達(dá)50000個并發(fā)連接數(shù)的相應(yīng),Nginx+Tomcat負(fù)載均衡集案列是應(yīng)用于生產(chǎn)環(huán)境的一套可靠的Web站點解決方案,對Nginx Tomcat負(fù)載均衡集群相關(guān)知識感興趣的朋友一起看看吧2021-10-10利用nginx與ffmpeg搭建流媒體服務(wù)器過程詳解
這篇文章主要給大家介紹了利用nginx與ffmpeg搭建流媒體服務(wù)器的全過程,文中介紹的很詳細(xì),對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。2017-03-03Nginx訪問FTP服務(wù)器文件的時效性/安全校驗的方法
nginx的實現(xiàn)方式在校驗失敗的時候頁面返回error image,跳轉(zhuǎn)的是420 error_page,成功的時候會訪問FTP文件服務(wù)器的路徑,反正圖片到頁面展示,這篇文章主要介紹了Nginx訪問FTP服務(wù)器文件的時效性/安全校驗,需要的朋友可以參考下2023-12-12Nginx根據(jù)url中的path動態(tài)轉(zhuǎn)發(fā)到upstream的實現(xiàn)
這篇文章主要介紹了Nginx根據(jù)url中的path動態(tài)轉(zhuǎn)發(fā)到upstream的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01linux(centos5.5)/windows下nginx開啟phpinfo模式功能的配置方法分享
某站點用到結(jié)合phpinfo功能的urlrewrite,在nginx中需要在nginx.conf文件中進行配置才可支持phpinfo2013-02-02nginx 作為反向代理實現(xiàn)負(fù)載均衡的例子
以下我們就來舉例說明如何使用 nginx 實現(xiàn)負(fù)載均衡。因為nginx在處理并發(fā)方面的優(yōu)勢,現(xiàn)在這個應(yīng)用非常常見。2010-12-12