.NET-高并发及限流方案

前言:高并发对我们来说应该都不陌生,特别想淘宝秒杀,竞价等等,使用的非常多,如何在高并发的情况下,使用限流,保证业务的进行呢。以下是一个实例,不喜勿喷!

总体思路:

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

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

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

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

 

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

实例使用.net写的,仅供参考,了解思路和原理,需要者完全可以用其他方式语言来实现,很简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public class LimitService
   {
       /// <summary>
       /// 当前指针位置
       /// </summary>
       public int currentIndex = 0;
 
       //限制的时间的秒数,即:x秒允许多少请求
       public int limitTimeSencond = 1;
 
       /// <summary>
       /// 请求环的数组容器
       /// </summary>
       public DateTime?[] requstRing { get; set; } = null;
 
       /// <summary>
       /// 容器改变或者移动指针时的锁;
       /// </summary>
       object obj = new object();
 
       public LimitService(int countPerSecond, int _limitTimeSencond)
       {
           limitTimeSencond = _limitTimeSencond;
           requstRing = new DateTime?[countPerSecond];
       }
 
       /// <summary>
       /// 程序是否可以继续
       /// </summary>
       /// <returns></returns>
       public bool IsContinue()
       {
           lock (obj)
           {
               var currentNode = requstRing[currentIndex];
               if (currentNode != null && currentNode.Value.AddSeconds(limitTimeSencond) > DateTime.Now)
               {
                   return false;
               }
 
               //当前节点设置为当前时间
               requstRing[currentIndex] = DateTime.Now;
               //指针移动一个位置
               MoveNextIndex(ref currentIndex);
           }
 
           return true;
       }
 
       /// <summary>
       /// 改变每秒可以通过的请求数
       /// </summary>
       /// <param name="countPerSecond"></param>
       /// <returns></returns>
       public bool ChangeCountPerSecond(int countPerSecond)
       {
           lock (obj)
           {
               requstRing = new DateTime?[countPerSecond];
 
               currentIndex = 0;
           }
 
           return true;
       }
 
       /// <summary>
       /// 指针往前移动一个位置
       /// </summary>
       /// <param name="currentIndex"></param>
       public  void  MoveNextIndex (ref int currentIndex)
       {
           if(currentIndex!= requstRing.Length - 1)
           {
               currentIndex = currentIndex + 1;
           }
           else
           {
               currentIndex = 0;
           }
       }

  

 

测试程序如下:

复制代码
 1  public class Program
 2     {
 3         static LimitService l = new LimitService(1000, 1);
 4         public static void Main(string[] args)
 5         {
 6 
 7             int threadCount = 50;
 8 
 9             while (threadCount >= 0)
10             {
11                 Thread t = new Thread(s => {
12                     Limit();
13 
14                 });
15 
16                 t.Start();
17 
18                 threadCount--;
19             }
20 
21             Console.ReadKey();
22         }
23 
24         public static void Limit()
25         {
26             int i = 0;
27             int okCount = 0;
28             int noCount = 0;
29             Stopwatch w = new Stopwatch();
30             w.Start();
31             while (i < 1000000)
32             {
33                 var ret = l.IsContinue();
34                 if (ret)
35                 {
36                     okCount++;
37                 }
38                 else
39                 {
40                     noCount++;
41                 }
42                 i++;
43             }
44             w.Stop();
45             Console.WriteLine($"共用{w.ElapsedMilliseconds},允许:{okCount},  拦截:{noCount}");
46         }
47     }
复制代码

 

测试结果:

最大用时7秒,共处理请求1000000*50=50000000 次

并未发生GC操作,内存使用率非常低,每秒处理 300万次+请求 。以上程序修改为10个线程,大约用时4秒之内

 

 如果是强劲的服务器或者线程数较少情况下处理速度将会更快!!!

以上就是测试的限制高并发的一种简单方案,当然还有其他方式比如:令牌桶算法,漏桶算法等等,可以去研究下!

以上仅为个人观点,如果错误,请大家指针,谢谢!

posted @   明&天  阅读(3471)  评论(1编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示
点击右上角即可分享
微信分享提示