web系统在高并发场景下,为避免系统宕机或出现功能完全不可用的情况下,需要进行相应的限流处理。限流处理应该结合系统架构和业务逻辑进行处理,下面列一些相关限流方法。
一、代理层
代理层常用的是用nginx做反向代理。nginx可以进行的限流配置有:
1、limit_conn_zone限制连接数,主要是限制单个ip的连接数
http {
#限流配置
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
proxy_pass http://192.168.1.15:8080;
#限流配置
limit_conn addr 2;
}
}
limit_conn_zone配置中:
1.$binary_remote_addr代表访问ip地址,
2.addr:10m中addr代表配置名称和下面limit_conn必须一致。10m代表共享内存大小,共享内存里面以ip为key,存储每个ip的连接数,当数据超过内存限制时,服务器返回报错。
3.limit_conn作用为限制每个ip只能存在2个连接数
:
2、limit_req_zone,限制单一的IP地址的请求的频次
http {
#限流配置
limit_req_zone $binary_remote_addr zone=addr_req:10m rate=1r/s;
server {
proxy_pass http://192.168.1.15:8080;
#限流配置
limit_req zone=addr_req burst=10 nodelay;
}
}
limit_req_zone配置中:
1.$binary_remote_addr同上
2.addr:10m用来存储访问的频次信息。rate代表处理请求的频次为1秒一个请求
3.
limit_req中burst=10代表突发请求大小为10.当1秒钟有11次请求过来,第一个直接处理其余10个进入突发缓冲区等待处理。
nodelay默认为空,不配置时所有超过限制数量的请求都会排队处理。当配置时,超过突发缓冲区的请求将返回503。基于漏桶算法实现。
3:ngx_http_upstream_module中设置max_conns
限制nginx到后端服务器的连接数
在upstream中每个主机后面配置 max_conns=1000,代表nginx负责均衡到该主机的最大连接数为1000;
二、业务层
限流常用的在业务层使用计数器(一般是单位时间内限制次数),漏桶算法和令牌桶算法进行处理。具体算法细节这里不赘述了。
漏桶和令牌桶的比较:令牌桶可以在运行时控制和调整数据处理的速率,处理某时的突发流量。放令牌的频率增加可以提升整体数据处理的速度,而漏桶不行,因为它的流出速率是固定的,程序处理速度也是固定的
java自带的Semaphore(信号量)限流。
三、微服务层
Dubbo中的限流通过TpsLimitFilter来实现,会在invoker执行实际业务逻辑前进行拦截,判断单位时间请求数是否超过上限,如果超过,抛出异常阻断调用。
最终是通过TPSLimiter的isAllowable实现限流 ,其内部采用了计数器算法,单位时间内限制多少调用次数,超过限制,返回false。
Spring Cloud Gateway中,官方就提供了RequestRateLimiterGatewayFilterFactory这个类,适用Redis和lua脚本实现了令牌桶的方式。具体实现逻辑在RequestRateLimiterGatewayFilterFactory类。
参考文章:高并发系统的限流方案如何实现 - 知乎