婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av

主頁 > 知識庫 > 分析從Linux源碼看TIME_WAIT的持續時間

分析從Linux源碼看TIME_WAIT的持續時間

熱門標簽:撫順移動400電話申請 貴陽教育行業電話外呼系統 烏海智能電話機器人 400電話申請方案 藍點外呼系統 在百度地圖標注車輛 做外呼系統的公司違法嗎 威海人工外呼系統供應商 寧夏房產智能外呼系統要多少錢

一、前言

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

二、首先介紹下Linux環境

TIME_WAIT這個參數通常和五元組重用扯上關系。在這里,筆者先給出機器的內核參數設置,以免和其它問題相混淆。

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

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

三、TIME_WAIT狀態轉移圖

提到Socket的TIME_WAIT狀態,不得就不亮出TCP狀態轉移圖了:

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

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

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

四、持續時間真如TCP_TIMEWAIT_LEN所定義么?

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

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

五、TIME_WAIT定時器源碼

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

tcp_v4_rcv

|->tcp_timewait_state_process

/* 將time_wait狀態的socket鏈入時間輪

|->inet_twsk_schedule

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

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

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

5.1、inet_twsk_schedule

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

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

void inet_twsk_schedule(struct inet_timewait_sock *tw,struct inet_timewait_death_row *twdr,const int timeo, const int timewait_len)
{
	......
	// 計算時間輪的slot
	slot = (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當前正在處理的slot
		// 在TIME_WAIT_LEN下,這個邏輯一般7
		slot = (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狀態的socket即將鏈接到當前處理slot最遠的slot(+7)以便處理。如下圖所示:

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

所有的slot全部掛滿了TIME_WAIT狀態的Socket。

5.2、具體的清理函數

每次調用inet_twsk_schedule時候傳入的處理函數都是:

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

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

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已經達到了100個,且還沒處理完
	if (inet_twdr_do_twkill_work(twdr, twdr->slot)) {
		twdr->thread_slots |= (1 << twdr->slot);
		// 將余下的任務交給work queue處理
		schedule_work(&twdr->twkill_work);
		need_timer = 1;
	} else {
		/* We purged the entire slot, anything left?  */
		// 判斷是否還需要繼續處理
		if (twdr->tw_count)
			need_timer = 1;
		// 如果當前slot處理完了,才跳轉到下一個slot
		twdr->slot = ((twdr->slot + 1) & (INET_TWDR_TWKILL_SLOTS - 1));
	}
	// 如果還需要繼續處理,則在7.5s后再運行此函數
	if (need_timer)
		mod_timer(&twdr->tw_timer, jiffies + twdr->period);
out:
	spin_unlock(&twdr->death_lock);
}

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

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

注: 小時間輪(tw\_cal)在tcp\_tw\_recycle開啟的情況下會使用

5.3、先作出一個假設

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

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

因為實際計算的時候是拿60*HZ進行計算,

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

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

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

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

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

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

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

對于這種情況,筆者寫了個程序進行模擬。

public class TimeWaitSimulator {

    public static void main(String[] args) {
        double delta = (60) * 1.0 / 8;

        // 0表示開始清理,1表示清理完畢
        // 清理完畢之后slot向前推進
        int startPurge = 0;
        double sum = 0;
        int slot = 0;
        while (slot < 8) {
            if (startPurge == 0) {
                sum += delta;
                startPurge = 1;
                if (slot == 7) {
                    // 因為假設進入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才應該向前推進
                slot++;
            }
        }
    }
}

得出結果如下面所示:

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這個時間輪的時候,其實外面時間已經過去了112.5s,處理已經完全滯后了。不過由于TIME_WAIT狀態下的Socket(inet_timewait_sock)所占用內存很少,所以不會對系統可用資源造成太大的影響。但是,這會在NAT環境下造成一個坑,這也是筆者文章前面提到過的Bug。
上面的計算如果按照圖和時間線畫出來,應該是這么個情況:

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

如果7.5s內還處理不完,那么響應時間輪的輪轉還得繼續加上一個或多個perod。但在tcp_tw_max_buckets的限制,應該無法達到這么嚴苛的條件。

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

事實上,以上結論還是不夠嚴謹。TIME_WAIT時間還可以繼續延長!看下這段源碼:

enum tcp_tw_status
tcp_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.
		 */
		/* 如果有回繞校驗失敗的包到達的情況下,或者其實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.
		 */
		/* 向對端發送當前time wait狀態應該返回的ACK */
		return TCP_TW_ACK;
	}
	inet_twsk_put(tw);
	/* 注意,這邊通過paws校驗的包,會返回tcp_tw_success,使得time_wait狀態的
	 * socket五元組也可以三次握手成功重新復用
	 * /
	return TCP_TW_SUCCESS;
}

上面的邏輯如下圖所示:

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

以上就是分析從Linux源碼看TIME_WAIT的持續時間的詳細內容,更多關于Linux源碼 TIME_WAIT持續時間的資料請關注腳本之家其它相關文章!

標簽:銅川 周口 慶陽 松原 泰州 蕪湖 那曲 朝陽

巨人網絡通訊聲明:本文標題《分析從Linux源碼看TIME_WAIT的持續時間》,本文關鍵詞  分析,從,Linux,源碼,看,TIME,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《分析從Linux源碼看TIME_WAIT的持續時間》相關的同類信息!
  • 本頁收集關于分析從Linux源碼看TIME_WAIT的持續時間的相關信息資訊供網民參考!
  • 推薦文章
    婷婷综合国产,91蜜桃婷婷狠狠久久综合9色 ,九九九九九精品,国产综合av
    久久蜜臀中文字幕| 日韩毛片在线免费观看| 91蝌蚪porny九色| 色综合久久久久网| 中文字幕在线不卡视频| 日本一区二区电影| 99精品国产热久久91蜜凸| 国产精品麻豆一区二区| 美女网站在线免费欧美精品| 欧美电影免费观看高清完整版 | 欧美裸体一区二区三区| 亚洲一区二区黄色| 欧美日韩国产另类一区| 成人激情免费电影网址| 久久av资源站| 久久精品在线观看| 亚洲丶国产丶欧美一区二区三区| 亚洲欧美综合网| av一本久道久久综合久久鬼色| 久久久噜噜噜久久中文字幕色伊伊| 婷婷综合久久一区二区三区| 国产成人夜色高潮福利影视| 国产白丝精品91爽爽久久| 91麻豆精品国产自产在线| 国产电影精品久久禁18| 午夜视频一区在线观看| 亚洲综合区在线| 日韩理论片一区二区| 日韩欧美一区电影| 欧美一区二区三区日韩| 色综合久久99| 久久久三级国产网站| gogo大胆日本视频一区| 亚洲大片一区二区三区| 欧美一区三区四区| 欧美日韩一二三区| 色综合天天综合网天天看片| www.亚洲人| 欧美三级视频在线播放| 欧美日韩精品福利| 欧美激情一区三区| 亚洲第一av色| 国产美女视频91| 在线观看91视频| 中文字幕精品一区二区精品绿巨人 | 日韩欧美资源站| 中文字幕免费一区| 久久aⅴ国产欧美74aaa| av激情成人网| 欧美性一区二区| 久久精品在线免费观看| 国产日韩精品一区| 一区二区三区在线观看欧美| 午夜精品福利一区二区蜜股av| 奇米一区二区三区av| 精品视频1区2区| 一区二区三区在线观看动漫| 亚洲国产精品久久艾草纯爱| 日本人妖一区二区| 成人av在线观| 成人av集中营| 日本精品免费观看高清观看| 精品久久久久久久久久久久包黑料 | 婷婷丁香久久五月婷婷| 国产v综合v亚洲欧| 精品乱码亚洲一区二区不卡| 亚洲视频小说图片| 国产91丝袜在线播放九色| 久久精品夜色噜噜亚洲a∨| 亚洲国产综合色| 欧美日韩激情在线| 日本vs亚洲vs韩国一区三区| 91久久香蕉国产日韩欧美9色| 欧美mv日韩mv国产网站| 日本在线不卡视频| 欧美一区二区在线看| 亚洲免费观看高清完整版在线观看熊| 丁香天五香天堂综合| 1区2区3区国产精品| 91福利小视频| 蜜桃视频在线一区| 精品久久久久久久久久久久久久久久久 | 日韩欧美亚洲一区二区| 国产露脸91国语对白| 中文字幕在线一区免费| 日韩午夜在线影院| 欧美私人免费视频| 成人app软件下载大全免费| 午夜精品在线看| 一区二区三区在线观看网站| 久久久精品日韩欧美| 日韩一区二区三区视频| 欧美亚洲精品一区| 蜜臀av性久久久久蜜臀aⅴ四虎| 国产欧美一区二区精品性色超碰| 91官网在线免费观看| 亚洲精品中文在线观看| 久久99精品久久只有精品| 亚洲另类色综合网站| 精品国产乱码久久久久久浪潮| 欧美亚洲国产一区二区三区| 国产麻豆精品一区二区| 亚洲日本中文字幕区| 欧美日韩成人高清| 国产a精品视频| 国产成人av电影免费在线观看| 亚洲综合免费观看高清完整版在线 | 欧美日韩国产小视频在线观看| 成+人+亚洲+综合天堂| 免费欧美日韩国产三级电影| 欧美一级艳片视频免费观看| 奇米亚洲午夜久久精品| 夜夜精品浪潮av一区二区三区| 国产一区二区h| 精久久久久久久久久久| 韩国午夜理伦三级不卡影院| 欧美一区二区三区视频在线观看| 91丨九色丨尤物| 欧美日韩一本到| 欧美一级二级三级乱码| 国产综合久久久久影院| 中文字幕一区二区三区不卡| 亚洲黄色片在线观看| 亚洲成av人片一区二区| 9191国产精品| 中文字幕一区二区三区不卡在线| 久久综合色播五月| 色狠狠色噜噜噜综合网| 成人免费在线视频| 亚洲欧美一区二区三区国产精品| 国产日韩欧美综合在线| 99九九99九九九视频精品| 国内精品自线一区二区三区视频| 久久成人免费网| 99视频有精品| 欧美影院一区二区三区| 91视视频在线观看入口直接观看www | 亚洲色图视频网| 在线看国产一区| www.亚洲人| 欧美精品一二三四| 国产精品一区在线| 国产成人在线视频网站| 欧美sm美女调教| 91美女蜜桃在线| 欧美精品一区二区高清在线观看| 成人免费精品视频| 亚洲黄色免费网站| 久久99精品久久久久婷婷| 欧美精品18+| 亚洲亚洲人成综合网络| 一区二区日韩av| 不卡电影免费在线播放一区| 欧美喷水一区二区| 日韩视频中午一区| 亚洲狼人国产精品| 国产成人av电影在线| 7777女厕盗摄久久久| 亚洲一区二区三区视频在线播放| 亚洲一区二区三区四区在线观看 | 欧美精品vⅰdeose4hd| 久久成人免费日本黄色| 亚洲男同性恋视频| 欧美日韩国产乱码电影| 欧美激情艳妇裸体舞| 一本一道综合狠狠老| 一区二区三区欧美日韩| 制服.丝袜.亚洲.另类.中文| 国产精品资源网| 首页综合国产亚洲丝袜| 久久蜜臀中文字幕| 久久一区二区视频| 欧美日韩美女一区二区| 99re热这里只有精品免费视频| 日韩高清不卡一区二区三区| 国产精品乱人伦中文| 欧美成人在线直播| 欧美巨大另类极品videosbest | 日本丰满少妇一区二区三区| 久久精品99国产精品日本| 亚洲国产电影在线观看| 久久蜜桃av一区二区天堂 | 日韩你懂的在线播放| 欧美国产国产综合| 国产精品久久久久久久久久久免费看 | 国产精品综合久久| 91免费看片在线观看| 欧美性色欧美a在线播放| 欧美日韩亚洲国产综合| 在线播放欧美女士性生活| 国产精品系列在线观看| 91在线丨porny丨国产| 色琪琪一区二区三区亚洲区| 欧美午夜视频网站| 欧美私人免费视频| 精品99999| 在线综合+亚洲+欧美中文字幕| 美女视频黄 久久| 高清不卡在线观看av| av男人天堂一区|