1.限流算法:
1.计数器算法
计数器算法采用计数器实现限流有点简单粗暴,一般会限制一秒钟的能够通过的请求数,比如限流qps为100,算法的实现思路就是从第一个请求进来开始计时,在接下去的1s内,每来一个请求,就把计数加1,如果累加的数字达到了100,那么后续的请求就会被全部拒绝。等到1s结束后,把计数恢复成0,重新开始计数。
具体的实现可以是这样的:对于每次服务调用,可以通过AtomicLong#incrementAndGet()方法来给计数器加1并返回最新值,通过这个最新值和阈值进行比较。
这种实现方式有一个弊端:如果在单位时间1s内的前10ms,已经通过了100个请求,那后面的990ms,只能把请求拒绝,这种现象称为“突刺现象”。
2. 漏桶算法
算法思想:
- 水(请求)从上方倒入水桶,从水桶下方流出(被处理);
- 来不及流出的水存在水桶中(缓冲),以固定速率流出;
- 水桶满后水溢出(丢弃)。
- 这个算法的核心是:缓存请求、匀速处理、多余的请求直接丢弃。
3.令牌桶算法
算法思想:
- 令牌以固定速率产生,并缓存到令牌桶中;
- 令牌桶放满时,多余的令牌被丢弃;
- 请求要消耗等比例的令牌才能被处理;
- 令牌不够时,请求被缓存。
两种算法区别:是否允许突发流量(burst)的处理,漏桶算法能够强行限制数据的实时传输(处理)速率,对突发流量不做额外处理;而令牌桶算法能够在限制数据的平均传输速率的同时允许某种程度的突发传输。
Nginx按请求速率限速模块使用的是漏桶算法
springcloudgateway可以使用 计数器算法、漏桶算法、令牌桶算法
2.Nginx限流参数配置:
http {
include mime.types;
default_type application/octet‐stream;
sendfile on;
keepalive_timeout 65;
# 设置限流配置
limit_req_zone $binary_remote_addr zone=myRateLimit:10m rate=2r/s;
server {
listen 8081;
server_name localhost;
charset utf‐8;
location / {
limit_req zone=myRateLimit burst = 5 nodelay;
root html;
index index.html index.htm;
}
}
}
binary_remote_addr :是一种key,表示基于 remote_addr(客户端IP) 来做限流, binary_ 的目的是压缩内存占用量,是限制同一客户端ip地址。
zone:定义共享内存区来存储访问信息, myRateLimit:10m 表示一个大小为10M,名字为 myRateLimit的内存区域。1M能存储16000 IP地址的访问信息,10M可以存储16W IP地址访 问信息。
rate :表示允许相同标识的客户端的访问频次,用于设置最大访问速率,rate=10r/s 表示每秒最多处理10个请求。Nginx 实际上以 毫秒为粒度来跟踪请求信息,因此 10r/s 实际上是限制:每100毫秒处理一个请求。这意味 着,自上一个请求处理完后,若后续100毫秒内又有请求到达,将拒绝处理该请求。
burst :译为突发、爆发,表示在超过设定的处理速率后能额外处理的请求数,当 rate=2r/s 时,将1s拆成2份,即每500ms可处理1个请求。
此处,burst=5 ,若同时有6个请求到达,Nginx 会处理第一个请求,剩余5个请求将放 入队列,然后每隔500ms从队列中获取一个请求进行处理。若请求数大于6,将拒绝处理 多余的请求,直接返回503. 不过,单独使用 burst 参数并不实用。假设 burst=50 ,rate为10r/s,排队中的50个请 求虽然每100ms会处理一个,但第50个请求却需要等待 50 * 100ms即 5s,这么长的处 理时间自然难以接受。 因此,burst 往往结合 nodelay 一起使用。
nodelay:如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回503,如果没有设置,则所有请求会等待排队。