限流

https://zhuanlan.zhihu.com/p/678776165

比如系统本来可以处理1000个请求,忽然一下子来了2000个,为了不让系统崩溃,最简单的方式,就是限流,我只接1000个,超出1000个的不提供服务

  • 常用限流算法
#漏桶算法
一个请求在被系统处理之前,先找一个漏桶存起来,然后再以固定速率流出,比如这个漏桶可以存1000个请求,如果漏桶中有超出1000个未被处理的请求,那么这部分请求就会溢出,也就是被丢弃,比如我们常用的消息队列。

#令牌桶算法
令牌桶就是以固定的速率产生,并缓存到令牌桶中,每个请求必选先获取令牌才能系统处理,令牌桶存满的时候,多余的令牌被丢弃。


#滑动时间窗口
既然以时间为界限不行的话,我们就以时间窗口为界限,保证每个时间段内都不能超过1000qps
  • Nginx限制RPS
  • limit_req_zone:用来限制单位时间内的请求数,即速率限制 , 采用的漏桶算法 leaky bucket
http {
    #limit_req_zone $binary_remote_addr zone=limit_zone:10m rate=10r/s;
    limit_req_zone $binary_remote_addr zone=reqlimit:64m rate=5000r/s;  #参考

    server {
        listen 80;
        server_name example.com;

        location / {
            #limit_req zone=limit_zone burst=20;
            #limit_req zone=limit_zone burst=20 nodelay;   # 不延时立即返回
            limit_req zone=reqlimit burst=1000;  #参考

            proxy_pass http://backend;
        }
    }
}
  • 参数:
    limit_req_zone指令用于定义一个名为limit_zone的限流区域。
    $binary_remote_addr变量表示客户端的IP地址,
    zone=limit_zone:10m 表示定义一个limit_zone的10M内存区,存放限流信息
    rate=10r/s 表示限制每秒处理10个请求

  • 在location块中
    limit_req 指令用于将请求限制应用于特定的URL路径。
    burst=20 表示缓冲区大小20个(即等待队列),
    nodelay 超过第秒10个+缓冲区20个 共30个之后的请求不延时,立即返回503错误
    proxy_pass 指令用于将请求转发到后端服务器

并发连接数限制
http {
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    limit_conn_zone $binary_remote_addr zone=iplimit:64m;  #参考
    ...
    server {
        ...
        location /download/ {
            # 限制一个客户端ip一个连接
            limit_conn addr 1;

            # 限制单个 IP 同时最多能持有 1 个连接
            limit_conn perip 1;
            # 限制服务器处理并发连接总数
            limit_conn iplimit 5000 ;

        }
    }
}
  • 说明:
    这个配置限制了对/download/的并发连接数为1
    以上这两个模块通过定义一个”zone”来实现限制,这个”zone”可以按照IP或者其他变量进行分类,并使用内存来存储状态

降级

我们前面看到了,限流之后有一部分的请求直接返回的503,这样对用户体验非常不好,但是我们可能有时候会看到这样的页面,比如 xx活动异常火爆,请稍后再试等提示页。或者是某个商品详情页,优先推送缓存数据而非实时数据,这就是服务降级。服务降级的核心是对非核心的,非关键的业务进行降级。



熔断

熔断这个词大家应该是熟悉的,比如家里的保险丝,当电流过大或者发生短路的时候,就会熔断,从而避免发生更大的危害。服务熔断也类似,当被调用方出现故障。调用方出于自我保护的目的,主动停止调用。为什么要主动停止调用?我之前就有过这样的经历,由于某个MySQL服务器性能的问题,执行一个SQL要好几秒。MySQL的请求越来越多,最终导致MySQL宕机,接着php的请求也越来越多,php进程打满,最终php也跟着报错。最终整个服务挂掉。



支持软件

nginx,sentinel和hystrix