队列管理机制
原文地址 :http://selab.whust.com/Display_Diary.aspx?DiaryID=47
?
實(shí)驗(yàn)?zāi)康?/span>
? ?學(xué)習(xí)DropTail 和 RED 隊(duì)列管理機(jī)制,以了解主動式和被動式隊(duì)列管理的優(yōu)缺點(diǎn)。
?背景知識
【DropTail 和被動式隊(duì)列管理機(jī)制】
?? 在Internet中最簡單也最普遍的隊(duì)列管理機(jī)制就是DropTail。當(dāng)一個數(shù)據(jù)報到達(dá)隊(duì)列時,就把數(shù)據(jù)報放到隊(duì)列中等待被傳送,但由于隊(duì)列長度是有限的,因此如果數(shù)據(jù)流太大,而隊(duì)列沒有空間去暫存這些新到的數(shù)據(jù)報,就會把隊(duì)列最尾端的數(shù)據(jù)報丟棄,這樣的管理機(jī)制就叫做DropTail。很多時候,DropTail隊(duì)列管理機(jī)制會與FIFO(First In First Out)相結(jié)合,整個運(yùn)作方式為:數(shù)據(jù)報傳送的順序與封包進(jìn)入隊(duì)列的順序相同,先進(jìn)入隊(duì)列的封包先傳送出去,后進(jìn)入隊(duì)列的封包較晚傳送出去。如果隊(duì)列長度超過暫存空間的大小,就會把隊(duì)列最尾端的數(shù)據(jù)報丟棄。DropTail在丟棄數(shù)據(jù)報時,并不會去考慮要丟棄的數(shù)據(jù)報屬于哪個數(shù)據(jù)流,只是單純的把超過暫存空間大小的數(shù)據(jù)流丟棄,因此DropTail隊(duì)列管理機(jī)制的最大優(yōu)點(diǎn)就是實(shí)際操作簡單。但是,有利有弊,正是由于這個特性,使得隊(duì)列在相當(dāng)長的時間內(nèi)處于充滿或幾乎充滿的狀態(tài)。而隊(duì)列管理機(jī)制最重要的目標(biāo)之一是降低穩(wěn)定狀態(tài)下隊(duì)列的長度,因?yàn)槎它c(diǎn)到端點(diǎn)的延遲主要由隊(duì)列中排隊(duì)等待造成的。
此外,DropTail容易造成TCP全局同步(TCP Global Synchronization)問題。由于Internet 上的數(shù)據(jù)流都具有突發(fā)性,到達(dá)路由器的封包也往往是突發(fā)的。如果此時隊(duì)列處于充滿或幾乎充滿狀態(tài),就會導(dǎo)致在短時間內(nèi)連續(xù)大量的丟包。而TCP數(shù)據(jù)流具有自適應(yīng)特性(Adaptive),來源端發(fā)現(xiàn)封包丟失就會急速降低傳送速度,于是網(wǎng)絡(luò)擁塞情況得到緩解。但來源端在發(fā)現(xiàn)網(wǎng)絡(luò)不再擁塞后又開始增加發(fā)送速度,最終又造成網(wǎng)絡(luò)擁塞。這種現(xiàn)象就像一個循環(huán),周而復(fù)始的進(jìn)行下去,致使網(wǎng)絡(luò)長期處于鏈路利用率很低的狀態(tài),降低了整體的吞吐量,這正是傳說中的“TCP全局同步”現(xiàn)象,這個現(xiàn)象,我們會在后面的實(shí)驗(yàn)中通過網(wǎng)絡(luò)仿真產(chǎn)生的數(shù)據(jù)和圖形進(jìn)行驗(yàn)證。
除了DropTail外,另外兩種在隊(duì)列滿時用得比較多的隊(duì)列管理機(jī)制是Random Drop 和 Drop Front。當(dāng)隊(duì)列滿時,前者從隊(duì)列中隨機(jī)找到一個數(shù)據(jù)報丟棄,讓新來的數(shù)據(jù)報進(jìn)入隊(duì)列;后者從隊(duì)列前端把數(shù)據(jù)報丟棄,以便新來的數(shù)據(jù)報進(jìn)入隊(duì)列。但這兩種隊(duì)列管理機(jī)制仍然存在“滿隊(duì)列”問題。由于這幾種方法都是在隊(duì)列滿時被迫丟包,因此被稱為被動式隊(duì)列管理。
?
【RED和主動式隊(duì)列管理機(jī)制】
與被動式隊(duì)列管理機(jī)制在隊(duì)列滿時被動丟包相比,主動式隊(duì)列管理機(jī)制在隊(duì)列未滿時就開始按一定概率丟棄數(shù)據(jù)報。這樣未雨綢繆,對具有擁塞控制的傳送端做流量速度管制,以避免滿隊(duì)列被迫丟包的兩種負(fù)面影響:端點(diǎn)到端點(diǎn)的延遲時間過長,鏈路利用率過低。而RED(Random Early Detection)就是一種典型的主動式隊(duì)列管理機(jī)制。
RED隊(duì)列管理機(jī)制使用平均隊(duì)列長度來預(yù)測即將發(fā)生的網(wǎng)絡(luò)擁塞,并采用隨機(jī)選擇的方式對數(shù)據(jù)報進(jìn)行丟棄,使得擁塞發(fā)生前就會有擁塞控制的傳送端提示要進(jìn)行流量速度管制,以避免擁塞發(fā)生。與此同時,由于RED是采用隨機(jī)的方式來丟棄封包,因此不同的TCP數(shù)據(jù)流對擁塞情況的反應(yīng)不同步,因而解決了“TCP全局同步”現(xiàn)象。
簡言之,RED路由器由兩個獨(dú)立的算法組成:1.計(jì)算平均隊(duì)列長度(avg)的算法決定了路由器隊(duì)列容納突發(fā)性數(shù)據(jù)的程度;2.計(jì)算丟包概率(Pb)的算法決定了在當(dāng)前擁塞程度下,路由器丟棄分組的概率。
RED計(jì)算平均隊(duì)列長度是采用加權(quán)平均方式,計(jì)算公式如下:
??? ????avg = (1- Wq)* avg + Wq * q
其中,avg是平均隊(duì)列長度,q是目前實(shí)際的隊(duì)列長度,Wq 為目前實(shí)際的隊(duì)列長度加權(quán)系數(shù),其值在0與1之間。一般而言,設(shè)置得比較小,以便計(jì)算出來的平均隊(duì)列長度變化得比較慢,不會因?yàn)橥话l(fā)流量的到來而使平均隊(duì)列長度增加得過快,造成大量封包丟失。
決定要丟棄封包依據(jù)兩個閾值minth 和maxth ,當(dāng)平均隊(duì)列長度avg 小于minth 時,所有的封包都允許進(jìn)入隊(duì)列,但當(dāng)avg超過maxth 時,所有的封包被直接丟棄,當(dāng)avg介于minth 和maxth 時,則根據(jù)下面的概率公式來丟棄封包。
Pb ?= maxp * (avg - minth)/(maxth- minth)
其中的maxp為網(wǎng)管預(yù)先設(shè)置的丟棄概率值,Pb 為目前封包丟棄的計(jì)算值,其值變化如下圖所示:
?
?
??
?
而RED再真正決定是否要丟棄數(shù)據(jù)報,并不是采用Pb ,而是對Pb 進(jìn)行如下修改,以作為實(shí)際封包丟棄概率:
?? ??Pa = Pb ?/ (1- count* Pb)
其中,count記錄了上一個封包丟棄后有多少數(shù)據(jù)報進(jìn)入隊(duì)列。采用 Pa 是希望能讓數(shù)據(jù)報丟棄概率的分布更均勻。
可見,若想有效的使用RED,適當(dāng)選擇Wq ?,minth ,? maxth ,maxp 等參數(shù)很關(guān)鍵。1993年 Floy S,Jacobson 發(fā)表了一篇題為“Random early detection gateways for congestion avoidance”的論文,將RED的算法,參數(shù)的設(shè)置,實(shí)驗(yàn)的結(jié)果詳細(xì)的進(jìn)行了分析和論證,大家可以在網(wǎng)上下載,進(jìn)行參考。
?
實(shí)驗(yàn)步驟
說了這么久,我們終于可以開始做實(shí)驗(yàn)了!
1.????? 仿真的網(wǎng)絡(luò)結(jié)構(gòu)圖
?????????????????????????????? ?
可能大家對這個結(jié)構(gòu)圖已經(jīng)不陌生了,r1和r2是路由器,其中的鏈路采用DropTail和RED隊(duì)列管理機(jī)制以作為效率分析的比較,頻率為56kbps,傳輸延遲為10ms。其中的數(shù)據(jù)流數(shù)目可由用戶在模擬時決定,下面的例子為10條TCP數(shù)據(jù)流。我們要比較的效率是這10條數(shù)據(jù)流的平均吞吐量、第一條數(shù)據(jù)流的端點(diǎn)到端點(diǎn)平均延遲時間和隊(duì)列長度變化。
2.????? TCL程序代碼 (假設(shè)我們將程序代碼保存于/home/ns下的queue.tcl中)
if {$argc !=2} {
?puts "Usage: ns queue.tcl queuetype_ noflows_"
?puts "Example: ns queue.tcl DropTail 10"
?puts "queuetype_: DropTail or RED"
?exit
?}
?
set par1 [lindex $argv 0]
set par2 [lindex $argv 1]
#產(chǎn)生一個仿真的對象
set ns [new Simulator]
#打開一個trace文件,用來記錄數(shù)據(jù)報傳送的過程
set nd [open out-$par1-$par2.tr w]
$ns trace-all $nd
#結(jié)束一個結(jié)束的程序
proc finish {} {
?global ns nd par2 tcp startT
?$ns flush-trace
?close $nd
?set time [$ns now]
?set sum_thgpt 0
# throughput = 收到ACK數(shù) * Packet Size(Bit) / 傳送時間
# 收到Ack數(shù) = 傳送出Packet 數(shù)
for {set i 0} {$i < $par2} {incr i 1} {
?set ackno_($i) [$tcp($i) set ack_ ]
?set thgpt($i) [expr $ackno_($i) *1000.0*8.0/($time-$startT($i))]
?#puts $thgpt($i)
?set sum_thgpt [expr $sum_thgpt+$thgpt($i)]
}
?
?set avgthgpt [expr $sum_thgpt/$par2]
?puts "average throughput: $avgthgpt (bps)"
?exit 0
}
#定義節(jié)點(diǎn)
for {set i 0} {$i<$par2} {incr i 1} {
?set src($i) [$ns node]
?set dst($i) [$ns node]
}
#產(chǎn)生兩個路由器
set r1 [$ns node]
set r2 [$ns node]
#把結(jié)點(diǎn)和路由器連接起來
for {set i 0} {$i<$par2} {incr i 1} {
? $ns duplex-link $src($i) $r1 100Mb [expr ($i*10)]ms DropTail
? $ns duplex-link $r2 $dst($i) 100Mb [expr ($i*10)]ms DropTail
?}
?
$ns duplex-link $r1 $r2 56k 10ms $par1
#設(shè)置r1和r2之間的Queue Size 為50個數(shù)據(jù)報大小
$ns queue-limit $r1 $r2 50
#記錄隊(duì)列長度
#Recording the length of queue
set q_ [[$ns link $r1 $r2] queue]
# set queuechan [open q-$par1-$par2.tr w]
# $q_ trace curq_
?
if {$par1=="RED"} {
#Using packet mode
$q_ set bytes_ false
$q_ set queue_in_bytes false
}
?
# $q_ attach $queuechan
?
for {set i 0} {$i<$par2} {incr i 1} {
?set tcp($i) [$ns create-connection TCP/Reno $src($i) TCPSink $dst($i) 0]
?$tcp($i) set fid_ $i
?}
#隨機(jī)在0與1之間決定數(shù)據(jù)流開始傳送的時間
set rng [new RNG]
?$rng seed 1
?
?set RVstart [new RandomVariable/Uniform]
?$RVstart set min_ 0
?$RVstart set max_ 1
?$RVstart use-rng $rng
?
?for {set i 0} {$i<$par2} {incr i 1} {
? set startT($i) [expr [$RVstart value]]
? #puts "startT($i) $startt($i)sec"
?}
?
#在指定時間,開始傳送數(shù)據(jù)
for {set i 0} {$i<$par2} {incr i 1} {
?set ftp($i) [$tcp($i) attach-app FTP]
?$ns at $startT($i) "$ftp($i) start"
}
?
#在第50s時區(qū)調(diào)用finish來結(jié)束模擬
$ns at 50.0 "finish"
$ns run
?
3.????? 執(zhí)行方法和執(zhí)行結(jié)果
(1)10條TCP數(shù)據(jù)流,采用DropTail 隊(duì)列管理機(jī)制:
[root@localhost ns]# ns queue.tcl DropTail 10
average throughput: 4353.6337788880564 (bps)
?
(2)10條TCP數(shù)據(jù)流,采用RED隊(duì)列管理機(jī)制:
?[root@localhost ns]# ns queue.tcl RED 10
average throughput: 4789.3897693204663 (bps)
結(jié)果分析:從上面的數(shù)據(jù)可知,在只有10條TCP數(shù)據(jù)流的情況下,RED隊(duì)列管理機(jī)制得到的吞吐量高于DropTail隊(duì)列管理機(jī)制。
知識拓展:上面是10條TCP數(shù)據(jù)流,我們還可以將數(shù)據(jù)流的數(shù)目改為15,20,25,30等,然后觀察平均吞吐量(average throughput)
?
4.????? 端點(diǎn)到端點(diǎn)平均延遲的awk程序 (假設(shè)我們將此awk程序保存于/home/ns下的measure-delay1.awk中)
#這是測量第一條TCP數(shù)據(jù)流數(shù)據(jù)報端點(diǎn)到端點(diǎn)間平均延遲時間的awk程序
#我們可以根據(jù)這個程序,舉一反三,寫出測量第2條以至第n條TCP/UDP
#數(shù)據(jù)流的awk程序
?
BEGIN {
?#程序初始化,設(shè)置一變量以記錄目前最高處理數(shù)據(jù)報的ID
?highest_packet_id = 0;
}
?
{
?#與trace文件結(jié)構(gòu)對應(yīng)
?action = $1;
?time = $2;
?from = $3;
?to = $4;
?type = $5;
?pktsize = $6;
?flow_id = $8;
?src = $9;
?dst = $10;
?seq_no = $11;
?packet_id = $12;
#記錄目前最高的packet ID
if( packet_id > highest_packet_id )
?highest_packet_id = packet_id;
#記錄第一條TCP(flow-id=0)的接收時間
if ( start_time[packet_id] == 0 )
?start_time[packet_id] = time;
?
#記錄第一條TCP(flow-id=0)的接收時間
if( flow_id==0 && action!="d" && type=="tcp" ) {
?? if ( action == "r" ) {
????? end_time[packet_id] = time;
????? }
? } else {
?#把不是flow-id=0 的封包或則flow-id=0 ,但此封包被drop的時間設(shè)置為-1
?? end_time[packet_id] = -1;
? }
}
?
END {
sum_delay=0;
no_sum=0;
#把數(shù)據(jù)全部讀取完后,開始計(jì)算有效數(shù)據(jù)報的端點(diǎn)到端點(diǎn)延遲時間
for( packet_id = 0; packet_id <= highest_packet_id; packet_id++ ) {
start = start_time[packet_id];
end = end_time[packet_id];
packet_duration = end-start;
?
#只把接收時間大于傳送時間的記錄列出來
if( start < end ) {
?#print ("%f %f/n",start,packet_duration);
?sum_delay+=packet_duration;
?no_sum+=1;
? }
?}
#求出數(shù)據(jù)報端點(diǎn)到端點(diǎn)的平均延遲時間
printf( "average delay: %f sec/n",sum_delay/no_sum );
}
?
5. 執(zhí)行方法和執(zhí)行結(jié)果:
(1)10條TCP數(shù)據(jù)流,采用DropTail隊(duì)列管理機(jī)制
? [root@localhost ns]# awk -f measure-delay1.awk out-DropTail-10.tr
average delay: 4.379053 sec
?? (2)10條TCP數(shù)據(jù)流,采用RED隊(duì)列管理機(jī)制
??? [root@localhost ns]# awk -f measure-delay1.awk out-RED-10.tr
average delay: 1.237935 sec
結(jié)果分析:從上面的數(shù)據(jù)可知,在只有10條TCP數(shù)據(jù)流的情況下,RED隊(duì)列管理機(jī)制得到的端點(diǎn)到端點(diǎn)的平均延遲時間低于DropTail隊(duì)列管理機(jī)制。
6. 使用gnuplot 觀察DropTail 和RED 隊(duì)列長度變化(假設(shè)我們要分析的q-DropTail-10.tr 和q-RED-10.tr文件都保存在/home/ns中)
? [root@localhost root]# cd /home/ns
[root@localhost ns]# gnuplot
?
??????? G N U P L O T
??????? Version 3.7 patchlevel 3
??????? last modified Thu Dec 12 13:00:00 GMT 2002
??????? System: Linux 2.4.20-8
?
??????? Copyright(C) 1986 - 1993, 1998 - 2002
??????? Thomas Williams, Colin Kelley and many others
?
??????? Type `help` to access the on-line reference manual
??????? The gnuplot FAQ is available from
??????? http://www.gnuplot.info/gnuplot-faq.html
?
??????? Send comments and requests for help to
??????? Send bugs, suggestions and mods to
?
?
Terminal type set to 'x11'
gnuplot> plot "q-RED-10.tr" using 2:3 with linespoints 1
顯示圖形如下:
???????
?
按照同樣的方法進(jìn)入gnuplot,然后輸入:
gnuplot> plot "q-DropTail-10.tr" using 2:3 with linespoints 2
???????????????????????????????????????????????????????????? ^
得到的結(jié)果為:? x range is invalid
為什么呢?
我們從/home/ns中打開文件q-DropTail-10.tr,查看,發(fā)現(xiàn)此文件是空的。
原因何在呢?
我們來看queue.tcl中的這段代碼:
#記錄隊(duì)列長度
#Recording the length of queue
set q_ [[$ns link $r1 $r2] queue]
# set queuechan [open q-$par1-$par2.tr w]
# $q_ trace curq_
?
if {$par1=="RED"} {
#Using packet mode
$q_ set bytes_ false
$q_ set queue_in_bytes false
}
?
# $q_ attach $queuechan
?我們把記錄隊(duì)列長度的核心代碼set queuechan [open q-$par1-$par2.tr w] 、$q_ trace curq_ 、$q_ attach $queuechan 給注釋了!之所以這樣做,是因?yàn)?/span>NS2中并沒有提供追蹤DropTail隊(duì)列長度的功能。因此,現(xiàn)在的關(guān)鍵在于,如何在NS2中添加追蹤DropTail隊(duì)列長度的新協(xié)議。
?????? 這個問題還待研究。。。。。。
總結(jié)
- 上一篇: NS安装问题收集(3)
- 下一篇: set class_ x set fid