日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

分析從Linux源碼看TIME_WAIT的持續(xù)時間

瀏覽:304日期:2024-04-09 08:26:35
目錄一、前言二、首先介紹下Linux環(huán)境三、TIME_WAIT狀態(tài)轉(zhuǎn)移圖四、持續(xù)時間真如TCP_TIMEWAIT_LEN所定義么?五、TIME_WAIT定時器源碼5.1、inet_twsk_schedule5.2、具體的清理函數(shù)5.3、先作出一個假設(shè)5.4、如果一個slot中的TIME_WAIT<=1005.5、如果一個slot中的TIME_WAIT>1005.6、PAWS(Protection Against Wrapped Sequences)使得TIME_WAIT延長一、前言

筆者一直以為在Linux下TIME_WAIT狀態(tài)的Socket持續(xù)狀態(tài)是60s左右。線上實(shí)際卻存在TIME_WAIT超過100s的Socket。由于這牽涉到最近出現(xiàn)的一個復(fù)雜Bug的分析。所以,筆者就去Linux源碼里面,一探究竟。

二、首先介紹下Linux環(huán)境

TIME_WAIT這個參數(shù)通常和五元組重用扯上關(guān)系。在這里,筆者先給出機(jī)器的內(nèi)核參數(shù)設(shè)置,以免和其它問題相混淆。

cat /proc/sys/net/ipv4/tcp_tw_reuse 0

cat /proc/sys/net/ipv4/tcp_tw_recycle 0

cat /proc/sys/net/ipv4/tcp_timestamps 1

可以看到,我們設(shè)置了tcp_tw_recycle為0,這可以避免NAT下tcp_tw_recycle和tcp_timestamps同時開啟導(dǎo)致的問題。

三、TIME_WAIT狀態(tài)轉(zhuǎn)移圖

提到Socket的TIME_WAIT狀態(tài),不得就不亮出TCP狀態(tài)轉(zhuǎn)移圖了:

分析從Linux源碼看TIME_WAIT的持續(xù)時間

持續(xù)時間就如圖中所示的2MSL。但圖中并沒有指出2MSL到底是多長時間,但筆者從Linux源碼里面翻到了下面這個宏定義。

#define TCP_TIMEWAIT_LEN (60*HZ) /* how long to wait to destroy TIME-WAIT * state, about 60 seconds*/

如英文字面意思所示,60s后銷毀TIME_WAIT狀態(tài),那么2MSL肯定就是60s嘍?

四、持續(xù)時間真如TCP_TIMEWAIT_LEN所定義么?

筆者之前一直是相信60秒TIME_WAIT狀態(tài)的socket就能夠被Kernel回收的。甚至筆者自己做實(shí)驗(yàn)telnet一個端口號,人為制造TIME_WAIT,自己計時,也是60s左右即可回收。

分析從Linux源碼看TIME_WAIT的持續(xù)時間

但在追查一個問題時候,發(fā)現(xiàn),TIME_WAIT有時候能夠持續(xù)到111s,不然完全無法解釋問題的現(xiàn)象。這就逼得筆者不得不推翻自己的結(jié)論,重新細(xì)細(xì)閱讀內(nèi)核對于TIME_WAIT狀態(tài)處理的源碼。當(dāng)然,這個追查的問題也會寫成博客分享出來,敬請期待_。

五、TIME_WAIT定時器源碼

談到TIME_WAIT何時能夠被回收,不得不談到TIME_WAIT定時器,這個就是專門用來銷毀到期的TIME_WAIT Socket的。而每一個Socket進(jìn)入TIME_WAIT時,必然會經(jīng)過下面的代碼分支:

tcp_v4_rcv

|->tcp_timewait_state_process

/* 將time_wait狀態(tài)的socket鏈入時間輪

|->inet_twsk_schedule

由于我們的kernel并沒有開啟tcp_tw_recycle,所以最終的調(diào)用為:

/* 這邊TCP_TIMEWAIT_LEN 60 * HZ */inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN, TCP_TIMEWAIT_LEN);

好了,讓我們按下這個核心函數(shù)吧。

5.1、inet_twsk_schedule

在閱讀源碼前,先看下大致的處理流程。Linux內(nèi)核是通過時間輪來處理到期的TIME_WAIT socket,如下圖所示:

分析從Linux源碼看TIME_WAIT的持續(xù)時間

內(nèi)核將60s的時間分為8個slot(INET_TWDR_RECYCLE_SLOTS),每個slot處理7.5(60/8)范圍time_wait狀態(tài)的socket。

void inet_twsk_schedule(struct inet_timewait_sock *tw,struct inet_timewait_death_row *twdr,const int timeo, const int timewait_len){......// 計算時間輪的slotslot = (timeo + (1 << INET_TWDR_RECYCLE_TICK) - 1) >> INET_TWDR_RECYCLE_TICK;......// 慢時間輪的邏輯,由于沒有開啟TCP_TW_RECYCLE,timeo總是60*HZ(60s)// 所有都走slow_timer邏輯 if (slot >= INET_TWDR_RECYCLE_SLOTS) {/* Schedule to slow timer */if (timeo >= timewait_len) {slot = INET_TWDR_TWKILL_SLOTS - 1;} else {slot = DIV_ROUND_UP(timeo, twdr->period);if (slot >= INET_TWDR_TWKILL_SLOTS)slot = INET_TWDR_TWKILL_SLOTS - 1;}tw->tw_ttd = jiffies + timeo;// twdr->slot當(dāng)前正在處理的slot// 在TIME_WAIT_LEN下,這個邏輯一般7slot = (twdr->slot + slot) & (INET_TWDR_TWKILL_SLOTS - 1);list = &twdr->cells[slot];} else{// 走短時間定時器,由于篇幅原因,不在這里贅述......}....../* twdr->period 60/8=7.5 */if (twdr->tw_count++ == 0)mod_timer(&twdr->tw_timer, jiffies + twdr->period);spin_unlock(&twdr->death_lock);}

從源碼中可以看到,由于我們傳入的timeout皆為TCP_TIMEWAIT_LEN。所以,每次剛成為的TIME_WAIT狀態(tài)的socket即將鏈接到當(dāng)前處理slot最遠(yuǎn)的slot(+7)以便處理。如下圖所示:

分析從Linux源碼看TIME_WAIT的持續(xù)時間

如果Kernel不停的產(chǎn)生TIME_WAIT,那么整個slow timer時間輪就會如下圖所示:

分析從Linux源碼看TIME_WAIT的持續(xù)時間

所有的slot全部掛滿了TIME_WAIT狀態(tài)的Socket。

5.2、具體的清理函數(shù)

每次調(diào)用inet_twsk_schedule時候傳入的處理函數(shù)都是:

/*參數(shù)中的tcp_death_row即為承載時間輪處理函數(shù)的結(jié)構(gòu)體*/inet_twsk_schedule(tw,&tcp_death_row,TCP_TIMEWAIT_LEN,TCP_TIMEWAIT_LEN)/* 具體的處理結(jié)構(gòu)體 */struct inet_timewait_death_row tcp_death_row = {....../* slow_timer時間輪處理函數(shù) */.tw_timer= TIMER_INITIALIZER(inet_twdr_hangman, 0, (unsigned long)&tcp_death_row),/* slow_timer時間輪輔助處理函數(shù)*/.twkill_work= __WORK_INITIALIZER(tcp_death_row.twkill_work, inet_twdr_twkill_work),/* 短時間輪處理函數(shù) */.twcal_timer= TIMER_INITIALIZER(inet_twdr_twcal_tick, 0, (unsigned long)&tcp_death_row),};

由于我們這邊主要考慮的是設(shè)置為TCP_TIMEWAIT_LEN(60s)的處理時間,所以直接考察slow_timer時間輪處理函數(shù),也就是inet_twdr_hangman。這個函數(shù)還是比較簡短的:

void inet_twdr_hangman(unsigned long data){struct inet_timewait_death_row *twdr;unsigned int need_timer;twdr = (struct inet_timewait_death_row *)data;spin_lock(&twdr->death_lock);if (twdr->tw_count == 0)goto out;need_timer = 0;// 如果此slot處理的time_wait socket已經(jīng)達(dá)到了100個,且還沒處理完if (inet_twdr_do_twkill_work(twdr, twdr->slot)) {twdr->thread_slots |= (1 << twdr->slot);// 將余下的任務(wù)交給work queue處理schedule_work(&twdr->twkill_work);need_timer = 1;} else {/* We purged the entire slot, anything left? */// 判斷是否還需要繼續(xù)處理if (twdr->tw_count)need_timer = 1;// 如果當(dāng)前slot處理完了,才跳轉(zhuǎn)到下一個slottwdr->slot = ((twdr->slot + 1) & (INET_TWDR_TWKILL_SLOTS - 1));}// 如果還需要繼續(xù)處理,則在7.5s后再運(yùn)行此函數(shù)if (need_timer)mod_timer(&twdr->tw_timer, jiffies + twdr->period);out:spin_unlock(&twdr->death_lock);}

雖然簡單,但這個函數(shù)里面有不少細(xì)節(jié)。第一個細(xì)節(jié),就在inet_twdr_do_twkill_work,為了防止這個slot的time_wait過多,卡住當(dāng)前的流程,其會在處理完100個time_wait socket之后就回返回。這個slot余下的time_wait會交給Kernel的work_queue機(jī)制去處理。

分析從Linux源碼看TIME_WAIT的持續(xù)時間

值得注意的是。由于在這個slow_timer時間輪判斷里面,根本不判斷精確時間,直接全部刪除。所以輪到某個slot,例如到了52.5-60s這個slot,直接清理52.5-60s的所有time_wait。即使time_wait還沒有到60s也是如此。而小時間輪(tw_cal)會精確的判定時間,由于篇幅原因,就不在這里細(xì)講了。

注: 小時間輪(tw_cal)在tcp_tw_recycle開啟的情況下會使用

5.3、先作出一個假設(shè)

我們假設(shè),一個時間輪的數(shù)據(jù)最多能在一個slot間隔時間,也就是(60/8=7.5)內(nèi)肯定能處理完畢。由于系統(tǒng)有tcp_tw_max_buckets設(shè)置,如果設(shè)置的比較合理,這個假設(shè)還是比較靠譜的。

注: 這里的60/8為什么需要精確到小數(shù),而不是7。

因?yàn)閷?shí)際計算的時候是拿60*HZ進(jìn)行計算,

如果HZ是1024的話,那么period應(yīng)該是7680,即精度精確到ms級。

所以在本文中計算的時候需要精確到小數(shù)。

5.4、如果一個slot中的TIME_WAIT<=100

如果一個slot的TIME_WAIT<=100,很自然的,我們的處理函數(shù)并不會啟用work_queue。同時,還將slot+1,使得在下一個period的時候可以處理下一個slot。如下圖所示:

分析從Linux源碼看TIME_WAIT的持續(xù)時間

5.5、如果一個slot中的TIME_WAIT>100

如果一個slot的TIME_WAIT>100,Kernel會將余下的任務(wù)交給work_queue處理。同時,slot不變!也即是說,下一個period(7.5s后)到達(dá)的時候,還會處理同樣的slot。按照我們的假設(shè),這時候slot已經(jīng)處理完畢,那么在第7.5s的時候才將slot向前推進(jìn)。也就是說,假設(shè)slot一開始為0,到真正處理slot 1需要15s!

分析從Linux源碼看TIME_WAIT的持續(xù)時間

假設(shè)每一個slot的TIME_WAIT都>100的話,那么每個slot的處理都需要15s。

對于這種情況,筆者寫了個程序進(jìn)行模擬。

public class TimeWaitSimulator { public static void main(String[] args) {double delta = (60) * 1.0 / 8;// 0表示開始清理,1表示清理完畢// 清理完畢之后slot向前推進(jìn)int startPurge = 0;double sum = 0;int slot = 0;while (slot < 8) { if (startPurge == 0) {sum += delta;startPurge = 1;if (slot == 7) { // 因?yàn)榧僭O(shè)進(jìn)入work_queue之后,很快就會清理完 // 所以在slot為7的時候并不需要等最后的那個purge過程7.5s System.out.println('slot ' + slot + ' has reach the last ' + sum); break;} } if (startPurge == 1) {sum += delta;startPurge = 0;System.out.println('slot ' + 'move to next at time ' + sum);// 清理完之后,slot才應(yīng)該向前推進(jìn)slot++; }} }}

得出結(jié)果如下面所示:

slot move to next at time 15.0

slot move to next at time 30.0

slot move to next at time 45.0

slot move to next at time 60.0

slot move to next at time 75.0

slot move to next at time 90.0

slot move to next at time 105.0

slot 7 has reach the last  112.5

也即處理到52.5-60s這個時間輪的時候,其實(shí)外面時間已經(jīng)過去了112.5s,處理已經(jīng)完全滯后了。不過由于TIME_WAIT狀態(tài)下的Socket(inet_timewait_sock)所占用內(nèi)存很少,所以不會對系統(tǒng)可用資源造成太大的影響。但是,這會在NAT環(huán)境下造成一個坑,這也是筆者文章前面提到過的Bug。上面的計算如果按照圖和時間線畫出來,應(yīng)該是這么個情況:

分析從Linux源碼看TIME_WAIT的持續(xù)時間

也即TIME_WAIT狀態(tài)的Socket在一個period(7.5s)內(nèi)能處理完當(dāng)前slot的情況下,最多能夠存在112.5s!

如果7.5s內(nèi)還處理不完,那么響應(yīng)時間輪的輪轉(zhuǎn)還得繼續(xù)加上一個或多個perod。但在tcp_tw_max_buckets的限制,應(yīng)該無法達(dá)到這么嚴(yán)苛的條件。

5.6、PAWS(Protection Against Wrapped Sequences)使得TIME_WAIT延長

事實(shí)上,以上結(jié)論還是不夠嚴(yán)謹(jǐn)。TIME_WAIT時間還可以繼續(xù)延長!看下這段源碼:

enum tcp_tw_statustcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb, const struct tcphdr *th){......if (paws_reject)NET_INC_STATS_BH(twsk_net(tw), LINUX_MIB_PAWSESTABREJECTED);if (!th->rst) {/* In this case we must reset the TIMEWAIT timer. * * If it is ACKless SYN it may be both old duplicate * and new good SYN with random sequence number <rcv_nxt. * Do not reschedule in the last case. *//* 如果有回繞校驗(yàn)失敗的包到達(dá)的情況下,或者其實(shí)ack包 * 重置定時器到新的60s之后 * /if (paws_reject || th->ack)inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN, TCP_TIMEWAIT_LEN);/* Send ACK. Note, we do not put the bucket, * it will be released by caller. *//* 向?qū)Χ税l(fā)送當(dāng)前time wait狀態(tài)應(yīng)該返回的ACK */return TCP_TW_ACK;}inet_twsk_put(tw);/* 注意,這邊通過paws校驗(yàn)的包,會返回tcp_tw_success,使得time_wait狀態(tài)的 * socket五元組也可以三次握手成功重新復(fù)用 * /return TCP_TW_SUCCESS;}

上面的邏輯如下圖所示:

分析從Linux源碼看TIME_WAIT的持續(xù)時間

注意代碼最后的return TCP_TW_SUCCESS,通過PAWS校驗(yàn)的包,會返回TCP_TW_SUCCESS,使得TIME_WAIT狀態(tài)的Socket(五元組)也可以三次握手成功重新復(fù)用!

以上就是分析從Linux源碼看TIME_WAIT的持續(xù)時間的詳細(xì)內(nèi)容,更多關(guān)于Linux源碼 TIME_WAIT持續(xù)時間的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Linux系統(tǒng)
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲成人三区| 日韩avvvv在线播放| 国产亚洲人成a在线v网站| 久久成人一区| 中文字幕av一区二区三区人| 性色一区二区| 婷婷精品久久久久久久久久不卡| 中文字幕在线高清| 免费观看久久av| 欧美gv在线| 日韩精品不卡一区二区| 国产精品www994| 国产精品成人一区二区网站软件| 日韩精品91亚洲二区在线观看| 欧美影院三区| 精品日韩视频| 亚洲激情婷婷| 久久国产欧美日韩精品| 国产中文字幕一区二区三区| 日韩成人亚洲| 日本国产一区| 精品免费av在线| 日韩黄色大片网站| 999国产精品永久免费视频app| 免费在线视频一区| 久久99国产精品视频| 亚洲成av在线| 奇米狠狠一区二区三区| 欧洲亚洲一区二区三区| 热久久久久久| 亚洲激情av| 国产免费av国片精品草莓男男| 日本午夜大片a在线观看| 午夜久久一区| 青青青免费在线视频| 国产欧美三级| 亚洲一区二区三区久久久| 四虎成人av| 日韩动漫一区| 久色成人在线| 欧美日韩中文字幕一区二区三区| 国产欧美一区| 日本精品久久| 美女日韩在线中文字幕| 久久精品动漫| 成年男女免费视频网站不卡| 亚洲伊人影院| 9色国产精品| 国产综合激情| 97精品国产| 国产一区二区三区不卡视频网站| 日韩精品成人在线观看| 亚洲精品伦理| 婷婷精品在线| 日本不卡在线视频| 91亚洲精品视频在线观看| 日本精品一区二区三区在线观看视频 | 国产精品手机在线播放| 婷婷成人av| 日韩在线卡一卡二| 夜夜嗨一区二区| 亚洲视频www| 亚洲涩涩av| 日欧美一区二区| 日本午夜精品久久久久| 国产日韩免费| 涩涩av在线| 一区二区自拍| 免费人成在线不卡| 婷婷精品久久久久久久久久不卡| 欧美一区二区三区激情视频 | 婷婷久久一区| 日韩精品成人在线观看| 伊人国产精品| 日本不卡免费高清视频在线| 中文字幕中文字幕精品| 欧美日韩在线精品一区二区三区激情综合| 综合亚洲自拍| 久久香蕉网站| 亚洲成人不卡| 午夜一级久久| 精品一区二区三区视频在线播放 | 亚洲欧洲av| 久久gogo国模啪啪裸体| 美女免费视频一区| 1000部精品久久久久久久久| 亚洲精品888| 日本综合精品一区| 久久影院资源站| 激情欧美一区| 日韩国产成人精品| 国产精品伦理久久久久久| 伊人精品一区| 日本在线成人| 欧美sss在线视频| 91麻豆精品| 黄色免费成人| 美女av在线免费看| 午夜亚洲福利| 日本免费一区二区三区四区| 三级欧美韩日大片在线看| 久久精品99国产国产精| 午夜av成人| 欧美黑人巨大videos精品| 亚洲经典在线| 国产一区二区三区四区五区| 欧美综合国产| 都市激情国产精品| 国产欧美大片| 日本在线成人| 中文字幕日韩高清在线| 亚洲v在线看| 国产va免费精品观看精品视频| 偷拍亚洲精品| 久久九九电影| 91精品韩国| 黄色网一区二区| 日本视频一区二区| 亚洲欧美日本国产| 视频一区二区国产| 久久亚洲风情| 天堂成人国产精品一区| 欧美在线资源| 伊人精品在线| 久久亚洲精品伦理| 日韩影院在线观看| 久色成人在线| 青草综合视频| 另类欧美日韩国产在线| 免费看久久久| 色乱码一区二区三区网站| 成人免费电影网址| 99re国产精品| 国产亚洲人成a在线v网站| 亚洲一二av| 国产一区亚洲| 亚洲精品国产日韩| 少妇高潮一区二区三区99| 亚洲精品九九| 国产一区二区三区成人欧美日韩在线观看| 久久精品99久久久| 亚洲网址在线观看| 日本久久综合| 欧美成a人国产精品高清乱码在线观看片在线观看久 | 美女尤物久久精品| 午夜宅男久久久| 91av亚洲| 国产精品一区二区免费福利视频| 偷拍欧美精品| 亚洲午夜电影| 国产一区调教| 夜夜嗨网站十八久久| 精品九九在线| 国产一区二区久久久久| 国产高清视频一区二区| 另类欧美日韩国产在线| 国产视频久久| 日韩在线精品| 国内自拍视频一区二区三区| 国产精品久久久久77777丨| 亚洲18在线| 日韩和欧美的一区| 色老板在线视频一区二区| 日韩在线成人| 欧美亚洲国产激情| 国产精品原创| 伊人久久av| 国产精品毛片在线看| 最新亚洲国产| 日韩精品导航| 欧美极品中文字幕| 国产suv精品一区二区四区视频| 亚洲午夜av| 欧美va亚洲va日韩∨a综合色| 福利在线免费视频| 在线看片不卡| 国产探花一区| 一本一道久久a久久精品蜜桃| 97精品一区二区| 国产精品毛片久久久| 色乱码一区二区三区网站| 91高清一区| 久久久国产精品网站| 午夜精品成人av| 国内精品福利| 91亚洲无吗| 丝袜国产日韩另类美女| 在线人成日本视频| 日韩免费福利视频| 亚洲一区二区三区四区五区午夜| 欧美国产不卡| 国产精品久久乐| 欧洲一区二区三区精品| 亚洲欧美日韩在线观看a三区| 精品视频在线你懂得| 9国产精品视频| 日本91福利区| 亚洲一级特黄| 久久免费精品| 精品黄色一级片|