緣起雙十一如期而至,此時(shí)的我因?yàn)樵谔幚砜蛻舻囊粋€(gè)問(wèn)題已經(jīng)陷入了忙碌,。突然,,不斷接到駐場(chǎng)實(shí)施發(fā)來(lái)的反饋,,都是相同的反饋——”客戶端操作緩慢”。 我現(xiàn)在負(fù)責(zé)的服務(wù)器是一臺(tái)接口服務(wù)器,,所有的賣家都要通過(guò)這臺(tái)服務(wù)器連接到自己的數(shù)據(jù)庫(kù)上,,不得小覷。于是我立馬放下手頭的話,,打開了我事先安裝好的服務(wù)器監(jiān)控軟件(netdata),,便看到了下面的警告: 其實(shí),作為一個(gè)服務(wù)器端新手,,我并不知道什么意思,。但是客戶反饋慢啊,!屁股一想也知道是因?yàn)榉?wù)器資源不夠了嘛,!于是,我立馬把一小部分客戶的配置切換到了另外一臺(tái)準(zhǔn)備好的服務(wù)器上,,危機(jī)化解了,,我擦了一把汗。 所以,,什么是tcp accept queue,?通過(guò)搜索這個(gè)警告,找到了一個(gè)叫backlog的關(guān)鍵字,,網(wǎng)上很多辦法是增大這個(gè)值,,因?yàn)楫?dāng)時(shí)雙十一已經(jīng)過(guò)去了,客戶已經(jīng)沒(méi)有那么多單子發(fā)貨了,。所以,,也沒(méi)有驗(yàn)證這個(gè)方法是否對(duì)不對(duì)。但backlog的迷還一直留在我的腦海里,。 直到有一天,,我遇到了上面的一篇文章,才對(duì)backlog有較為具體的認(rèn)識(shí),。我簡(jiǎn)單的根據(jù)文中的意思介紹下backlog參數(shù)。 本圖片來(lái)自coolshell.cn要搞清楚這個(gè)問(wèn)題,,我們必須要先了解下tcp建立鏈接的三次握手,,從圖中可以看出,第一次握手是客戶端給服務(wù)器發(fā)送syn,,此時(shí)服務(wù)器進(jìn)入SYN_RECV狀態(tài)(也叫未完成鏈接,對(duì)應(yīng)圖中的SYN_RCVD),,那么既然是一個(gè)服務(wù)器,所以接受這樣的鏈接就不是一個(gè),,是很多,,所以會(huì)有一個(gè)隊(duì)列去記錄這樣的未完成鏈接,,暫且稱為syn隊(duì)列。 第一次握手完成后,,服務(wù)器會(huì)給客戶端發(fā)送 SYN+ACK,,客戶端收到后,這個(gè)鏈接在客戶端方面已經(jīng)是ESTABLISHED狀態(tài)了,??蛻舳私又鴷?huì)給服務(wù)器發(fā)送ACK,當(dāng)服務(wù)器收到這個(gè)ACK的時(shí)候,,服務(wù)器上的該鏈接由SYN_RECV 狀態(tài)到ESTABLISHED狀態(tài),,此時(shí)它進(jìn)入了一個(gè)新隊(duì)列,這里叫它accept隊(duì)列,。顧明思議就是供accept來(lái)消耗的請(qǐng)求,。 兩個(gè)隊(duì)列的長(zhǎng)度限制由什么參數(shù)決定?經(jīng)過(guò)上面分析,,我們知道服務(wù)器端處理的請(qǐng)求鏈接是有兩個(gè)隊(duì)列來(lái)控制,,syn隊(duì)列(對(duì)應(yīng)圖中的syns queue)是等待客戶端回復(fù)ack的鏈接,叫做未完成鏈接或者半連接,,而完成三次握手后,,該鏈接進(jìn)入accept隊(duì)列,那么這兩個(gè)隊(duì)列的長(zhǎng)度是多少呢,? 圖片來(lái)源 http://jm./2017/05/25/525-1/由上圖可以看出,,syn隊(duì)列就是由 /proc/sys/net/ipv4/tcp_max_syn_backlog參數(shù)來(lái)控制。處于這個(gè)隊(duì)列上的鏈接需要等待的全雙工的通信時(shí)間,,所以如果這個(gè)參數(shù)開的太小,,可能對(duì)于一些并發(fā)性比較高的http服務(wù)器來(lái)說(shuō),容易成為瓶頸,。因?yàn)檫@個(gè)syns隊(duì)列滿了以后,,新的請(qǐng)求就因?yàn)殛?duì)列滿的緣故而被忽略(有待進(jìn)一步驗(yàn)證,本人在實(shí)際測(cè)試中,,把隊(duì)列長(zhǎng)度調(diào)整的很小,,并發(fā)測(cè)試幾乎不出現(xiàn)syn queue溢出的情況)。 而accept函數(shù)是有兩個(gè)參數(shù)共同決定的,,分別是系統(tǒng)函數(shù)listen函數(shù)的backlog參數(shù)以及內(nèi)核參數(shù)somaxconn,,這兩者會(huì)取最小值,如果應(yīng)用服務(wù)器能夠很快的從accept隊(duì)列中取出任務(wù)并執(zhí)行,,這個(gè)隊(duì)列并不會(huì)成為負(fù)擔(dān),,但如果每個(gè)請(qǐng)求都要耗費(fèi)很長(zhǎng)時(shí)間處理的話,那么服務(wù)器處理線程將會(huì)被打滿,,這個(gè)時(shí)候accept隊(duì)列就會(huì)被占滿,。 accept隊(duì)列被占滿的時(shí)候,,會(huì)引入一個(gè)新的問(wèn)題,那就是此時(shí)如果未完成鏈接接收到客戶端的ack完成三次握手,,需要轉(zhuǎn)入accept隊(duì)列,,此時(shí)該怎么辦?此時(shí),,如果 關(guān)于syn隊(duì)列長(zhǎng)度的限制,,大部分文獻(xiàn)說(shuō)的是由 tcp_max_syn_backlog 參數(shù)控制,但也有部分博客有更詳細(xì)的說(shuō)明,,認(rèn)為syn隊(duì)列不僅僅受控制與該參數(shù),,帶著這個(gè)疑問(wèn),我也看了些源碼: linux 內(nèi)核源碼文件 request_sock.c以上linux源碼中,,max_qlen_log中代表syn隊(duì)列的最大長(zhǎng)度,,sysctl_max_syn_backlog 即是tcp_max_syn_backlog參數(shù)的值。第一行的nr_table_entries 是計(jì)算這個(gè)最大值的因子,,它是作為一個(gè)參數(shù)傳入進(jìn)來(lái)的,,它是傳入的backlog參數(shù),上面已經(jīng)介紹過(guò)backlog參數(shù)是內(nèi)核參數(shù)somaxconn和listen函數(shù)中傳入的backlog的最小值,,而通過(guò)第一行源碼我們可以看出來(lái),,這里syn隊(duì)列的最大值是取backlog 和 tcp_max_syn_backlog的最小值,因此得到以下結(jié)論: syn queue length = min(somaxconn,backlog,tcp_max_syn_backlog) accept queue length = min(somaxconn,backlog) 實(shí)驗(yàn)驗(yàn)證口說(shuō)無(wú)憑,,下面進(jìn)行一個(gè)實(shí)驗(yàn),,來(lái)按照上面的理論分析下。 準(zhǔn)備 OS 云機(jī) 1核1G的入門機(jī) 服務(wù)器是nginx + php-fpm 服務(wù)器監(jiān)控軟件netdata ab壓測(cè)工具 step 1 : 參數(shù)設(shè)置 經(jīng)過(guò)上面對(duì)兩個(gè)隊(duì)列的長(zhǎng)度限制分析知道somaxconn參數(shù)對(duì)兩個(gè)隊(duì)列有影響,,于是設(shè)置somaxconn的值為8,,其他backlog參數(shù)均為1024。 net.ipv4.tcp_max_syn_backlog = 1024 net.core.somaxconn = 8 net.ipv4.tcp_syncookies = 0 為了避免其他因素的影響我們的測(cè)試php文件中只有一句
step2: 開始?jí)簻y(cè) ab 壓測(cè) 工具并發(fā)512個(gè)請(qǐng)求,,請(qǐng)求總數(shù)5120個(gè) step3:netdata得到以下危險(xiǎn)警告 此時(shí),可以看到兩個(gè)隊(duì)列都已經(jīng)開始drop鏈接了,。 step4:將somaxconn參數(shù)為1024,,再次相同條件壓測(cè)發(fā)現(xiàn)已經(jīng)沒(méi)有警告提示了 結(jié)論:通過(guò)合理的參數(shù)設(shè)置,,是可以提高服務(wù)器報(bào)警的門檻,將參數(shù)調(diào)整到服務(wù)器能夠承受的最大值,,確實(shí)可以在一定程度上提高服務(wù)器的容量,。一方面,隊(duì)列增大后,,可以暫時(shí)容納這些隊(duì)列,,供應(yīng)用程序消耗。如果隊(duì)列設(shè)置過(guò)小,,那么新來(lái)的鏈接就會(huì)被忽略,,客戶端還會(huì)進(jìn)行重試,另一方面如果accept很快被充滿的話,,syn隊(duì)列會(huì)被阻塞,,而且syn隊(duì)列上的鏈接仍要去消耗資源對(duì)客戶端重新發(fā)送syn+ack,導(dǎo)致一個(gè)惡性循環(huán)。 但這不意味著盡量調(diào)整參數(shù)就可以萬(wàn)事大吉了,,在一些突發(fā)訪問(wèn)的網(wǎng)絡(luò)中,,調(diào)大參數(shù)可以緩解網(wǎng)絡(luò)情況,但此時(shí)客戶端訪問(wèn)服務(wù)器肯定不會(huì)很快,,因?yàn)榉?wù)器已經(jīng)陷入了繁忙狀態(tài),。如果服務(wù)器一直處于報(bào)警狀態(tài),即鏈接不是突發(fā)性的,,而是長(zhǎng)時(shí)間處于一個(gè)比較高的數(shù)量,,那么就需要進(jìn)行優(yōu)化了。優(yōu)化分為兩方面,,第一方面應(yīng)用程序的優(yōu)化,,即讓每個(gè)鏈接的處理速度加快,這樣線程可以快速的釋放,,accept消耗加快,,服務(wù)器處理速度加快。另外一方面,,就是擴(kuò)容服務(wù)器,,通過(guò)負(fù)載均衡水平擴(kuò)展計(jì)算資源,讓鏈接分配到不同機(jī)器上快速消耗,。 |
|
來(lái)自: lxylibary > 《網(wǎng)絡(luò)》