koala通用频率控制系统,一个应对所有频次控制高度配置化的通用反作弊系统,高性能可扩展

Koala - 通用频率控制规则引擎系统介绍

作者:黑夜路人(heiyeluren)

欢迎各位喜欢Koala的技术伙伴给本软件点一个“Star”,也希望能够共同交流!


Koala 是什么?

Koala系统,也叫“用户行为频率控制系统”。它是用GO语言开发的高性能后端独立服务,独立的规则引擎+计数器,采用redis缓存用户行为数据。初衷是支撑线上业务的多种用户行为频率控制需求,属于反作弊功能的一个组成部分。同时,它将控制策略完全配置化,koala系统本身不和业务策略直接耦合,提供http接口供业务方访问,故通用性较强,也适用于各类UGC产品的同类需求,并且性能高超。

什么时候你需要Koala?

image

Koala技术特性:

  • 独立运行的高性能后端服务
  • 纯Go语言实现、对外提供HTTP接口。
  • 关注频率控制,但不耦合任何业务
  • 高度灵活的策略配置
  • 策略配置自动更新
  • 高效率日志缓冲处理



Koala应用场景

  • 基本模式

既然用redis缓存用户行为数据,就意味着,每次操作,都涉及对redis中缓存数据的,读和写。因此,koala目前提供的主要服务接口,就是browse和update。

每次用户操作,首先要调用browse接口,来确认“是否允许用户的这一次操作”。

如果被“允许操作”,操作完成后,再调用update接口,将缓存计数值+n。

  • 应用场景

koala最初是为了满足互联网产品以“提交”为主的频率控制。而实际上,koala既不是为“提交(写)”操作设计的,也不和业务融合。

基本的“提交”场景,如:一次用户“提问”操作,首先,将特征数据提供给koala,查询koala系统以确认此次“提问”的否允许执行;通过后,才进行提交内容的入库落地,成功以后,将此次行为记录。“提问”过程最终完成。

  • 更多的应用场景

比如:A产品,需要知道某个用户在某个特定的页面,是否做了某个选择(给某个帖子投票等,如果选择了,希望按钮“置灰”),cookie等方式自然就不可行了。如果使用koala,需要配置一项规则:

“每个user_id对每个帖子,X时段内,只能点1次W操作”。

再比如:

“u用户,X时段内,Y广告弹窗,不超过1次”

“两次Y广告弹窗,至少间隔2小时”

“u用户,X时段内,积分增长,不超过300分”

“某IP,X时段内,发帖超过10次,需要出验证码”

……

Koala如何为业务服务:

通常在论坛等“用户提交类产品”中,面对各种垃圾灌水的威胁,PM会提出诸如“每个用户每天只能回帖100次”、“两次回帖至少间隔10秒”等等的反作弊需求,而最直接的做法,就是在服务端逻辑里写上“if(submit > 100) return false;”。

产品经理永远不会满足于当前的功能,当需求越来越多,逻辑也就越来越复杂。

当然大部分人都会想到封装,将此类功能封装到一个模块中,可维护性更高了。但是,如果没有一个比较抽象的配置文件,控制策略就会散落在代码中而不易管理;而且分布在web后端众多机器中,仅依靠同步代码来同步策略。

koala系统的引入,将这些策略统一收集到一个独立的后端服务中。所有web服务器通过访问koala服务器来完成控制功能。

并且koala系统实现了比较通用、又比较灵活的“策略配置化”能力。需要的变更,只需要对配置文件进行修改。

koala系统同时也以“高性能”为目标之一。采用GO语言实现,一方面可以有接近“脚本语言”的开发效率,另一方面有可以有接近C语言级别的性能指标。GO语言本身也是以“高并发”、“高性能”为设计目标。

并且常驻内存的demon进程,也使我们拥有了在进程地址空间内对关键数据进行缓存的能力,对性能将是有力的支撑。

有了高性能的支撑,koala不仅仅应用在“提交”操作(写操作)。比如请求量较大的“浏览”操作(读操作),也可以应用,以应对各种恶意抓取行为。

Koala 控制策略配置使用:

我们通过一条策略,作为示例,不关注的可以忽略。

#提问,同IP,超过30次后,每次提问间隔2秒

rule : [base] [act=add_ask;ip=+;] [base=30; time=2; count=1;] [result=2; return=224]

为了高度灵活的配置频率策略,我们制定了如上所示的格式。

用[ ]分割的几个段,分别是“方法”、“参数”、“阀值”、“返回值”4个区域。

  • 方法:代表策略的类型,采用一种什么控制模式,如上面的例子,就是一种有“基数”的策略,提交超过“基数”之后才会生效。
  • 参数:是满足此策略的必要条件,一般是,某个参数满足某个范围,或者等于某些特定值。这些参数通过http get参数提供给koala系统。
  • 阀值:定义的特定方法模式下,需要的条件值,time,和count是基本的值,代表缓存有效期,计数上限,而base则是值。
  • 返回值:代表此策略名中之后,应该采取的行为,比如“阻止提交”、“出验证码”。

通过这种多维度、较灵活的配置格式,提供的较大的配置能力。保证一段时期内,新的需求完全通过修改配置来实现。

同时,我们又实现了“配置的动态更新”。因为配置被读取到内存中长期保存,我们通过检测相关文件的MD5值变化,读取并解析到内存中,采用0/1覆盖的方法,替换内存中现有的配置数据。所以,不需要加入锁操作。 通过这些设计,我们在享受更高性能的同时,也可以像php开发一样,直接替换文件,就可以让策略生效。

更多使用参考文档: https://github.com/heiyeluren/koala/tree/main/doc




Koala 工作机制:

  • 使用调用流程 image

  • Koala并发模型:

    • 单进程,多线程,多协程。
  • Koala 核心模块:

    • http-front: 路由
    • Logger: 日志库,日志缓冲
    • Redigo: go版redis库,连接池支持
    • 其他:守护进程机制、便利调试
  • 性能数据:

    • 单机稳定 1w+ QPS/秒
    • 2核CPU、线上95% cpu idle,500M内存占用
  • 高性能原因

    • Go本身固有的高性能
    • I/O 最小化
    • Redis访问最小化
    • 更多内存数据
Koala内外部框架

koala系统采用的GO语言http服务的模式,很容易用于以后的GO开发项目中。姑且将这些称为一个“GO框架”。

  • http框架

采用了一个开发并长期使用的一个http模块,清晰、实用。 此http模块,实现了“http包解析”、“http包封装”、“路由”等等必要的功能。提供了http接口的快速开发能力。

本次koala基本沿用了此模块,只是补充了“获取client IP”的api。

  • log模块

日志模块,是本项目中,新开发的模块。 主要实现了“日志分级”、“日志切割”、“日志合并写入”等功能。 有丰富的日志配置项。可以分别配置每个日志级别的“目标文件”、日志切割周期、日志输出开关等

应用GO语言的channal,我们实现了对日志的“缓存”、“合并写”;有多种策略控制日志写入文件的时机。

  • redis库

引入了一个比较完善的redis客户端的GO语言实现,提供了redis的大部分特性,同时还实现了redis连接池,对服务本身的性能有很大的帮助。

koala 内部结构:

koala服务,是单进程,多线程,多协程(goroutine)结构模式。

图1 image

其总体结构如图1所示。

图中,http front、worker、logger、rule loader分别都是一个GO协程,GO语言内部实现了轻量级的协程goroutine,每个goroutine有独立的运行栈,被进程的“运行时包”调度执行,依附于OS线程运行。

  • httpFront负责监听并接受连接,解析http参数,并定位到特定的接口函数执行,每个请求,都起一个独立的协程,代表一个worker。

  • logger除了提供log相关API之外,更主要的是包含了一个log缓冲的协程。

  • RuleLoader是提供控制策略自动加载的独立协程。

Koala 核心算法实现机制:

核心统计算法工作机制参考: https://github.com/heiyeluren/koala/blob/main/doc/README.md




Koala 总结与展望

Koala 的开发,很大一部分工作是实现对策略配置的解析,以及配置的自动load功能。而服务接口逻辑相对简单,因为很多事情,交给配置来定义了。配置语法中包含了“关键词”、“操作符”,俨然就是一个微型语言。但语法分析器之类的高级货就有点杀鸡用牛刀的意思了。简单考虑,仅用基本的条件判断if-else来实现,显得比较笨拙。

目前koala已经完成了web业务的迁移,正在为提供用户行为相关的控制。面对目前每天大约2000万+次的请求调用,koala基本可以轻松应对。

从易用性的角度看,koala尚有一些不足,比如,缺少一个图形化的策略更新平台,这方面,可以补充开发一个管理后台页面,实现策略的“查看”、“上传”、“正确性验证”。

从通用性的角度来说,koala目前已经可以支持线上多个产品的同时应用,表现性能稳定性也非常不错,当然还有很多需要更进一步的优化改进。

百尺竿头,更进一步。



Koala 使用 & 技术交流

欢迎各位喜欢Koala的技术伙伴给本软件点一个“Star”,也希望能够共同交流!


想直接运行体验Koala服务请参考文档:

https://github.com/heiyeluren/koala/tree/main/output

更多使用说明参考文档:

https://github.com/heiyeluren/koala/tree/main/doc


加入微信群交流

image


群失效可添加作者微信加群

image

Last update: 2021/5/19

Similar Resources
Comments
  • Can koala support a web framework middleware?

    Can koala support a web framework middleware?

    Hi, 首先谢谢作者的开源,这个规则引擎非常棒,下面是我对于这个引擎在投产上的一些小疑问🤔️ image

    1. 对于部署方面作者准备后面做什么规划?我理解单实例部署没发保证很好的高可用,无法直接用于生产
    2. 有没有考虑下作为web框架的前置中间件去控制频率,像gin中的middleware
    3. 是否可以直接放在离业务最近的网关上,比如直接做成nginx的一个模块,提供多网关实例间全局的频率控制
  • browse及update,是两个操作,多线程下会不对

    browse及update,是两个操作,多线程下会不对

    每次用户操作,首先要调用browse接口,来确认“是否允许用户的这一次操作”。

    如果被“允许操作”,操作完成后,再调用update接口,将缓存计数值+n。

    如果用户同时调用browse,那么全部是通过的,即使打开_writeThrough,由于是异步去更新,所以即使k.base > value返回null,对于browse也没有影响。