一、前言
另外,对于非法请求的恶意流量(如刷单),除了安全层面的防护外,业务侧针对业务属性的频控也是非常有必要的。
为满足公司日常业务场景中,对限流方式多样化的需求,我们推出了一款轻量级限流组件 MOAT 。本文将从背景需求与目标、设计方式、具体实现,为大家逐一介绍。
二、背景
业务中对限流的需求主要有以下几个方面:
业务维度,即业务需求,如在开放平台 API 多维度限制单位时间访问量;
系统稳定性维度,是保护应用的措施,防止过载;
异常业务流量,针对特定场景的异常请求做限制,并需要进行自动拉黑处理或自定义后置处理,来实现整体频控闭环。
三、目标
基于以上的背景需求,对 Moat 频控组件做了相关规划,确定其实现目标。整体是对于限流频控,能做到多维度控制、轻量级、可扩展、自闭环。包括配置规则策略、风险发现、加入黑名单、限制请求、释放黑名单五个环节,各环节的交互流程:
业务侧按需配置规则策略;
通过规则策略驱动对请求进行拦截;
若触发拦截,则进行后置处理,如“加入黑名单”(此处可业务侧自行扩展);
若触发拦截,将根据规则对后续相同规则的请求进行拦截,如在指定黑名单时间内拒绝访问;
释放后置处理拦截,以便继续接收其流量;
对于功能集,目前已实现如下功能:
四、技术方案
在设计中,我们整体分为四层:
接入层: 支持HTTP、Dubbo的自动接入,同时支持 API编程式接入;
逻辑层:频控的逻辑实现,包括拦截检查、频控计算、触发处理、拦截释放;
数据层:根据业务方集成方式的差异,支持多种存储介质,用来存储计算的中间数据和拦截成功后的结果数据。集群模式下, 使用的是业务方的 Redis 实例,作为存储介质,减少应用间的干扰, 单机版则直接使用本地内存;
日志层: 通过Cat 记录过程中的结果数据。用以分析被拦截目标,用户行为等;
4.1.2 整体流转图
业务请求时,Moat SDK 通过实现 HTTP 与 Dubbo 的 Filter 拦截了请求,并对请求的资源判断是否需要拦截。先通过配置,判断请求资源是否是 MOAT 管理端已发布的资源,如果不是已发布资源,将进入图上 “3.2”的步骤, Filter 直接退出;若存在已发布资源,将进入"3.1" MOAT SDK 内部的拦截处理链路。通过资源上配置的规则、规则阈值统计计算结果, 若已达到配置的规则, 则会进行后置的拦截操作后, 响应结果,若未达到,则放行,进入后续的业务逻辑处理后响应结果。
管理端主要是负责应用的接入,频控资源的配置与发布等功能,具体的功能说明和步骤如下:
接入频控的应用,首先需要在MOAT 后台完成应用入驻,并分配可以对应用配置频控资源的相关人员的权限。APPID 和接入方的业务应用中的保持一致即可。
1、客户端整体交互流程
客户端的交互大致可以分为三个阶段: 启动、调用、规则变更,交互的时序图如下。
【应用启动】:接入组件的业务方应用,会在启动时和Moat管理端通信,完成规则的拉取与加载,并初始化到内存, 另后续会每隔 1s 交互一次,以保证客户端的配置的时效性,详见【规则变更】。
【业务调用】:当业务调用时,进入SDK处理流程,根据加载的规则资源,判断是否需要处理。
【规则变更】:当应用管理员在 MOAT 管理端修改并发布规则时,客户端的定时更新模块,会更新最新发布资源到本地,完成资源变更的热更新。
【解析请求】获取请求资源,判断该资源,是否是资源管理端,已发布的需要频控的资源。
【解析模型】根据规则定义的拦截维度,获取对应入参\出参模型上的字段,并拼装成规则实例数据。
【验证请求】通过解析的规则实例数据,校验实例数据,是否已经被拉黑,是否已经达到请求窗口上限。
【请求累计】基于选择的算法(固定窗口、滑动窗口)累计请求数据。
【计算日志】处理过的请求,和被拦截的请求,将记录在CAT。
当应用管理员发布规则后,便会触发规则的更新。完整的规则更新过程如下图所示。
Moat 客户端除了基于 Filter(WebFilter/DubboFilter) 的自动调用外, 还提供了编程式接入的方式,通过 Moat 客户端提供的静态类 Moat,业务方可以构建一个 EntriesDTO 的频控请求模型,通过调用 Moat 的 entry 相关方法,即可完成对本次请求的统计及异常拦截处理。若触发异常拦截,则会抛出异常,业务可以通过捕获被频控时的异常,来进行业务后置处理。也可以通过获取执行返回结果中的拦截状态,来判断是否拦截。
try{
// 资源名可使用任意有业务语义的字符串
EntriesDTO entriesDTO = EntriesDTO.builder().resourceName("自定义资源").args(new Object[]{avg}).build();
Moat.entryWithException(entriesDTO);
// 被保护的业务逻辑
// do something...
} catch (MoatBlockException e1) {
// 资源访问阻止
// 进行相应的处理操作,限流或降级
} finally {
// todo yourself code.
}
目前主要是通过公司的监控系统CAT来进行观测,包括处理过的请求,以及被拦截的请求。观测内容中包含触发的拦截类型、拦截的对象、具体的调用链等,业务方能以此来作为分析原因的切入点。
同时,通过CAT数据看盘,可以看出来资源级被拦截的比例,通过这些数据,业务方可以优化资源的频控配置,以便做到有效的频控拦截,保护应用和业务。
五、实践
六、未来规划