zoukankan      html  css  js  c++  java
  • 高并发的限流例子

    总体思路是这样:

    1.  用一个环形来代表通过的请求容器。

    2.  用一个指针指向当前请求所到的位置索引,来判断当前请求时间和当前位置上次请求的时间差,依此来判断是否被限制。

    3.  如果请求通过,则当前指针向前移动一个位置,不通过则不移动位置

    4.  重复以上步骤 直到永远.......

    以下代码的核心思路是这样的:指针当前位置的时间元素和当前时间的差来决定是否允许此次请求,这样通过的请求在时间上表现的比较平滑。

    //限流组件,采用数组做为一个环
        class LimitService
        {
            //当前指针的位置
            int currentIndex = 0;
            //限制的时间的秒数,即:x秒允许多少请求
            int limitTimeSencond = 1;
            //请求环的容器数组
            DateTime?[] requestRing = null;
            //容器改变或者移动指针时候的锁
            object objLock = new object();

            public LimitService(int countPerSecond,int  _limitTimeSencond)
            {
                requestRing = new DateTime?[countPerSecond];
                limitTimeSencond= _limitTimeSencond;
            }

            //程序是否可以继续
            public bool IsContinue()
            {
                lock (objLock)
                {
                    var currentNode = requestRing[currentIndex];
                    //如果当前节点的值加上设置的秒 超过当前时间,说明超过限制
                    if (currentNode != null&& currentNode.Value.AddSeconds(limitTimeSencond) >DateTime.Now)
                    {
                        return false;
                    }
                    //当前节点设置为当前时间
                    requestRing[currentIndex] = DateTime.Now;
                    //指针移动一个位置
                    MoveNextIndex(ref currentIndex);
                }            
                return true;
            }
            //改变每秒可以通过的请求数
            public bool ChangeCountPerSecond(int countPerSecond)
            {
                lock (objLock)
                {
                    requestRing = new DateTime?[countPerSecond];
                    currentIndex = 0;
                }
                return true;
            }

            //指针往前移动一个位置
            private void MoveNextIndex(ref int currentIndex)
            {
                if (currentIndex != requestRing.Length - 1)
                {
                    currentIndex = currentIndex + 1;
                }
                else
                {
                    currentIndex = 0;
                }
            }
        }

    测试程序如下:

    static  LimitService l = new LimitService(1000, 1);
            static void Main(string[] args)
            {
                int threadCount = 50;
                while (threadCount >= 0)
                {
                    Thread t = new Thread(s =>
                    {
                        Limit();
                    });
                    t.Start();
                    threadCount--;
                }           

                Console.Read();
            }

            static void Limit()
            {
                int i = 0;
                int okCount = 0;
                int noCount = 0;
                Stopwatch w = new Stopwatch();
                w.Start();
                while (i < 1000000)
                {
                    var ret = l.IsContinue();
                    if (ret)
                    {
                        okCount++;
                    }
                    else
                    {
                        noCount++;
                    }
                    i++;
                }
                w.Stop();
                Console.WriteLine($"共用{w.ElapsedMilliseconds},允许:{okCount},  拦截:{noCount}");
            }

    转载于:https://mp.weixin.qq.com/s/xIEN_IvR8h-Yc7oZoojTpw

  • 相关阅读:
    Android 接口中含有" "不能正常显示
    android
    EditText禁止自动弹出键盘
    相册选择照片
    Android完美获取状态栏高度、标题栏高度、编辑区域高度的获取
    Android WebView获取UserAgent
    php extract()用法
    php的安装和破解
    php 兼容换行符
    php 引用
  • 原文地址:https://www.cnblogs.com/FateHuli/p/10448712.html
Copyright © 2011-2022 走看看