.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秒之内
如果是强劲的服务器或者线程数较少情况下处理速度将会更快!!!
以上就是测试的限制高并发的一种简单方案,当然还有其他方式比如:令牌桶算法,漏桶算法等等,可以去研究下!
以上仅为个人观点,如果错误,请大家指针,谢谢!
没有什么优雅的代码比空代码的执行效率更高
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 记一次.NET内存居高不下排查解决与启示