日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Token Bucket在QoS中入门级介绍python示例

發布時間:2025/4/5 python 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Token Bucket在QoS中入门级介绍python示例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Token Bucket為令牌桶算法,常被用于流量整形,或對客戶端的限速。

假設家里是200M的寬帶, 為了保證打游戲的流暢,我要把電視設置為10M。那么實現上可以如下:

?

方案一:

累加電視的所有接收/發出的數據包長度,如果超出10M,則丟棄報文;每秒更新一次累加值為0。

思路非常簡單,也非常實用;從長時間統計上看,結果上偏差不大。

但可能限制出來流量圖就會如下,不均勻,像抽風似的。如果設置了10條限速規則對10個設備進行限速時,則每秒開始的0.1秒,CPU壓力很大,然后0.9秒很閑。

?

這種漏桶似的算法,利用率和平衡性較差。

方案二:

如果改進一下,將統計時間細化0.1秒,將效果會好不少。再進一步,將時間細化到每個報文接收,則效果就達到極致。

這就是Token Bucket做的事情。

?

流程出下:

1、當收到數據報文時,先試圖獲取token,如果剩余token足夠則放行;

2、不夠則更新token,等待token足夠再繼續。token按指定速率添加到bucket中,超過其容量則設置為最大值。

預期效果圖如下:

?

示例代碼實現如下:假設允許的速率每秒100,模擬包長在50~100隨機,統計一下發送時間和平均速率。


?

# -- coding: utf-8 -- # Good luck.import time import randomclass tb():def __init__(self, token_per_sec):self.captoken = token_per_secself.curr_token = 0self.timestamp = time.time()def refill(self):if time.time() > self.timestamp:refill_token = self.captoken*(time.time() - self.timestamp)self.curr_token = min(self.curr_token + refill_token, self.captoken)print "\tRefill tokens Current: %d. (Add %d)" %(self.curr_token, refill_token)self.timestamp = time.time()else:print "\tNo refill...."def consume(self, num):ret = Falseif self.curr_token > 0: # Control precisionself.curr_token -= numprint "\tGet token %d : remain %d" %(num, self.curr_token)ret = Trueself.refill()return rettest = tb(100) run_time = time.time() all_len = 0; times = 0while True:t = 0.1ts = time.time()send_len = random.randint(10, 50)print "Need send %d" %(send_len)while not test.consume(send_len):time.sleep(t)te = time.time()print "Use Time:%s Send:%d " %(te-ts, send_len)all_len += send_lentimes += 1print "Avg = %s (times=%d)" %(all_len/(ts - run_time+0.1), times)time.sleep(t)

運行效果

C:\Python27\python.exe X:/GIT/wxy_code_backup/Flash_tools/tokenbucket.py

Need send 44

No refill....

Refill tokens Current: 9. (Add 9)

Get token 44 : remain -34

Refill tokens Current: -23. (Add 10)

Use Time:0.200999975204 Send:44

Avg = 440.0 (times=1)

Need send 27

Refill tokens Current: -13. (Add 9)

Refill tokens Current: -3. (Add 10)

Refill tokens Current: 6. (Add 10)

Get token 27 : remain -20

Refill tokens Current: -10. (Add 10)

Use Time:0.302000045776 Send:27

Avg = 177.057409665 (times=2)

Need send 33

Refill tokens Current: 0. (Add 10)

Refill tokens Current: 9. (Add 10)

Get token 33 : remain -23

Refill tokens Current: -13. (Add 10)

Use Time:0.200999975204 Send:33

Avg = 129.51431022 (times=3)

Need send 42

Refill tokens Current: -3. (Add 10)

Refill tokens Current: 6. (Add 10)

Get token 42 : remain -35

Refill tokens Current: -25. (Add 10)

Use Time:0.201000213623 Send:42

Avg = 132.126711657 (times=4)

Need send 16

Refill tokens Current: -15. (Add 9)

Refill tokens Current: -5. (Add 9)

Refill tokens Current: 4. (Add 10)

Get token 16 : remain -11

Refill tokens Current: -1. (Add 9)

Use Time:0.300999879837 Send:16

Avg = 115.22048411 (times=5)

......

Need send 21

Refill tokens Current: -4. (Add 10)

Refill tokens Current: 5. (Add 9)

Get token 21 : remain -15

Refill tokens Current: -5. (Add 10)

Use Time:0.200999975204 Send:21

Avg = 100.389763573 (times=138)

Need send 41

Refill tokens Current: 4. (Add 9)

Get token 41 : remain -36

Refill tokens Current: -26. (Add 10)

Use Time:0.101000070572 Send:41

Avg = 100.66413934 (times=139)

Need send 18

Refill tokens Current: -15. (Add 10)

Refill tokens Current: -5. (Add 10)

Refill tokens Current: 4. (Add 10)

Get token 18 : remain -13

Refill tokens Current: -3. (Add 10)

Use Time:0.301999807358 Send:18

Avg = 100.607594694 (times=140)

?

穩定后效果還算可以,從發包點上也相對均勻。當然初始僅為波動而已,可以通過調整優化掉,但從長時間看,效果是一致的。

?

方案三:

方案一、二都缺少緩沖的支持。如果報文來了,但是現在資源不夠,不能發送,直接丟棄,則客戶端再重發,這個過程太浪費。

因此增加緩沖隊列,根據系統的內存,設定隊列的大小,對于不能發送的報文,先入隊。

如果隊列滿了呢? 那只能丟棄了,毫無辦法。(不考慮共享寬帶的情況)。

從Linux收發包角度,每個以太網設備有一個發送隊列,如果滿了,則設置為狀態不可用,則不再收包。道理是一樣的。

?

關于更新Token時間的設計,如上例程序,僅為演示,我沒有加線程額外處理。

在存在緩沖隊列的情況下,則必須增加更新線程,因為存在收發異常的情況。

?

示例如下,不過緩沖不過是增加一些彈性,丟包依然不可避免。結果可預知:由于緩沖的存在,平均流量會在一段時間后,才能趨向限制值。

# -- coding: utf-8 -- # Good luck.import time import random import threadingclass tb():def __init__(self, token_per_sec):self.captoken = token_per_secself.curr_token = 0self.timestamp = time.time()self.queue = []self.q_max = 5def refill(self):if time.time() > self.timestamp:refill_token = self.captoken*(time.time() - self.timestamp)self.curr_token = min(self.curr_token + refill_token, self.captoken)print "\tRefill tokens Current: %d. (Add %d)" %(self.curr_token, refill_token)self.timestamp = time.time()else:print "\tNo refill...."def consume(self, num):ret = Falseif self.curr_token > 0: # Control precisionself.curr_token -= numprint "\tGet token %d : remain %d" %(num, self.curr_token)ret = Trueelif len(self.queue) < self.q_max:# Enter queueself.queue.append(num)print "Enqueue Action."ret = Trueelse:# Drop it.ret = Falseself.refill()return retdef dequeue(self):if len(self.queue) and self.curr_token > 0:tmp = self.queue.pop()self.curr_token -= tmpprint "Dequeue Action : %d (remain %d)" %(tmp, self.curr_token)def update_bucket(args):print "Args=%s" %(args.captoken)while True:time.sleep(0.1)args.refill()args.dequeue()test = tb(100) run_time = time.time() all_len = 0 times = 0 tx_queue = []# update bucket thread. update_t = threading.Thread(target=update_bucket, args=(test,)) update_t.start()while True:t = 0.2ts = time.time()send_len = random.randint(40, 50)print "Need send %d" %(send_len)if test.consume(send_len):te = time.time()print "Use Time:%s Send:%d " %(te-ts, send_len)all_len += send_lenelse:print "Drop Action."times += 1print "Avg = %s (times=%d)" %(all_len/(ts - run_time+0.1), times)time.sleep(t)

運行結果:

Args=100

Need send 46

Enqueue Action.

Refill tokens Current: 0. (Add 0)

Use Time:0.0 Send:46

Avg = 455.44587139 (times=1)

Refill tokens Current: 10. (Add 9)

Dequeue Action : 46 (remain -35)

Need send 41

Enqueue Action.

Refill tokens Current: -25. (Add 10)

Use Time:0.0 Send:41

Avg = 289.036568661 (times=2)

Refill tokens Current: -25. (Add 0)

Refill tokens Current: -15. (Add 10)

Need send 47

Enqueue Action.

Refill tokens Current: -5. (Add 9)

Use Time:0.0 Send:47

Avg = 266.932297286 (times=3)

Refill tokens Current: -5. (Add 0)

Refill tokens Current: 4. (Add 10)

Dequeue Action : 47 (remain -42)

?

......

Drop Action.

Avg = 106.217083485 (times=170)

Refill tokens Current: -9. (Add 2)

Refill tokens Current: 0. (Add 10)

Dequeue Action : 42 (remain -41)

Need send 50

Enqueue Action.

Refill tokens Current: -34. (Add 7)

Use Time:0.0 Send:50

Avg = 107.055107617 (times=171)

Refill tokens Current: -31. (Add 2)

?

在有針對多個用戶的多個限速規則,必然存在多個隊列后,就需要有一定的調度算法,常用的RR、DRR、WRR,后面使用一些示例,展開討論一下。

?

?

?

?

?

?

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的Token Bucket在QoS中入门级介绍python示例的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。