.NET-高并发及限流方案
前言:高并发对我们来说应该都不陌生,特别想淘宝秒杀,竞价等等,使用的非常多,如何在高并发的情况下,使用限流,保证业务的进行呢。以下是一个实例,不喜勿喷!
总体思路:
1. 用一个环形来代表通过的请求容器。
2. 用一个指针指向当前请求所到的位置索引,来判断当前请求时间和当前位置上次请求的时间差,依此来判断是否被限制。
3. 如果请求通过,则当前指针向前移动一个位置,不通过则不移动位置
4. 重复以上步骤 直到永远.......
以下代码的核心思路是这样的:指针当前位置的时间元素和当前时间的差来决定是否允许此次请求,这样通过的请求在时间上表现的比较平滑。
实例使用.net写的,仅供参考,了解思路和原理,需要者完全可以用其他方式语言来实现,很简单:
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;
}
}
测试程序如下:
public class Program
{
static LimitService l = new LimitService(, );
public static void Main(string[] args)
{ int threadCount = ; while (threadCount >= )
{
Thread t = new Thread(s => {
Limit(); }); t.Start(); threadCount--;
} Console.ReadKey();
} public static void Limit()
{
int i = ;
int okCount = ;
int noCount = ;
Stopwatch w = new Stopwatch();
w.Start();
while (i < )
{
var ret = l.IsContinue();
if (ret)
{
okCount++;
}
else
{
noCount++;
}
i++;
}
w.Stop();
Console.WriteLine($"共用{w.ElapsedMilliseconds},允许:{okCount}, 拦截:{noCount}");
}
}
测试结果:
最大用时7秒,共处理请求1000000*50=50000000 次
并未发生GC操作,内存使用率非常低,每秒处理 300万次+请求 。以上程序修改为10个线程,大约用时4秒之内
如果是强劲的服务器或者线程数较少情况下处理速度将会更快!!!
以上就是测试的限制高并发的一种简单方案,当然还有其他方式比如:令牌桶算法,漏桶算法等等,可以去研究下!
以上仅为个人观点,如果错误,请大家指针,谢谢!
.NET-高并发及限流方案的更多相关文章
- coding++:高并发解决方案限流技术---漏桶算法限流--demo
1.漏桶算法 漏桶作为计量工具(The Leaky Bucket Algorithm as a Meter)时,可以用于流量整形(Traffic Shaping)和流量控制(TrafficPolici ...
- coding++:高并发解决方案限流技术--计数器--demo
1.它是限流算法中最简单最容易的一种算法 计数器实现限流 每分钟只允许10个请求 第一个请求进去的时间为startTime,在startTime + 60s内只允许10个请求 当60s内超过十个请求后 ...
- coding++:高并发解决方案限流技术-使用RateLimiter实现令牌桶限流-Demo
RateLimiter是guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根据系统的实际情况来调整生成token的速率. 通常可应用于抢购限流防止冲垮系统:限制某接口.服务单位时 ...
- 高并发解决方案限流技术-----使用RateLimiter实现令牌桶限流
1,RateLimiter是guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根据系统的实际情况来调整生成token的速率.通常可应用于抢购限流防止冲垮系统:限制某接口.服务单位 ...
- Guava-RateLimiter实现令牌桶控制接口限流方案
一.前言 对于一个应用系统来说,我们有时会遇到极限并发的情况,即有一个TPS/QPS阀值,如果超了阀值可能会导致服务器崩溃宕机,因此我们最好进行过载保护,防止大量请求涌入击垮系统.对服务接口进行限流可 ...
- Java高并发的常见应对方案
Java高并发的常见应对方案 一.关于并发我们说的高并发是什么? 在互联网时代,高并发,通常是指,在某个时间点,有很多个访问同时到来. 高并发,通常关心的系统指标与业务指标? QPS:每秒钟查询量,广 ...
- WCF学习笔记之并发与限流
最近一直在学习WCF相关知识:本文章将针对并发与限流知识进行一个梳理,由于很多理论的知识所以做一个简单的记录,为今后回顾做一个记录: 一:并发知识 WCF将服务实例封装在一个称为实例上下文的对象中,并 ...
- 高并发WEB网站优化方案
一.什么是高并发在互联网时代,所讲的并发.高并发,通常是指并发访问,也就是在某个时间点,有多少个访问同时到来.比如,百度首页同时有1000个人访问,那么也就是并发为1000.通常一个系统的日PV在千万 ...
- Linux海量数据高并发实时同步架构方案杂谈
不论是Redhat还是CentOS系统,除去从CDN缓存或者数据库优化.动静分离等方面来说,在架构层面上,实 现海量数据高并发实时同步访问概括起来大概可以从以下几个方面去入手,当然NFS的存储也可以是 ...
随机推荐
- 使用Google Closure Compiler全力压缩代码(转)
JavaScript压缩代码的重要性不言而喻,如今的压缩工具也有不少,例如YUI Compressor,Google Closure Compiler,以及现在比较红火的UglifyJS.Uglify ...
- jquery easyui 显示和关闭数据加载的遮罩
$('#yearReportTable').datagrid('loading');//打开等待div $('#yearReportTable').datagrid('loaded');//关闭等待d ...
- bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级【分层图+spfa】
至死不用dijskstra系列2333,洛谷上T了一个点,开了O2才过 基本想法是建立分层图,就是建k+1层原图,然后相邻两层之间把原图的边在上一层的起点与下一层的终点连起来,边权为0,表示免了这条边 ...
- laravel生命周期和核心思想
工欲善其事,必先利其器.在开发Xblog的过程中,稍微领悟了一点Laravel的思想.确实如此,这篇文章读完你可能并不能从无到有写出一个博客,但知道Laravel的核心概念之后,当你再次写起Larav ...
- curl 做爬虫 用服务器代理ip
有时候会ip会封锁,所以会用一些模拟代理ip进行抓取测试 从网上找了一下代码 function curl_string ($url,$user_agent,$proxy){ $ch = ...
- mac更改本地mysql登陆密码
安装完mysql 之后,登陆以后,运行任何命令,提示 You must SET PASSWORD before executing this statement解决办法. step 1: SET PA ...
- 反向代理与Real-IP和X-Forwarded-For(转)
如下图所示,客户端通过Nginx Proxy1 和 Nginx Proxy2 两层反向代理才访问到具体服务Nginx Backend(或如Tomcat服务).那Nginx Backend如何才能拿到真 ...
- [译]curl_multi_info_read
curl_multi_info_read - read multi stack informationals读取multi stack中的信息 SYNOPSIS#include <curl/cu ...
- 揭开WebService的神秘面纱
一.序言 大家或多或少都听过WebService(Web服务),有一段时间很多计算机期刊.书籍和网站都大肆的提及和宣传WebService技术,其中不乏很多吹嘘和做广告的成分.但是不得不承认的是Web ...
- Git——github基本操作
基本概念 上一篇文章写到git共享仓库,但是有个局限性,就是这个仓库存在于本地,其他人无法从我们这个仓库拿到共享的内容 但是我们可以将这个共享仓库放入一个远程的服务器上,然后设置一些登录权限就能完美的 ...