写着写着突破 300 篇文章了
SpringBoot学习交流
▲长按图片识别优惠券
师傅:那你知道常用的限流算法嘛?
悟纤:师傅,我就知道一个计算器算法。
师傅:那这一节,你把你知道的给大家介绍介绍。要好好介绍,说的不好,不准吃饭。
悟纤:师傅,必须认真对待。
一、计数器算法原理
计数器法是限流算法里最简单也是最容易实现的一种算法,一般我们会限制一秒钟能够通过的请求数。比如我们规定,对于A接口来说,我们1分钟的访问次数不能超过100个。那么我们可以这么做:在一开始的时候,我们可以设置一个计数器counter,每当一个请求过来的时候, counter就加1,如果counter的值大于100并且该请求与第一个请求的间隔时间还在1分钟之内,那么说明请求数过多; 如果该请求与第一个请求的间隔时间大于1分钟,且counter的值还在限流范围内,那么就重置 counter。
二、计数器算法小实现
对于技术,再多的理论,都不如实践来的好理解,来,我看下要怎么实现。
看下具体的一个代码:
public class Counter { public long timeStamp = System.currentTimeMillis(); // 当前时间 public int reqCount = 0; // 初始化计数器 public final int limit = 100; // 时间窗口内最大请求数 public final long interval = 1000 * 60; // 时间窗口ms
public boolean limit() { long now = System.currentTimeMillis(); if (now < timeStamp + interval) { // 在时间窗口内 reqCount++; // 判断当前时间窗口内是否超过最大请求控制数 return reqCount <= limit; } else { timeStamp = now; // 超时后重置 reqCount = 1; return true; } }}
说明:上面代码逻辑很简单,就是在1秒之内进行统计请求的总个数,然后校验请求的个数是否超过了限制的请求数,如果在1秒之外,那么就重置请求数。
师傅:差不多,是这么个意思,那徒儿知道,这种算法有什么弊端呐?
悟纤:师傅,徒儿愚钝,请师傅指点一二。
师傅:对于秒级以上的时间周期来说,会存在一个非常严重的问题,那就是临界问题。
从上图中我们可以看到,假设有一个恶意用户,他在0:59时,瞬间发送了100个请求,并且1:00又瞬间发送了100个请求,那么其实这个用户在 1秒里面,瞬间发送了200个请求。我们刚才规定的是1分钟最多100个请求,也就是每秒钟最多1.7个请求,用户通过在时间窗口的重置节点处突发请求, 可以瞬间超过我们的速率限制。用户有可能通过算法的这个漏洞,瞬间压垮我们的应用。
悟纤:师傅,那有什么方案可以解决这个问题呐?
师傅:今天师傅累了,下节给你揭晓。
三、小思考
(1)计算器算法存在的问题,可以怎么解决呢?
(2)应用限流的常用算法你都知道哪些?你理解了嘛?