内存固定窗口限流算法的简单实现
作者:admin 来源:原创 2023/9/28 15:15:53

    在计算机网络中,限流就是控制网络接口发送或接收请求的速率,它可防止DOs攻击和限制Web爬虫。

    也称流量控制。是指系统在面临高并发或者大流量请求的情况下,限制新的请求对系统的访问,从而保证系统的访问。

    常见限流算法:

    一、固定窗口算法

    二、滑动窗口限流算法

    三、漏桶算法

    四、令牌桶算法

    下面是内存固定窗口限流算法的简单实现。

    (1)使用Hashtable保存每个请求来源。

    (2)定义模型rateRule作为限流规则。

    (3)计算TcpClient中的RemoteEndPoint属性的MD5值作为哈希表的key,value值包括访问次数、过期时间,至多访问次数。

      (4)  每一个tcpClient都经过checkRule函数,超限后直接关闭连接,并返回true否则返回false。

      (5)  首先提取请求的RemoteEndPoint属性并计算其MD5值作为限流目标,然后根据限流目标到hashTable中查找限流参数。如果不存在,则添加一个记录,访问次数是1,过期时间是当前时间+限流时间长度。如果存在则检查是否过期,如果过期,则参数重置。如果未过期,则访问次数+1并检查访问次数是否超限,超限则直接关闭,返回true,否则返回false。

		#region 限流设置
		/// <summary>
		/// 限流哈希表
		/// </summary>
		static public Hashtable rateLimiterTable { get; set; } = new Hashtable(20);
		/// <summary>
		/// 限流规则
		/// </summary>
		public class rateRule
		{
			/// <summary>
			/// 
			/// </summary>
			/// <param name="_timeOffTotal">时间长度内最多timeOffTotal次</param>
			/// <param name="timeSpan">过期时间长度</param>
			public rateRule(string _name, int _timeOffTotal, TimeSpan _timeSpan)
			{
				name = _name;
				timeOffTotal = _timeOffTotal;
				timespace = _timeSpan;
				timeOff = DateTime.Now.Add(_timeSpan);
			}
			public string name { get; set; }
			/// <summary>
			/// 访问次数
			/// </summary>
			public int sum { get; set; } = 1;
			public TimeSpan timespace { get; set; }
			/// <summary>
			/// 过期时间
			/// </summary>
			public DateTime timeOff { get; set; }
			/// <summary>
			/// timeOff时间内最多timeOffTotal次
			/// </summary>
			public int timeOffTotal { get; set; }
		}

		#region 将远程终结点格式化为以IP地址和端口号为表示形式的网络端点
		/// <summary>
		/// 将远程终结点格式化为以IP地址和端口号为表示形式的网络端点
		/// </summary>
		/// <param name="RemoteEndPoint">远程终结点字符串</param>
		/// <returns></returns>
		public IPEndPoint IpAndPortFormat(EndPoint RemoteEndPoint)
		{
			try
			{
				IPAddress ipAdes = IPAddress.Parse("0.0.0.0");
				int port = 0;
				string[] array_ipAndPort = RemoteEndPoint.ToString().Split(':');
				if (array_ipAndPort.Length == 2)
				{
					IPAddress.TryParse(array_ipAndPort[0], out ipAdes);
					int.TryParse(array_ipAndPort[1], out port);
				}
				return new IPEndPoint(ipAdes, port);
			}
			catch (Exception ex)
			{
				Tools.Instance.WriteError(ex);
			}
			return new IPEndPoint(1, 0);
		}
		#endregion

		/// <summary>
		/// 限流监测
		/// </summary>
		/// <param name="tc"></param>
		/// <returns></returns>
		public bool checkRule(TcpClient tc)
		{
			bool close = false;
			IPEndPoint iPEndPoint = IpAndPortFormat(tc.Client.RemoteEndPoint);
			string ip = iPEndPoint.Address.ToString();
			List<rateRule> rules = null;
			lock (rateLimiterTable.SyncRoot)
			{
				rules = (List<rateRule>)rateLimiterTable[ip];
			}
			if (rules == null)
			{
				rules = new List<rateRule>();
				rules.Add(new rateRule("[1分钟内至多3次]", 3, new TimeSpan(0, 1, 0)));
				rules.Add(new rateRule("[5分钟内至多10次]", 10, new TimeSpan(0, 5, 0)));
				rules.Add(new rateRule("[10分钟内至多15次]", 15, new TimeSpan(0, 10, 0)));
				rules.Add(new rateRule("[20分钟内至多20次]", 20, new TimeSpan(0, 20, 0)));
				rules.Add(new rateRule("[1小时内至多30次]", 30, new TimeSpan(1, 0, 0)));
				rules.Add(new rateRule("[1.5小时内至多60次]", 60, new TimeSpan(1, 30, 0)));
				rateLimiterTable.Add(ip, rules);
			}
			else
			{
				foreach (var rule in rules)
				{
					if (DateTime.Now < rule.timeOff)
					{
						//在限制时间内
						if (rule.sum > rule.timeOffTotal)
						{
							//超了
							if (close == false)
							{
								tc.Close();
								close = true;
							}
							//inout.Common.Tools.Instance.WriteDebugLog($"{ip},规则:{rule.name}超期");
						}
						else
						{
							//未超
						}
						rule.sum++;
					}
					else
					{
						//不在限制时间内了,恢复
						//inout.Common.Tools.Instance.WriteDebugLog($"{ip},规则{rule.name}恢复,次数达到{rule.sum}");
						rule.sum = 1;
						rule.timeOff = DateTime.Now.Add(rule.timespace);
					}
				}
			}
			return close;
		}

    应用:

TcpListener tcpListener = new TcpListener(ipAndPort);
...
TcpClient tc = tcpListener.AcceptTcpClient();
if (Tools.Instance.checkRule(tc)==false)
{
...											
}

    限流效果:

    部署在服务器中,确实达到了一定的限流效果。可以叠加任意数量,任意时间长度的限流规则,每个请求经过重重考验方能到达目的地,把访问太频繁的一切请求直接close。    

2023/8/5 22:00:06:43.136.114.252,规则[1分钟内至多3次]恢复,次数达到2
2023/8/5 22:00:06:43.136.114.252,规则:[1小时内至多30次]超期,次数达到61
2023/8/5 22:00:06:43.136.114.252,规则:[2小时内至多50次]超期,次数达到72
2023/8/5 22:00:08:103.91.209.30,规则:[5分钟内至多10次]超期,次数达到13
2023/8/5 22:00:08:103.91.209.30,规则:[10分钟内至多15次]超期,次数达到39
2023/8/5 22:00:08:103.91.209.30,规则:[1小时内至多30次]超期,次数达到41
2023/8/5 22:00:08:103.91.209.30,规则:[1.5小时内至多40次]超期,次数达到50
2023/8/5 22:00:08:103.91.209.30,规则:[2小时内至多50次]超期,次数达到292
2023/8/5 22:00:23:103.91.209.30,规则:[5分钟内至多10次]超期,次数达到14
2023/8/5 22:00:23:103.91.209.30,规则:[10分钟内至多15次]超期,次数达到40
2023/8/5 22:00:23:103.91.209.30,规则:[1小时内至多30次]超期,次数达到42
2023/8/5 22:00:23:103.91.209.30,规则:[1.5小时内至多40次]超期,次数达到51
2023/8/5 22:00:23:103.91.209.30,规则:[2小时内至多50次]超期,次数达到293
2023/8/5 22:00:38:103.91.209.30,规则:[1分钟内至多3次]超期,次数达到4
2023/8/5 22:00:38:103.91.209.30,规则:[5分钟内至多10次]超期,次数达到15
2023/8/5 22:00:38:103.91.209.30,规则[10分钟内至多15次]恢复,次数达到41
2023/8/5 22:00:38:103.91.209.30,规则:[1小时内至多30次]超期,次数达到43
2023/8/5 22:00:38:103.91.209.30,规则:[1.5小时内至多40次]超期,次数达到52
2023/8/5 22:00:38:103.91.209.30,规则:[2小时内至多50次]超期,次数达到294
2023/8/5 22:00:53:103.91.209.30,规则[1分钟内至多3次]恢复,次数达到5
2023/8/5 22:00:53:103.91.209.30,规则:[5分钟内至多10次]超期,次数达到16
2023/8/5 22:00:53:103.91.209.30,规则:[1小时内至多30次]超期,次数达到44
2023/8/5 22:00:53:103.91.209.30,规则:[1.5小时内至多40次]超期,次数达到53
2023/8/5 22:00:53:103.91.209.30,规则:[2小时内至多50次]超期,次数达到295
2023/8/5 22:01:03:43.136.114.252,规则:[1小时内至多30次]超期,次数达到62

我已将代码上传,下载码是:D0B001B435

    下载码是啥?如何下载=》点击查看

称      呼:
联系方式:
您的评论:
技术支持:l.w.dong@qq.com www.luweidong.cn
广州市   wx:lwdred
Copyright © 2014 三味书屋 All Rights Reserved
技术支持:l.w.dong@qq.com  sitemap xml  sitemap html

粤公网安备44010602011869号

粤ICP备13031080号-1