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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

基于.net的分布式系统限流组件

發(fā)布時間:2024/9/20 windows 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于.net的分布式系统限流组件 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

在互聯(lián)網(wǎng)應用中,流量洪峰是常有的事情。在應對流量洪峰時,通用的處理模式一般有排隊、限流,這樣可以非常直接有效的保護系統(tǒng),防止系統(tǒng)被打爆。另外,通過限流技術手段,可以讓整個系統(tǒng)的運行更加平穩(wěn)。今天要與大家分享一下限流算法和C#版本的組件。

一、令牌桶算法:

??? 令牌桶算法的基本過程如下:

  • 假如用戶配置的平均發(fā)送速率為r,則每隔1/r秒速率將一個令牌被加入到桶中;
  • 假設桶最多可以存發(fā)b個令牌。當桶中的令牌達到上限后,丟棄令牌。
  • 當一個有請求到達時,首先去令牌桶獲取令牌,能夠取到,則處理這個請求
  • 如果桶中沒有令牌,那么請求排隊或者丟棄
  • ???? 工作過程包括3個階段:產(chǎn)生令牌、消耗令牌和判斷數(shù)據(jù)包是否通過。其中涉及到2個參數(shù):令牌產(chǎn)生的速率和令牌桶的大小,這個過程的具體工作如下。

  • 產(chǎn)生令牌:周期性的以固定速率向令牌桶中增加令牌,桶中的令牌不斷增多。如果桶中令牌數(shù)已到達上限,則丟棄多余令牌。
  • 消費 令牌:業(yè)務程序根據(jù)具體業(yè)務情況消耗桶中的令牌。消費一次,令牌桶令牌減少一個。
  • 判斷是否通過:判斷是否已有令牌桶是否存在有效令牌,當桶中的令牌數(shù)量可以滿足需求時,則繼續(xù)業(yè)務處理,否則將掛起業(yè)務,等待令牌。
  • ???? 下面是C#的一個實現(xiàn)方式

    class TokenBucketLimitingService: ILimitingService
    ??? {
    ??????? private LimitedQueue<object> limitedQueue = null;
    ??????? private CancellationTokenSource cancelToken;
    ??????? private Task task = null;
    ??????? private int maxTPS;
    ??????? private int limitSize;
    ??????? private object lckObj = new object();
    ??????? public TokenBucketLimitingService(int maxTPS, int limitSize)
    ??????? {
    ??????????? this.limitSize = limitSize;
    ??????????? this.maxTPS = maxTPS;

    ?????????? if (this.limitSize <= 0)
    ??????????????? this.limitSize = 100;
    ??????????? if(this.maxTPS <=0)
    ??????????????? this.maxTPS = 1;

    ?????????? limitedQueue = new LimitedQueue<object>(limitSize);
    ??????????? for (int i = 0; i < limitSize; i++)
    ??????????? {
    ??????????????? limitedQueue.Enqueue(new object());
    ??????????? }
    ??????????? cancelToken = new CancellationTokenSource();
    ??????????? task = Task.Factory.StartNew(new Action(TokenProcess), cancelToken.Token);
    ??????? }

    ?????? /// <summary>
    ??????? /// 定時消息令牌
    ??????? /// </summary>
    ??????? private void TokenProcess()
    ??????? {
    ??????????? int sleep = 1000 / maxTPS;
    ??????????? if (sleep == 0)
    ??????????????? sleep = 1;

    ?????????? DateTime start = DateTime.Now;
    ??????????? while (cancelToken.Token.IsCancellationRequested ==false)
    ??????????? {
    ??????????????? try
    ??????????????? {
    ??????????????????? lock (lckObj)
    ??????????????????? {
    ??????????????????????? limitedQueue.Enqueue(new object());
    ??????????????????? }
    ??????????????? }
    ??????????????? catch
    ??????????????? {
    ??????????????? }
    ??????????????? finally
    ??????????????? {
    ??????????????????? if (DateTime.Now - start < TimeSpan.FromMilliseconds(sleep))
    ??????????????????? {
    ??????????????????????? int newSleep = sleep - (int)(DateTime.Now - start).TotalMilliseconds;
    ??????????????????????? if (newSleep > 1)
    ??????????????????????????? Thread.Sleep(newSleep - 1); //做一下時間上的補償
    ??????????????????? }
    ??????????????????? start = DateTime.Now;
    ??????????????? }
    ??????????? }
    ??????? }

    ?????? public void Dispose()
    ??????? {
    ??????????? cancelToken.Cancel();
    ??????? }

    ?????? /// <summary>
    ??????? /// 請求令牌
    ??????? /// </summary>
    ??????? /// <returns>true:獲取成功,false:獲取失敗</returns>
    ??????? public bool Request()
    ??????? {
    ??????????? if (limitedQueue.Count <= 0)
    ??????????????? return false;
    ??????????? lock (lckObj)
    ??????????? {
    ??????????????? if (limitedQueue.Count <= 0)
    ??????????????????? return false;

    ?????????????? object data = limitedQueue.Dequeue();
    ??????????????? if (data == null)
    ??????????????????? return false;
    ??????????? }

    ?????????? return true;
    ??????? }
    ??? }

    public interface ILimitingService:IDisposable
    ???? {
    ???????? /// <summary>
    ???????? /// 申請流量處理
    ???????? /// </summary>
    ???????? /// <returns>true:獲取成功,false:獲取失敗</returns>
    ???????? bool Request();
    ???? }

    public class LimitingFactory
    ???? {
    ???????? /// <summary>
    ???????? /// 創(chuàng)建限流服務對象
    ???????? /// </summary>
    ???????? /// <param name="limitingType">限流模型</param>
    ???????? /// <param name="maxQPS">最大QPS</param>
    ???????? /// <param name="limitSize">最大可用票據(jù)數(shù)</param>
    ???????? public static ILimitingService Build(LimitingType limitingType = LimitingType.TokenBucket, int maxQPS = 100, int limitSize = 100)
    ???????? {
    ???????????? switch (limitingType)
    ???????????? {
    ???????????????? case LimitingType.TokenBucket:
    ???????????????? default:
    ???????????????????? return new TokenBucketLimitingService(maxQPS, limitSize);
    ???????????????? case LimitingType.LeakageBucket:
    ???????????????????? return new LeakageBucketLimitingService(maxQPS, limitSize);
    ???????????? }
    ???????? }
    ???? }

    ?? /// <summary>
    ???? /// 限流模式
    ???? /// </summary>
    ???? public enum LimitingType
    ???? {
    ???????? TokenBucket,//令牌桶模式
    ???????? LeakageBucket//漏桶模式
    ???? }

    public class LimitedQueue<T> : Queue<T>
    ???? {
    ???????? private int limit = 0;
    ???????? public const string QueueFulled = "TTP-StreamLimiting-1001";

    ??????? public int Limit
    ???????? {
    ???????????? get { return limit; }
    ???????????? set { limit = value; }
    ???????? }

    ??????? public LimitedQueue()
    ???????????? : this(0)
    ???????? { }

    ??????? public LimitedQueue(int limit)
    ???????????? : base(limit)
    ???????? {
    ???????????? this.Limit = limit;
    ???????? }

    ??????? public new bool Enqueue(T item)
    ???????? {
    ???????????? if (limit > 0 && this.Count >= this.Limit)
    ???????????? {
    ???????????????? return false;
    ???????????? }
    ???????????? base.Enqueue(item);
    ???????????? return true;
    ???????? }
    ???? }

    ???? 調(diào)用方法:

    var service = LimitingFactory.Build(LimitingType.TokenBucket, 500, 200);

    while (true)
    {
    ????? var result = service.Request();
    ?????? //如果返回true,說明可以進行業(yè)務處理,否則需要繼續(xù)等待
    ?????? if (result)
    ?????? {
    ???????????? //業(yè)務處理......
    ?????? }
    ?????? else
    ???????????? Thread.Sleep(1);
    }

    二、漏桶算法

    ????? 聲明一個固定容量的桶,每接受到一個請求向桶中添加一個令牌,當令牌桶達到上線后請求丟棄或等待,具體算法如下:

  • 創(chuàng)建一個固定容量的漏桶,請求到達時向漏桶添加一個令牌
  • 如果請求添加令牌不成功,請求丟棄或等待
  • 另一個線程以固定的速率消費桶里的令牌
  • ???? 工作過程也包括3個階段:產(chǎn)生令牌、消耗令牌和判斷數(shù)據(jù)包是否通過。其中涉及到2個參數(shù):令牌自動消費的速率和令牌桶的大小,個過程的具體工作如下。

  • 產(chǎn)生令牌:業(yè)務程序根據(jù)具體業(yè)務情況申請令牌。申請一次,令牌桶令牌加一。如果桶中令牌數(shù)已到達上限,則掛起業(yè)務后等待令牌。
  • 消費令牌:周期性的以固定速率消費令牌桶中令牌,桶中的令牌不斷較少。
  • 判斷是否通過:判斷是否已有令牌桶是否存在有效令牌,當桶中的令牌數(shù)量可以滿足需求時,則繼續(xù)業(yè)務處理,否則將掛起業(yè)務,等待令牌。
  • ??? C#的一個實現(xiàn)方式:

    class LeakageBucketLimitingService: ILimitingService
    ???? {
    ???????? private LimitedQueue<object> limitedQueue = null;
    ???????? private CancellationTokenSource cancelToken;
    ???????? private Task task = null;
    ???????? private int maxTPS;
    ???????? private int limitSize;
    ???????? private object lckObj = new object();
    ???????? public LeakageBucketLimitingService(int maxTPS, int limitSize)
    ???????? {
    ???????????? this.limitSize = limitSize;
    ???????????? this.maxTPS = maxTPS;

    ??????????? if (this.limitSize <= 0)
    ???????????????? this.limitSize = 100;
    ???????????? if (this.maxTPS <= 0)
    ???????????????? this.maxTPS = 1;

    ??????????? limitedQueue = new LimitedQueue<object>(limitSize);
    ???????????? cancelToken = new CancellationTokenSource();
    ???????????? task = Task.Factory.StartNew(new Action(TokenProcess), cancelToken.Token);
    ???????? }

    ??????? private void TokenProcess()
    ???????? {
    ???????????? int sleep = 1000 / maxTPS;
    ???????????? if (sleep == 0)
    ???????????????? sleep = 1;

    ??????????? DateTime start = DateTime.Now;
    ???????????? while (cancelToken.Token.IsCancellationRequested == false)
    ???????????? {
    ???????????????? try
    ???????????????? {

    ??????????????????? if (limitedQueue.Count > 0)
    ???????????????????? {
    ???????????????????????? lock (lckObj)
    ???????????????????????? {
    ???????????????????????????? if (limitedQueue.Count > 0)
    ???????????????????????????????? limitedQueue.Dequeue();
    ???????????????????????? }
    ???????????????????? }
    ???????????????? }
    ???????????????? catch
    ???????????????? {
    ???????????????? }
    ???????????????? finally
    ???????????????? {
    ???????????????????? if (DateTime.Now - start < TimeSpan.FromMilliseconds(sleep))
    ???????????????????? {
    ???????????????????????? int newSleep = sleep - (int)(DateTime.Now - start).TotalMilliseconds;
    ???????????????????????? if (newSleep > 1)
    ???????????????????????????? Thread.Sleep(newSleep - 1); //做一下時間上的補償
    ???????????????????? }
    ???????????????????? start = DateTime.Now;
    ???????????????? }
    ???????????? }
    ???????? }

    ??????? public void Dispose()
    ???????? {
    ???????????? cancelToken.Cancel();
    ???????? }

    ??????? public bool Request()
    ???????? {
    ???????????? if (limitedQueue.Count >= limitSize)
    ???????????????? return false;
    ???????????? lock (lckObj)
    ???????????? {
    ???????????????? if (limitedQueue.Count >= limitSize)
    ???????????????????? return false;

    ??????????????? return limitedQueue.Enqueue(new object());
    ???????????? }
    ???????? }
    ???? }

    ??? 調(diào)用方法:

    var service = LimitingFactory.Build(LimitingType.LeakageBucket, 500, 200);

    while (true)
    {
    ????? var result = service.Request();
    ?????? //如果返回true,說明可以進行業(yè)務處理,否則需要繼續(xù)等待
    ????? if (result)
    ?????? {
    ???????????? //業(yè)務處理......
    ?????? }
    ?????? else
    ??????????? Thread.Sleep(1);
    }

    兩類限流算法雖然非常相似,但是還是有些區(qū)別的,供大家參考!

  • 漏桶算法能夠強行限制數(shù)據(jù)的傳輸速率。在某些情況下,漏桶算法不能夠有效地使用網(wǎng)絡資源。因為漏桶的漏出速率是固定的。
  • 令牌桶算法能夠在限制數(shù)據(jù)的平均傳輸速率的同時還允許某種程度的突發(fā)傳輸.
  • https://www.cnblogs.com/vveiliang/p/9049393.html
  • 總結

    以上是生活随笔為你收集整理的基于.net的分布式系统限流组件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。