开放平台的请求限流方案.docx

上传人:b****8 文档编号:10154305 上传时间:2023-02-08 格式:DOCX 页数:18 大小:390.32KB
下载 相关 举报
开放平台的请求限流方案.docx_第1页
第1页 / 共18页
开放平台的请求限流方案.docx_第2页
第2页 / 共18页
开放平台的请求限流方案.docx_第3页
第3页 / 共18页
开放平台的请求限流方案.docx_第4页
第4页 / 共18页
开放平台的请求限流方案.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

开放平台的请求限流方案.docx

《开放平台的请求限流方案.docx》由会员分享,可在线阅读,更多相关《开放平台的请求限流方案.docx(18页珍藏版)》请在冰豆网上搜索。

开放平台的请求限流方案.docx

开放平台的请求限流方案

开放平台的请求限流方案

 

场景

在设计开放性平台系统(尤其OpenAPI类型平台)时有三把利器用来保护系统:

缓存、降级和限流。

●缓存:

提升系统访问速度和增大系统能处理的容量,抗高并发流量;

●降级:

当服务出问题或者影响到核心流程的性能则需要暂时屏蔽掉,待高峰或者问题解决后再打开;

●限流:

有些场景并不能用缓存和降级来解决,比如稀缺资源(秒杀、抢购)、写服务(如评论、下单)、频繁的复杂查询(评论的最后几页)、恶意爬虫攻击,因此需有一种手段来限制这些场景的并发/请求量,即限流。

目的

限流的目的是通过对并发连接/访问请求进行限量,或者对一个时间窗口内的请求进行限速来保护系统,一旦达到限制阈值或速率则可以拒绝服务(返回HTTP状态码、重定向到错误页或告知资源没有了)、排队或等待(比如秒杀、评论、下单)、降级(返回兜底数据或默认数据,如商品详情页库存默认有货)。

限流策略

1.IP

针对调用方IP进行限制,黑白名单、请求速率、带宽流量

2.EndPoint

系统平台开放的url、接口地址、服务域名等都可视为一个限流端点(EndPoint)对其进行不同粒度限制

3.UserToken

使用用户唯一标识限制用户级别的调用,常用唯一标识:

●Cookies\SessionId\Token:

会话唯一标识

●UserId:

用户唯一标识

●DeviceId:

用户设备号

4.客户端Key

使用调用方客户端的唯一标识,对第三方调用进行限制,常用标识:

●AppId:

第三方唯一ID

●Header\User-agent

●AppDomain:

第三方域名

●APPName:

第三方服务名

流控方式

1.针对资源的限制

●总并发数:

Web容器并发连接数、数据库连接池、应用线程池、文件句柄

●瞬时并发数:

Web服务器Http连接数,socket连接数等

●CPU\内存负载情况

●网络带宽流量情况

2.针对频率的限制

●时间窗口请求速率:

一定时间窗口期内的request请求速率(QPS\TPS)

●RPC调用速率

●MQ生产消费速率

总体概览

限流算法

1.计数器

简单直接,配合redis等缓存原子操作实现

2.漏桶

漏桶(LeakyBucket)算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率.示意图如下:

可见这里有两个变量,一个是桶的大小,支持流量突发增多时可以存多少的水(burst),另一个是水桶漏洞的大小(rate),在某些情况下,漏桶算法不能够有效地使用网络资源。

因为漏桶的漏出速率是固定的参数,所以,即使网络中不存在资源冲突(没有发生拥塞),漏桶算法也不能使某一个单独的流突发到端口速率。

因此,漏桶算法对于存在突发特性的流量来说缺乏效率。

而令牌桶算法则能够满足这些具有突发特性的流量。

通常,漏桶算法与令牌桶算法可以结合起来为网络流量提供更大的控制。

3.令牌桶

令牌桶算法(TokenBucket)和LeakyBucket效果一样但方向相反的算法,更加容易理解.随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了.新请求来临时,会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务.

令牌桶的另外一个好处是可以方便的改变速度.一旦需要提高速率,则按需提高放入桶中的令牌的速率.一般会定时(比如100毫秒)往桶中增加一定数量的令牌,有些变种算法则实时的计算应该增加的令牌的数量.

限流技术

常用限流技术可针对其作用的位置分为如下几个层级:

代理层

基于网络的接入入口层的流量整形(Trafficshaping)策略进行控制,针对使用的负载均衡策略可分为:

●Nginx:

使用软负载,可利用Nginx自带的模块

ngx_http_limit_conn_module:

http连接限制,可对某个KEY对应的总的网络连接数进行限流,可以按照如IP、域名维度进行限流

ngx_http_limit_req_module:

request请求限制,可对某个KEY对应的请求的平均速率进行限流

ngx_stream_limit_conn_module:

流量限制

●Nginx+lua:

基于Nginxlua模块ngx_lua,或直接使用Openresty的lua-resty-limit-traffic,动态控制负责限流规则

Nginx-Lua-API:

●HAproxy:

●硬件负载均衡器(A10\F5):

API层

应用业务逻辑加入Ratelimit控制逻辑,实现方式可结合如下框架:

●Redis:

计数器

●Google-Guava:

google令牌桶算法开源框架,提供了限流工具类RateLimiter

●Gateway模式

线程层

线程级别对请求控制:

●线程池

●熔断器

●舱壁隔离技术

●信号量隔离技术

●降级方案

限流粒度

根据上文提到的限流策略,可将限流的粒度级别由粗到细做如下划分:

●IP级:

针对调用方IP限制

●应用级:

针对调用方(第三方)域名、租户级(AppId)

●业务级:

针对用户、应用服务url、开放接口方法地址

由上向下粒度范围逐级变小,限制更精确

限流方案

本文针对作用在代理层的限流控制,提供一套完整开放性平台限流技术解决方案。

现有方案

当前已有的限流方案调研:

●OpenResty——推荐

一组基于Lua开发的nginxmodule,开源后是对nginx相关功能的扩展,可视为对nginx的扩展插件,对nginx侵入性低、可跟随nginx主版本发布,兼容性好

http:

//openresty.org/cn/

●整合nginxmodule——较复杂

自行安装配置ngx_lua、LuaJIT及相关扩展依赖

●Tengine——定制化

淘宝开源webserver,是淘宝从nginxfork的一个分支,加入二次开发功能,依赖特定nginx主版本

●Kong——APIGateway

Kong是一个集成了Nginx的工具(也可嵌入Openresty整合运行),限流仅是其提供的功能之一,更多功能定位是偏向于在客户端和(微)服务间转发API通信的API网关(同样功能的开源软件还有Zuul),专为保护、管理和扩展业务侧API而设计。

同时通过插件(Lua编写)扩展功能,提供了日志记录,身份认证,流量控制、系统监控统计等功能。

Kong有两个主要组件:

◆KongServer:

基于 nginx 的服务器,用来接收API请求

◆DataStore:

基于ApacheCassandra(2.2.x )或PostgreSQL(9.4+) 存储Kong相关内部数据

以上相关方案提供了基本的限流、分流、降级等基础功能,但未实现规则的动态配置与更新等管理功能,因此基于以上问题提出如下解决构想,以整合限流系统与后台规则系统

核心思想

●前端:

1)动态模式:

基于Nginx+lua+redis技术对网络请求进行流量整形,动态拦截请求并匹配规则

2)静态模式:

基于Nginx的limit_conn与limit_req模块对IP、域名等固态规则拦截,以应对动态模式中redis出现异常导致规则库瘫痪时的兜底限流策略

注:

limit_conn与limit_req模块的限流拦截顺序优先于Lua实现的限流策略

●后端:

基于WebUI管理、配置、更新限流规则的后台系统,对限流规则进行可视化动态配置与刷新

总体架构

业务流程

通过Nginx模块拦截入口HTTP请求,先根据limit_conn与limit_req模块做静态拦截匹配校验,然后由lua模块从redis读取后台限流规则进行动态校验,规则读取策略可分为:

●静态固化规则:

类似限制总并发数、连接数、流量上限阈值、速率阈值等字典规则,可在nginx启动时加入初始化脚本从redis获取后存储在nginx本地共享缓存ngx.shared.DICT(lua_shared_dict),当规则更新时同步刷新本地缓存,以保证每次请求匹配规则时直接从本地缓存获取,避免每次都请求redis

●动态规则:

类似时间窗口内的接口调用次数阈值、用户请求频次等,涉及到修改数值“+1”运算类型的规则,可动态从redis每次请求获取并更新回redis

●本地缓存的设计:

1)Nginx启动时加入lua初始化脚本,在启动阶段完成从redis拉取限流规则,装载本地缓存,如发生异常,则在本地缓存标记限流开关关闭,从而不拦截请求,而走limit_conn与limit_req模块的固化静态规则兜底

2)本地缓存根据规则分区存储:

●静态字典规则:

固化数据,根据规则分类,开辟不同缓存区存储

●动态规则:

涉及到数值修改的规则,根据上层负载均衡策略选择使用本地缓存还是分布式限流缓存。

如负载均衡策略采用IP-Hash等可路由终端到同一个Nginx节点的策略时,可通过取模方式平均分配规则阈值,并完成每次请求拦截的数值修改操作,即将分布式限流转换为本地限流

3)本地缓存刷新:

◆定时器:

通过ngx.timer.at在nginx进程中注册定时器,定期回调方法刷新缓存

TimerDemo:

timer.lua

--nginx.conf:

in"http"tosetting:

--init_worker_by_lua_filelua/timer.lua

localdelay=120--inseconds

localnew_timer=ngx.timer.at

locallog=ngx.log

localINFO=ngx.INFO

localERR=ngx.ERR

localhandler

handler=function(premature,var)

--dobusiness

log(INFO,"=======>timerwork!

==="..ngx.worker.pid().."==="..tostring(premature).."==="..var)

ifprematurethen

--nginxreload:

premature==true

return

end

if0==ngx.worker.id()then

localok,err=new_timer(delay,handler,"test")

ifnotokthen

log(ERR,"failedtocreatetimer:

",err)

return

end

end

end

if0==ngx.worker.id()then

localok,err=new_timer(1,handler,"test")

ifnotokthen

log(ERR,"failedtocreatetimer:

",err)

return

end

end

◆接口触发:

通过Lua开放刷新本地ngx.shared.DICT的接口,外部调用此url,完成刷新操作

注:

●接口逻辑需校验认证安全,保证调用端的授权有效,防止非法调用

●接口需处理redis异常导致的刷新失败情况

请求时序

数据结构

ngx.shared.DICT

通过ngx.shared.DICT本地缓存可在Nginx中创建全局共享的一定大小的内存区,

参见:

特点:

●在nginx的多个worker进程间共享

●通过热加载方式(-sreload或HUP)重启nginx时,缓存不丢失,除非nginx进程退出才会失效

●缓存的容量超过预先申请的内存池大小的时,ngx.shared.DICT.set方法会尝试以LRU的形式淘汰一部分内容

●支持“原子级”(atomically)操作,保证线程安全

1.缓存分类

●开关类

●静态规则类

●动态规则类

2.运行机制

●启动时加载

●刷新机制:

定时刷新或接口触发刷新

Redis

限流逻辑

具体限流方式和流程策略如下:

限流开关

作用:

通过配置参数控制是否打开\关闭限流拦截,以达到动态开闭流控目的;

分类:

●总开关:

拦截入口总控制,判定请求是否进入限流拦截系统

●各级限流开关:

分别针对IP\域名级、应用服务级、API级等不同限制级别是否生效的开关

IP\域名黑白名单

作用:

定制服务端可访问IP或域名黑白名单,直接限制远程端对服务端的访问,同时也可防止恶意爬虫

限制级别:

IP\域名级

IP\域名访问频率

作用:

针对特定IP或域名限制访问频率

限制级别:

IP\域名级

服务并发数

作用:

定制当前应用对外提供的总并发连接数限制

限制级别:

应用级

服务访问频率

作用:

对特定外部调用服务名或第三方应用AppId进行总请求频率限制

限制级别:

应用级、App级

API访问频率

作用:

对调用特定API的外部服务或第三方应用进行总请求频率限制

限制级别:

API级(接口级)

规则管理

后台规则可视化管理系统

配置部署

OpenResty部署

1.下载安装包

wgethttps:

//openresty.org/download/openresty-1.11.2.2.tar.gz

2.依赖库安装:

将这些相关的库perl5.6.1+,libreadline,libpcre,libssl安装在系统中。

步骤:

1)输入以下命令,一次性安装需要的库

yuminstallreadline-develpcre-developenssl-develperl

2)相关库安装成功。

安装成功后会有“Complete!

”字样

3.解压编译安装:

tar-xzvfopenresty-1.11.2.2.tar.gz

cdopenresty-1.11.2.2/

./configure

make

makeinstall

安装完成后,会默认在/usr/local目录下安装openresty目录,结构如下:

4.配置Nginxconf文件:

viopenresty/nginx/conf/nginx.conf

worker_processes8;#根据cpu配置

error_loglogs/error.loginfo;#生产环境不配置info

events{

worker_connections65535;

}

http{

server{

listen80;

#test

location/hello{

default_typetext/html;

content_by_lua'

ngx.say("

hello,world

")

';

}

}

}

5.启动Nginx

./nginx/sbin/nginx

验证:

访问:

http:

//${nginx_host}/hello

6.热加载nginx.conf

./nginx/sbin/nginx-sreload

7.关闭nginx

./nginx/sbin/nginx-squit

8.查看日志:

tail-fnginx/logs/error.log

tail-fnginx/logs/access.log

9.

问题汇总

1.限流方案前方如配置A10\F5或nginx\LVS做负载或反向代理后可能产生的问题

1)A10自带流量整形策略,是否启用

2)Http请求接入方式:

域名?

IP(虚实)?

3)A10的负载均衡方式及Targetserver的心跳检查机制

4)A10路由策略,Ip-hash?

5)客户端真实IP(Client-Real-IP)的透传方式、参数名

6)区分不同服务请求的方法:

端口?

Url前缀?

7)Https的负载及路由策略

2.Lua访问redis的性能与限制、限流性能影响

3.Nginxconf文件reload问题

4.限流规则的匹配逻辑--流程

5.是否引入规则引擎及其执行过程

6.业务需求、粒度

7.运维、部署

8.与WAF整合

9.可能存在的安全隐患

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 文学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1