国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

聊一聊nginx中KeepAlive的設(shè)置

這篇具有很好參考價值的文章主要介紹了聊一聊nginx中KeepAlive的設(shè)置。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

問題

之前工作中遇到一個KeepAlive的問題,現(xiàn)在把它記錄下來,場景是這樣的:

聊一聊nginx中KeepAlive的設(shè)置

從上圖可以看出,用戶通過Client訪問的是LVS的VIP, VIP后端掛載的RealServer是Nginx服務器。 Client可以是瀏覽器也可以是一個客戶端程序。一般情況下, 這種架構(gòu)不會出現(xiàn)問題,但是如果Client端把請求發(fā)送給Nginx,Nginx的后端需要一段時間才能返回結(jié)果,超過1分30秒就會有問題,使用LVS作為負載均衡設(shè)備看到的現(xiàn)象就是1分30秒之后, Client和Nginx鏈接被斷開,沒有數(shù)據(jù)返回。

分析

原因是LVS默認保持TCP的Session為90s,超過90s沒有TCP報文在鏈接上傳輸,LVS就會給兩端發(fā)送RESET報文斷開鏈接。LVS這么做的原因相信大家都知道一二,我所知道的原因主要有兩點:

1.節(jié)省負載均衡設(shè)備資源,每一個TCP/UDP的鏈接都會在負載均衡設(shè)備上創(chuàng)建一個Session的結(jié)構(gòu), 鏈接如果一直不斷開,這種Session結(jié)構(gòu)信息最終會消耗掉所有的資源,所以必須釋放掉。
2.另外釋放掉能保護后端的資源,如果攻擊者通過空鏈接,鏈接到Nginx上,如果Nginx沒有做合適 的保護,Nginx會因為鏈接數(shù)過多而無法提供服務。
這種問題不只是在LVS上有,之前在商用負載均衡設(shè)備F5上遇到過同樣的問題,F(xiàn)5的Session斷開方式和LVS有點區(qū)別,F(xiàn)5不會主動發(fā)送RESET給鏈接的兩端,Session消失之后,當鏈接中一方再次發(fā)送報文時會接收到F5的RESET,
之后的現(xiàn)象是再次發(fā)送報文的一端TCP鏈接狀態(tài)已經(jīng)斷開,而另外一端卻還是ESTABLISH狀態(tài)。

知道是負載均衡設(shè)備原因之后,第一反應就是通過開啟KeepAlive來解決。到此這個問題應該是結(jié)束了,但是我發(fā)現(xiàn)過一段時間總又有人提起KeepAlive的問題,甚至發(fā)現(xiàn)由于KeepAlive的理解不正確浪費了很多資源,原本能使用LVS的應用放在了公網(wǎng)下沉區(qū),或者換成了商用F5設(shè)備(F5設(shè)備的Session斷開時間要長一點,默認應該是5分鐘)。所以我決定把我知道的KeepAlive知識點寫篇博客分享出來。

為什么要有KeepAlive?

在談KeepAlive之前,我們先來了解下簡單TCP知識(知識很簡單,高手直接忽略)。首先要明確的是在TCP層是沒有“請求”一說的,經(jīng)常聽到在TCP層發(fā)送一個請求,這種說法是錯誤的。TCP是一種通信的方式,“請求”一詞是事務上的概念,HTTP協(xié)議是一種事務協(xié)議,如果說發(fā)送一個HTTP請求,這種說法就沒有問題。也經(jīng)常聽到面試官反饋有些面試運維的同學,基本的TCP三次握手的概念不清楚, 面試官問TCP是如何建立鏈接,面試者上來就說,假如我是客戶端我發(fā)送一個請求給服務端,服務端發(fā)送一個請求給我。。。這種一聽就知道對TCP基本概念不清楚。下面是我通過wireshark抓取的一個TCP建立握手的過程。(命令行基本上用TCPdump,后面我們還會用這張圖說明問題):

聊一聊nginx中KeepAlive的設(shè)置

現(xiàn)在我看只要看前3行,這就是TCP三次握手的完整建立過程,第一個報文SYN從發(fā)起方發(fā)出,第二個報文SYN,ACK是從被連接方發(fā)出,第三個報文ACK確認對方的SYN,ACK已經(jīng)收到,如下圖:

聊一聊nginx中KeepAlive的設(shè)置

但是數(shù)據(jù)實際上并沒有傳輸,請求是有數(shù)據(jù)的,第四個報文才是數(shù)據(jù)傳輸開始的過程,細心的讀者應該能夠發(fā)現(xiàn)wireshark把第四個報文解析成HTTP協(xié)議,HTTP協(xié)議的GET方法和URI也解析出來,所以說TCP層是沒有請求的概念,HTTP協(xié)議是事務性協(xié)議才有請求的概念,TCP報文承載HTTP協(xié)議的請求(Request)和響應(Response)。

現(xiàn)在才是開始說明為什么要有KeepAlive。 鏈接建立之后,如果應用程序或者上層協(xié)議一直不發(fā)送數(shù)據(jù),或者隔很長時間才發(fā)送一次數(shù)據(jù),當鏈接很久沒有數(shù)據(jù)報文傳輸時如何去確定對方還在線,到底是掉線了還是確實沒有數(shù)據(jù)傳輸,鏈接還需不需要保持,這種情況在TCP協(xié)議設(shè)計中是需要考慮到的。TCP協(xié)議通過一種巧妙的方式去解決這個問題,當超過一段時間之后,TCP自動發(fā)送一個數(shù)據(jù)為空的報文給對方,如果對方回應了這個報文,說明對方還在線,鏈接可以繼續(xù)保持,如果對方?jīng)]有報文返回,并且重試了多次之后則認為鏈接丟失,沒有必要保持鏈接。

如何開啟KeepAlive
KeepAlive并不是默認開啟的,在Linux系統(tǒng)上沒有一個全局的選項去開啟TCP的KeepAlive。需要開啟KeepAlive的應用必須在TCP的socket中單獨開啟。Linux Kernel有三個選項影響到KeepAlive的行為:

1.net.ipv4.tcp_keepalive_intvl = 75
2.net.ipv4.tcp_keepalive_probes = 9
3.net.ipv4.tcp_keepalive_time = 7200

tcp_keepalive_time的單位是秒,表示TCP鏈接在多少秒之后沒有數(shù)據(jù)報文傳輸啟動探測報文; tcp_keepalive_intvl單位是也秒,表示前一個探測報文和后一個探測報文之間的時間間隔,tcp_keepalive_probes表示探測的次數(shù)。

TCP socket也有三個選項和內(nèi)核對應,通過setsockopt系統(tǒng)調(diào)用針對單獨的socket進行設(shè)置:

TCP_KEEPCNT: 覆蓋 tcp_keepalive_probes
TCP_KEEPIDLE: 覆蓋 tcp_keepalive_time
TCP_KEEPINTVL: 覆蓋 tcp_keepalive_intvl

舉個例子,以我的系統(tǒng)默認設(shè)置為例,kernel默認設(shè)置的tcp_keepalive_time是7200s, 如果我在應用程序中針對socket開啟了KeepAlive,然后設(shè)置的TCP_KEEPIDLE為60,那么TCP協(xié)議棧在發(fā)現(xiàn)TCP鏈接空閑了60s沒有數(shù)據(jù)傳輸?shù)臅r候就會發(fā)送第一個探測報文。

TCP KeepAlive和HTTP的Keep-Alive是一樣的嗎?

估計很多人乍看下這個問題才發(fā)現(xiàn)其實經(jīng)常說的KeepAlive不是這么回事,實際上在沒有特指是TCP還是HTTP層的KeepAlive,不能混為一談。TCP的KeepAlive和HTTP的Keep-Alive是完全不同的概念。TCP層的KeepAlive上面已經(jīng)解釋過了。 HTTP層的Keep-Alive是什么概念呢? 在講述TCP鏈接建立的時候,我畫了一張三次握手的示意圖,TCP在建立鏈接之后, HTTP協(xié)議使用TCP傳輸HTTP協(xié)議的請求(Request)和響應(Response)數(shù)據(jù),一次完整的HTTP事務如下圖:

聊一聊nginx中KeepAlive的設(shè)置

各位看官請注意,這張圖我簡化了HTTP(Req)和HTTP(Resp),實際上的請求和響應需要多個TCP報文。從圖中可以發(fā)現(xiàn)一個完整的HTTP事務,有鏈接的建立, 請求的發(fā)送,響應接收,斷開鏈接這四個過程,早期通過HTTP協(xié)議傳輸?shù)臄?shù)據(jù)以文本為主,一個請求可能就把所有要返回的數(shù)據(jù)取到,但是,現(xiàn)在要展現(xiàn)一張完整的頁面需要很多個請求才能完成,如圖片,JS,CSS等,如果每一個HTTP請求都需要新建并斷開一個TCP,這個開銷是完全沒有必要的,開啟HTTP Keep-Alive之后,能復用已有的TCP鏈接,當前一個請求已經(jīng)響應完畢,服務器端沒有立即關(guān)閉TCP鏈接,而是等待一段時間接收瀏覽器端可能發(fā)送過來的第二個請求,通常瀏覽器在第一個請求返回之后會立即發(fā)送第二個請求,如果某一時刻只能有一個鏈接,同一個TCP鏈接處理的請求越多,開啟KeepAlive能節(jié)省的TCP建立和關(guān)閉的消耗就越多。當然通常會啟用多個鏈接去從服務器器上請求資源,但是開啟了Keep-Alive之后,仍然能加快資源的加載速度。HTTP/1.1之后默認開啟Keep-Alive, 在HTTP的頭域中增加Connection選項。當設(shè)置為Connection:keep-alive表示開啟,設(shè)置為Connection:close表示關(guān)閉。實際上HTTP的KeepAlive寫法是Keep-Alive,跟TCP的KeepAlive寫法上也有不同。 所以TCP KeepAlive和HTTP的Keep-Alive不是同一回事情。

Nginx的TCP KeepAlive如何設(shè)置

開篇提到我最近遇到的問題,Client發(fā)送一個請求到Nginx服務端,服務端需要經(jīng)過一段時間的計算才會返回, 時間超過了LVS Session保持的90s,在服務端使用Tcpdump抓包,本地通過wireshark分析顯示的結(jié)果如第二副圖所示,第5條報文和最后一條報文之間的時間戳大概差了90s。在確定是LVS的Session保持時間到期的問題之后,我開始在尋找Nginx的TCP KeepAlive如何設(shè)置,最先找到的選項是keepalive_timeout,從同事那里得知keepalive_timeout的用法是當keepalive_timeout的值為0時表示關(guān)閉keepalive,當keepalive_timeout的值為一個正整數(shù)值時表示鏈接保持多少秒,于是把keepalive_timeout設(shè)置成75s,但是實際的測試結(jié)果表明并不生效。顯然keepalive_timeout不能解決TCP層面的KeepAlive問題,實際上Nginx涉及到keepalive的選項還不少,Nginx通常的使用方式如下:

聊一聊nginx中KeepAlive的設(shè)置

從TCP層面Nginx不僅要和Client關(guān)心KeepAlive,而且還要和Upstream關(guān)心KeepAlive, 同時從HTTP協(xié)議層面,Nginx需要和Client關(guān)心Keep-Alive,如果Upstream使用的HTTP協(xié)議,還要關(guān)心和Upstream的Keep-Alive,總而言之,還比較復雜。所以搞清楚TCP層的KeepAlive和HTTP的Keep-Alive之后,就不會對于Nginx的KeepAlive設(shè)置錯。我當時解決這個問題時候不確定Nginx有配置TCP keepAlive的選項,于是我打開Ngnix的源代碼,在源代碼里面搜索TCP_KEEPIDLE,相關(guān)的代碼如下:

519 #if (NGX_HAVE_KEEPALIVE_TUNABLE)
 520                 
 521         if (ls[i].keepidle) { 
 522             if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_KEEPIDLE,
 523                            (const void *) &ls[i].keepidle, sizeof(int))
 524                 == -1)
 525             {
 526                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno,
 527                               "setsockopt(TCP_KEEPIDLE, %d) %V failed, ignored",
 528                               ls[i].keepidle, &ls[i].addr_text);
 529             }
 530         }

從代碼的上下文我發(fā)現(xiàn)TCP KeepAlive可以配置,所以我接著查找通過哪個選項配置,最后發(fā)現(xiàn)listen指令的so_keepalive選項能對TCP socket進行KeepAlive的配置。

so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]
// on表示開啟
// off表示關(guān)閉

有些系統(tǒng)提供跟精確的控制,比如linux:

 keepidle表示等待時間,keepintvl表示探測報的發(fā)送間隔,keepcnt表示探測報文發(fā)送的次數(shù)。

以上三個參數(shù)只能使用一個,不能同時使用, 比如so_keepalive=on, so_keepalive=off或者so_keepalive=30s::(表示等待30s沒有數(shù)據(jù)報文發(fā)送探測報文)。通過設(shè)置listen 80,so_keepalive=60s::之后成功解決Nginx在LVS保持長鏈接的問題,避免了使用其他高成本的方案。在商用負載設(shè)備上如果遇到類似的問題同樣也可以通過這種方式解決。

Apache中KeepAlive和KeepAliveTimeOut

調(diào)優(yōu)apache參數(shù)一般都是根據(jù)場景去設(shè)置,這里分享下KeepAlive和KeepAliveTimeOut的關(guān)系與區(qū)別。

在Apache的httpd.conf中,KeepAlive指的是保持連接活躍,類似于數(shù)據(jù)庫中的永久連接。若將KeepAlive設(shè)置為On,那么來自同一客戶端的請求就不需要再一次連接,避免每次請求都要新建一個連接而加重服務器的負擔。

KeepAlive的連接活躍時間當然是受KeepAliveTimeOut限制的。如果第二次請求和第一次請求之間超過KeepAliveTimeOut的時間的話,第一次連接就會中斷,再新建第二個連接。所以,一般情況下,圖片較多的網(wǎng)站應該把KeepAlive設(shè)為On。但是KeepAliveTimeOut應該設(shè)置為多少秒就是一個值得討論的問題了。這里如果KeepAliveTimeOut設(shè)置的時間過短,比如設(shè)置=1秒,那么Apache就會頻繁的建立New Link,就會耗費不少的資源;反過來,如果KeepAliveTimeOut設(shè)置的時間過長,比如設(shè)置超過200秒,那么APACHE中肯定有很多無用的連接會占用服務器的資源,也不是一件好事。所以,到底要把KeepAliveTimeOut設(shè)置為多少,要看網(wǎng)站的流量、服務器的配置而定。

其實,這和數(shù)據(jù)庫比如mysql中的連接機制有點類似,KeepAlive相當于mysql_connectmysql_pconnect,KeepAliveTimeOut相當于wait_timeout。

參考資料

-《TCP/IP協(xié)議詳解VOL1》–網(wǎng)絡(luò)基礎(chǔ)知識詳盡介紹文章來源地址http://www.zghlxwxcb.cn/news/detail-428351.html

  • http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/#overview
  • http://nginx.org/en/docs/http/ngx_http_core_module.html
  • Nginx Source code: https://github.com/alibaba/tengine

到了這里,關(guān)于聊一聊nginx中KeepAlive的設(shè)置的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務器費用

相關(guān)文章

  • 聊一聊synchronized

    在 Java 中, synchronized 可以用于實現(xiàn)線程同步,有以下幾種常見的使用方式: 修飾代碼塊:將 synchronized 放在代碼塊的前面, 例如: 在這種方式下,會為給定的對象 obj 獲取鎖,在代碼塊執(zhí)行期間,只有持有該鎖的線程才能進入代碼塊執(zhí)行。 修飾方法:將 sync

    2024年01月22日
    瀏覽(27)
  • 聊一聊AIGC

    聊一聊AIGC

    “UGC不存在了”——借鑒自《三體》 ChatGPT 的橫空出世將一個全新的概念推上風口——AIGC( AI Generated Content)。 GC即創(chuàng)作內(nèi)容(Generated Content),和傳統(tǒng)的UGC、PGC,OGC不同的是,AIGC的創(chuàng)作主體由人變成了人工智能。 xGC PGC:Professionally Generated Content,專業(yè)生產(chǎn)內(nèi)容 UGC:User G

    2024年02月10日
    瀏覽(23)
  • 聊一聊模板方法模式

    聊一聊模板方法模式

    統(tǒng)一抽取,制定規(guī)范; 模板方法模式,又叫模板模式,屬于23種設(shè)計模式中的 行為型模式 。在抽象類中公開定義了執(zhí)行的方法,子類可以按需重寫其方法,但是要以抽象類中定義的方式調(diào)用方法??偨Y(jié)起來就是: 定義一個操作的算法結(jié)構(gòu),而將一些步驟延遲到子類中。在不

    2024年02月04日
    瀏覽(26)
  • 聊一聊適配器模式

    聊一聊適配器模式

    接口不能用?行,我?guī)湍氵m配 適配器模式(Adapter),是23種設(shè)計模式中的 結(jié)構(gòu)型模式 之一;它就像我們電腦上接口不夠時,需要用到的拓展塢,起到轉(zhuǎn)接的作用。它可以將新的功能和原先的功能連接起來,使由于需求變動導致不能用的功能,重新利用起來。 上圖的Mac上,只

    2024年02月04日
    瀏覽(25)
  • 聊一聊Vue和Ts

    1 前言 Vue3 已經(jīng)正式發(fā)布了一段時間了,各種生態(tài)已經(jīng)成熟。最近使用 taro+vue3 重構(gòu)冷鏈的小程序,經(jīng)過了一段時間的開發(fā)和使用,有了一些自己的思考。 總的來說,Vue3 無論是在底層原理還是在實際開發(fā)過程中,都有了很大的進步。 從源碼層面來說,使用 Proxy 代替 Object.d

    2023年04月08日
    瀏覽(26)
  • 聊一聊mysql中的間隙鎖

    聊一聊mysql中的間隙鎖

    間隙鎖在mysql中經(jīng)常使用到,今天就聊一聊mysql的間隙鎖的內(nèi)容。 間隙鎖是為了解決幻讀的問題,并且在當前讀的場景下解決的。 當前讀包含:update,delete,insert,select…lock in share mode,select…for update 一基本概念 1、行鎖:給某一行進行加鎖 2、間隙鎖:兩個值之間的間隙,為解

    2024年02月12日
    瀏覽(23)
  • 聊一聊Java抽象同步隊列AQS

    聊一聊Java抽象同步隊列AQS

    AQS是鎖的底層支持 由該圖可以看到,AQS是一個FIFO的雙向隊列,其內(nèi)部通過節(jié)點head和tail記錄隊首和隊尾元素,隊列元素的類型為Node。其中Node中的thread變量用來存放進入AQS隊列里面的線程;Node節(jié)點內(nèi)部的SHARED用來標記該線程是獲取共享資源時被阻塞掛起后放入AQS隊列的,EX

    2024年02月16日
    瀏覽(33)
  • 聊一聊 .NET高級調(diào)試 內(nèi)核模式堆泄露

    聊一聊 .NET高級調(diào)試 內(nèi)核模式堆泄露

    前幾天有位朋友找到我,說他的機器內(nèi)存在不斷的上漲,但在任務管理器中查不出是哪個進程吃的內(nèi)存,特別奇怪,截圖如下: 在我的分析旅程中都是用戶態(tài)模式的內(nèi)存泄漏,像上圖中的異常征兆已經(jīng)明確告訴你了,不是用戶態(tài)程序吃的內(nèi)存,那就是內(nèi)核態(tài)程序吃的,比如:

    2024年02月04日
    瀏覽(20)
  • 聊一聊近期測試行情以及個人的感受

    聊一聊近期測試行情以及個人的感受

    眾所周知,去年年底的裁員潮再加上今年的疫情影響,失業(yè)、找工作成為了蠻多人的當務之急。最近一些招聘網(wǎng)站也出現(xiàn)被刷爆的情況,其中順利找到工作的并不多,說明行情很冷,但是總有許多人順利跳槽。 其實對于大牛來說,行業(yè)是否景氣,影響真不大。反而有時候更容

    2024年02月09日
    瀏覽(15)
  • C++面試八股文:聊一聊指針?

    C++面試八股文:聊一聊指針?

    某日二師兄參加XXX科技公司的C++工程師開發(fā)崗位第17面: 面試官:聊一聊指針? 二師兄:好的。 面試官:你覺得指針本質(zhì)上是什么? 二師兄:這要從內(nèi)存地址開始說起了。如果有一塊容量是1G的內(nèi)存,假設(shè)它的地址是從 0x00000000 到 0x3fffffff ,每一個字節(jié)都對應一個地址。當

    2024年02月09日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包