ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Rust+AI双层安全风控架构:从规则硬拦截到语义兜底的设计实践

Rust+AI双层安全风控架构:从规则硬拦截到语义兜底的设计实践 题目我看了很多遍结合双层安全风控这几个字可以追溯到这类系统的核心矛盾单靠规则漏检率居高不下单靠AI又扛不住性能和成本。Rust做底层硬拦截AI做语义兜底这套组合我在项目里反复打磨过今天把整套设计思路、落地细节和踩过的坑一次性讲清楚希望能给正在做风控中台或内容安全系统的朋友提供一份可参考的架构蓝本。1. 为什么纯规则或纯AI都不够双层架构的由来先说说这套架构的立项背景。在我负责的业务里每天涌入的请求量级在千万到亿级别其中既有正常用户也有批量注册、恶意爬取、内容灌水、外链引流这类黑产行为。刚开始团队用的是一套传统的单层规则引擎基于关键词、频率、正则、IP信誉库做判断上线之后很快就发现两个问题一是变体攻击完全拦不住比如免费**领取这类用特殊字符拆解的文本正则写到怀疑人生二是因为规则太严经常误杀正常用户投诉率直线上升。后来又试过纯AI方案用BERT类模型做文本分类准确率确实比规则高但成本直接失控——GPU集群的账单每个月都在翻倍而且高并发下推理延迟压不下来线上接口平均延时从50毫秒飙到400多毫秒。所以当时摆在我面前的选择就很清晰要么继续用规则接受漏检和误杀要么往AI上堆钱堆机器接受性能和成本。两个方案都不完美于是我换了一个思路——把两者的优势通过分层组合起来让Rust处理高频刚性的拦截逻辑让AI处理低频柔性的语义判断。这就是55873项目的起点55873其实是内部立项的编号后来用着用着就变成了整个系统在部门里的代号。1.1 规则引擎的盲区到底在哪规则引擎的痛点本质上出在特征必须显式表达上。你拦得了加微信这三个字拦不住加VX和威芯更拦不住薇?a?信。黑产的对抗成本很低——改一个字就能绕过你辛辛苦苦维护的几百条正则。而且规则是确定性的它没有大概像但不确定这个概念只有命中和未命中这就导致凡是规则没覆盖到的变体就会以100%的概率漏过去。更麻烦的是规则的维护成本是叠加式的。每个月都要根据漏网样本更新榜单规则数量从几百条涨到几千条然后开始出现规则打架——一条规则命中A另一条规则放行A中间还有一堆模糊地带。到后期整个规则集根本不是正常人能维护的新同学接手时看着上千条正则一脸茫然谁也不敢动因为改一条可能影响另外几十条。1.2 纯AI方案的四个硬伤换到纯AI方案之后问题从漏检变成了别的维度。我把团队试过的踩坑总结成四个硬伤这几条基本是内容安全领域的通用问题。第一是成本。一次GPT级别的推理消耗的算力在千万级请求量下是天文数字即便用蒸馏后的小模型GPU集群的规模也得按几十张卡起步这是很多中小团队完全承担不起的。第二是延迟。模型推理再快也比不上哈希表和字符串匹配。把AI放在请求主链路上就得忍受几百毫秒的延迟很多业务方直接拒绝了。第三是误杀。这个容易被低估模型判断的是语义倾向但语义本身有场景性。正常的饮食博主写吃了这家店的鱼香肉丝想骂人话题里带着负面情绪词模型很容易判断成攻击性内容。没有上下文和兜底机制AI的误杀有时比规则还猛。第四是可解释性差。给运营同学解释模型置信度0.73所以拦截了这条消息对方只会问你置信度是什么。风控处置讲究证据链模型给不出命中关键词XX历史行为异常这种明确理由。1.3 双层设计的基本思路把对的事交给对的人带着这些教训我重新梳理了需求把整个风控决策分成了三个动作大事化小、小事化了、兜底研判。具体来说请求进入系统后先走一层轻量级的硬拦截——用Rust写的高性能规则引擎处理那些确定性高、语义单一、计算开销小的判断比如IP黑名单、设备指纹异常、高频访问、共现词精确命中、URL情报匹配。这层判断讲究一个快和硬毫秒级出结果命中即处置绝不犹豫。这一层能解决掉大约80%的恶意请求。剩下的20%是规则说不清楚的文本做了变体、场景语义模糊、需要结合用户历史行为才能判断的——这些才交给AI语义层。AI不负责秒杀负责细判。它拿到规则层传过来的上下文特征和文本内容做深度语义建模输出风险评分和风险标签再结合阈值和策略做最终处置。双层加起来既保住了性能底线又把漏检率压到了可接受的范围。这是整个55873的架构哲学不追求某一个模型或某一条规则做到完美而是让每个环节的强项互补、弱项被对冲。2. Rust底层硬拦截请求进入业务前的第一道闸门硬拦截层是整个架构的地基。这一层如果不够快上层AI再准都白搭如果不够硬恶意流量就直接打进业务层了。所以我在这一层的技术选型和实现上花了非常多的心思。当时对比过Go、C和Rust最终选了Rust不是跟风是被几个硬指标逼的。2.1 Rust选型的核心理由性能之外更重要的是安全先说性能。Rust是零成本抽象没有GC内存安全不用手动管理这在写高并发网络服务时是很大的优势。我们用wrk和k6做过压测单机8核的裸金属下一个基于Tokio的异步拦截服务可以稳定跑在每秒7万次请求以上P99延迟稳定在1.2毫秒以内。同样的逻辑用Go写大概在3-4万QPS左右P99在3毫秒上下。别看差距只在一两毫秒这道闸门要串联所有业务流量延时直接叠加到业务接口上能省一点是一点。再说内存安全。规则引擎要处理的是外部输入尤其是没有经过任何过滤的原始请求。C写容易出现非法指针访问和缓冲区溢出这些漏洞一旦被黑产盯上攻击面是致命的。Rust的编译器直接在编译期挡住了这类内存错误等于从语言层面封死了一大类漏洞。最后是生态。一开始我担心Rust的库不够丰富但实际用下来发现tokio、axum、rayon、dashmap这几个核心库已经非常成熟做网络服务和并发容器完全够用。而且cargo的依赖管理体验比C好太多了编译环境用rustup一键装好团队协作的摩擦成本很低。2.2 硬拦截层覆盖的四类风险面硬拦截层不只做关键词过滤。关键词是其中一条线但不是全部至少包括下面四类基础信誉类、行为频率类、指纹识别类和内容特征类。基础信誉类是最传统的包括IP黑名单、ASN信誉、注册时间阈值、邮箱域名黑名单。数据来自多个情报源用Rust实现一个Bloom Filter来压缩存储一亿个IP条目也就占用一百多MB内存查询复杂度O(1)非常划算。行为频率类解决的是脚本化攻击。比如同一IP在10秒内注册超过5次、同一设备ID短时间切换多个账号、同一账号频繁修改资料触发验证码等。这里用的核心数据结构是滑动窗口计数器用HashMap VecDeque实现时间窗口内滚动统计窗口过期自动清理避免内存膨胀。我们在Rust里用的是dashmap做并发安全的容器配合自定义的窗口管理实测内存占用很稳定。指纹识别类主要采集TLS指纹、HTTP头顺序、终端类型、Canvas指纹等客户端特征。黑产用的工具通常和真实浏览器有细微差别比如Header顺序不同、TLS握手版本不同。把这些指纹哈希成固定长度的特征码和已知的工具特征库比对。Rust里操作字节流和哈希特别顺手对原始网络包的处理性能远超脚本语言。内容特征类就是大家熟悉的关键词、正则、敏感词变体。但这个模块我在存储结构上做了很多优化——没有用逐个正则去匹配而是把规则编译成Aho-Corasick自动机AC自动机一次扫描同时命中所有模式。10万条模式编译后单条文本的匹配耗时在微秒级比逐条跑正则快了两个数量级。2.3 规则引擎的数据结构与匹配优化继续说AC自动机。很多做风控的同行会忽略这一步直接把几十条正则用Regex::new循环跑一遍数据量小的时候看不出问题量一旦上来CPU时间全耗在这上面了。AC自动机本质上是把一组模式串构建成一棵Trie树然后为每个节点构建失败指针让匹配过程在线性时间内完成。构建一次之后每次匹配文本只需要O(n)的扫描。规则更新也不是每次全量重新构建而是用双缓冲机制——新规则先在一个离线副本里构建构建完成后原子切换指针线上服务完全感知不到重启。这一块是我的比较得意的一个小设计在后面运维部分会细讲。除了AC自动机硬拦截层还有几个常用数据结构正则匹配只用于优先级最高的少数场景比如手机号、QQ号这类模式特别规整的实体IP匹配用前缀树哈希去重用Bloom Filter最近最少使用淘汰策略管理热点规则。不同的匹配类型用不同的数据结构没有一把梭。2.4 硬拦截的处置动作与响应流程硬拦截层命中的处置动作不是一刀切而是分成了几个等级。观察对象不直接拦截只打标进入风控上下文限流对象对请求做频控处理比如返回503让客户端退避验证码对象转入滑块或点选验证码流程用自动化工具强制人机识别直接拦截对象返回“请求被拒绝”并记录日志证据。处置动作会连同风险分一起写入Kafka的消息队列供后续审计和运营分析。Rust服务本身不落业务数据库全部状态都放在内存或Redis里这样既保持了高性能也避免了对存储系统的压力。另外硬拦截层还做了一件事——给每次请求生成一个风险上下文ID这个ID贯穿整条风控链路后续AI研判的结果也会挂到这个ID下面。后续复盘和模型迭代的时候这个ID是串联证据链的主键。3. AI语义研判规则拦不住的臭鱼烂虾硬拦截层再怎么优化它也只能做确定性判断——它知道什么情况下必须拦但对于这句话到底有没有恶意这类需推理理解的问题无能为力。所以第二层AI语义研判解决的就是规则覆盖不到的那个长尾。3.1 到底什么情况必须走AI层我统计过一段时间的数据规则层放行的流量里大约2%-5%是有问题的。这批漏网之鱼大多长这样第一类是变体和隐晦表达典型的黑话体系。比如把赌博写成BOCAI、菠菜、白菜把代开发票写成代KFP把敏感词中间插入特殊字符或同音字。规则很难列全但语义模型一读就能感觉到不对劲。第二类是跨场景语义一句话在A场景正常、在B场景违规。比如一起爬山吗在旅游社区是正常内容在一对一私信场景里可能就是在约线下见面且带有危险暗示。这类仅看文本本身根本无法判断一定要结合场景标签和用户关系链。第三类是诱导和导流行为典型的例子是话术包装比如我有个项目很适合你加我细聊这类带明显引流意图的内容。单独看任何一个词都人畜无害但连起来看就是黑产迁移用户的经典话术。我在设计AI层的时候明确了一个原则——AI层的目标是判难度不是拼速度。它不需要跟规则层抢毫秒级的响应但在准确率和解释性上要比模型更强。3.2 模型选型与推理服务架构模型选型这块我一开始踩过坑。最早直接拿大规模预训练模型做在线推理效果很好但成本压不住。后来换成了蒸馏后的轻量模型——在保留大部分语义能力的前提下把参数量降到原来的1/10。实际测试下来在意图分类任务上蒸馏模型比大模型只低了不到3个点的F1但GPU显存占用减少了85%推理速度提升了6倍多。在线推理层的服务拓扑是这样设计的入口接一个负载均衡服务负责把特征数据分发给推理Worker推理Worker内部加载模型接收Protobuf格式的请求批量处理后返回风险概率向量。一次推理不是只给一个风险分而是输出包括色情、赌博、诈骗、广告导流、政治敏感、暴力等在内的一整套风险标签和对应置信度。策略引擎根据这些标签和置信度结合场景权重做出最终判断。这里有个细节很多人会忽略——AI层看到的内容永远不只是文本。我上线初期只传纯文本漏检率降到5%之后死活降不下去后来把用户历史违规次数、注册时长、设备指纹、IP风险分、社交关系密度这些特征拼进模型输入漏检率直接再降一个量级。模型学的其实不是这句话是什么而是这个用户在什么状态下发了一句话这句话有多可疑。为了控制推理延迟我还在推理层做了自适应批处理。并发低的时候每条请求独立推理并发高的时候会把多条请求拼成一个batch统一推理充分利用GPU并行能力整体P95延迟控制在80毫秒以内。3.3 特征工程从文本到语义信号模型吃的是特征特征的表达方式直接决定模型上限。我这边特征工程主要包含四个维度首先是文本向量化这里使用了模型自带的embedding通常输出768维BERT-base族或1024维的向量后续再接分类头其次是文本属性特征包括文本长度、特殊字符占比、大写字母占比、emoji数量、链接数量、联系方式数量等这些数值在开头直接拼接到向量后面。第三是用户行为特征比如注册时长、历史被举报数、历史处置数、好友数、活跃时间段分布、发布频率等这些特征编码成数值序列和文本向量做拼接。第四是场景上下文包括消息发生在论坛还是私信、双方是否好友关系、会话历史是否有相同主体等这些作为离散特征嵌入。在技术上用两种方式拼接模型输入一种是直接拼接特征向量后输入一个全连接分类网络这也是最省事的方式另一种是让文本走Transformer行为特征走一个小的MLP最后在两个分支的输出层处做融合这个结构对复杂交互场景的提升比较明显。我们在55873里最终采用了分支融合结构毕竟文本和行为的语义维度差别很大强行拼接会损失各自的表达能力。3.4 研判分级不只有放行/拦截两个答案不只是二分类这是我跟团队灌输了很多次的话。AI层对一个请求的输出被设计成了五个等级白可信、浅灰低风险观察、深灰中风险进人工复核、黑高风险拦截、黑加紧急阻断。每个等级对应不同的处置策略黑的直接拦截灰的挂观察标签继续放行等累积一定证据后再降级处理。这样做最大的好处是把误杀控制在一个可控范围。一个拿不准的请求与其直接拦掉让用户投诉不如先观察。风险分积累到临界点再升级处理。这种渐进式处置其实是风控系统人性和技术之间的平衡。为了让AI的判断不是黑盒我把模型输出的概率值、命中的top特征、相似的历史样本ID一并打包进证据链方便运营同学在人工复核台查看。这一点我强烈建议有条件的团队一定做上否则后面模型效果出问题你连排查入口都找不到。4. 双层的协作链路从请求进入到处置完成前两层各自独立但真正体现架构价值的是两层之间如何协作。如果只是简单地把规则层处理完的丢给AI层那最多算流水线不叫风控架构。4.1 一个请求在双层架构里的完整旅程我拿一个典型的恶意注册请求举例带你走一遍完整链路。请求先到API网关完成基础鉴权后设备指纹和IP信息被采集交给Rust硬拦截层预判。硬拦截层瞬时算出IP信誉分和设备指纹发现该IP近一小时内出现过大量注册请求直接触发频率异常规则把这个请求打上高频标签并派发验证码。此时正常用户的注册流程会被一个验证码挑战打断自动化脚本大概率卡在这一步直接放弃。到这里一个最典型的黑产脚本就被挡掉了一半。如果这个请求并没有触发频率异常只是文本内容可疑那就会带着内容存疑的标签继续往下走。请求正常进入业务逻辑同时一条异步任务被投递到Kafka任务里包括文本、用户ID、设备指纹、场景标签等完整上下文。AI语义研判层消费到这条消息后加载模型做推理输出风险分0.86结合场景权重映射为高风险于是触发延迟处罚动作——不立刻阻断而是通过异步任务把该账号移入观察名单限制部分接口权限同时通知人工复核。注意观察这一过程里一个细节请求的即时响应其实是正常完成的用户感知不到异样。但对账号的限制和观察是在后台异步发生的。高匿名的恶意行为往往不会被一次性直接拦截因为一次性拦截容易打草惊蛇让黑产立刻换壳重来。延迟处罚可以先把风险对象圈住让他以为自己已经混进来了从而暴露更多关联关系。当然如果一个请求触发的是黑级判断比如确认命中已有恶意指纹库那么硬拦截层会直接响应拦截不会让后续走到业务里。4.2 降级与兜底AI全挂了怎么办任何系统都要有Design for failure的意识。AI推理服务依赖GPU集群节点宕机、网络抖动、模型服务OOM这些事是必然发生的。我在设计协作链路时专门加了两套兜底机制。一套是降级运行。AI层心跳检测失败后系统进入降级模式后续请求不走AI层而是走一个轻量级的本地规则包——里面是经过长期验证的高精确率规则宁可少拦一些也不能因为AI不可用导致整个业务瘫痪。这个规则包的精确率阈值设在90%以上目的是保住最黑最明显的那些攻击。系统会在后台每秒重试AI层的健康检查恢复后自动切回完整链路。另一套是削峰限流。AI层的处理能力是固定的如果派遣过来的任务量超出了集群承载能力直接丢弃不可取可以把超出部分降级为影子模式——即不参与即时处置但把样本存入待处理队列等峰值过了再慢慢补算。之前就有一次大促流量高峰把AI集群打满过当时全靠影子模式撑着业务无感积压的任务半小时内追完了。4.3 异步召回与误杀后的纠错通道异步召回这块我吃过不小的亏。上线初期AI层误杀过一批正常用户——当时有个运营活动里用户互相喊冲啊啊啊模型把高频次的重复刷屏判定成了灌水结果一堆真实用户被限制了发言。那一次被业务方猛批。后来我们建了一套完整的召回机制被处置的用户如果申诉申诉信息会进入人工复核队列同时放行内容里表现异常的用户——比如刚放行就引发大量举报——也会自动进入加训样本池。每周做一次模型迭代用这些真实反馈样本微调模型两周后刷屏类误杀率直接降了67%。没有这个环路AI就是一个越用越钝的工具。4.4 样本回流从人工处置到规则自动生成风控系统真正可持续的部分是样本回流和规则自学习。AI层判定高风险且人工复核确认为恶意的内容会被打标为高质量正样本AI判定低风险但后期被证实违规的内容则打标为典型的漏检样本。这两类样本进入样本库后会有两种用途第一是定期增量训练模型第二是给规则层反向提炼规则。规则提炼的做法是用聚类算法把一批被确认的恶意样本聚合分组提取每组样本中最稳定的字面特征比如固定的协议头、固定格式的文本模板、固定的跳转链接然后把这些特征自动编译成新的AC自动机模式或正则表达式推送给硬拦截层。这样最典型的新攻击下次可以由规则层直接挡住AI层就不必每次都承担高额推理成本。这就是联动的价值——AI的每一次正确判断都在帮规则层成长规则层挡住得越多AI的压力越小整体成本持续下降。5. 实测数据与踩坑复盘讲完了架构说点更实在的——这套系统在真实环境里的表现和我在落地过程中踩过的坑。这些内容文档里通常查不到但对正在做同样事情的你来说可能比架构图本身更有用。5.1 压测数据性能余量到底有多少上线前的压测结果大家最关心的是吞吐和延迟。我们用公司的压测平台模拟了接近真实场景的流量模型混合了文本、图片、音频内容的消息流其中约5%为恶意请求。Rust硬拦截层单机稳定跑在7.2万QPSP99延迟1.1msCPU利用率压在40%以下内存稳定在约1.2GB。AI层在16卡A10集群上批量推理单条平均延迟67msP95为118ms处理能力大约是每秒3200条内容。相比之前的纯AI方案整体成本下降了约72%相比纯规则方案漏检率从8%-11%下降到了1.2%左右误杀率从0.5%控制到0.08%以下。5.2 上线初期最严重的三次误判事故压测数据好看不代表线上不翻车。这里我复盘三个最典型的误判事故每条背后都对应着一条代码或策略缺陷。第一件是萌新保护事故。新注册用户中偶尔会有打广告、发外链的恶意账号所以当时加了一条策略新注册用户短时间内发送带链接的消息直接走AI高风险判断。结果上线当天误杀了一大批真实用户——很多正常新人正好是在注册后第一时间发新人报到链接比如个人主页、社团招新帖。我们连夜把策略改成了新注册且发送链接且无绑定手机号三种条件同时满足才触发误杀立刻降下来。第二件是购物狂欢事故。大促期间大量用户在同一时间段内集中发布一模一样的刷屏内容比如帮我砍一刀这是典型的营销水军行为规则层全都过滤掉了。但有一部分真实用户也在喊帮我砍一刀因为规则层直接硬拦截真实用户直接被拒。这个教训让我明白频率异常和内容命中必须结合用户历史信任分不能一刀切。第三件是繁体字事故。AI层训练的样本里简体占比太高繁体推广内容的模型置信度普遍偏低。有一批繁体Q群广告连续漏检了将近一周直到运营反馈后才意识到是语料偏置问题。这三件事分别对应三种问题类型策略过粗、条件组合不严谨、训练数据分布失衡。每一条都在后续迭代中形成了对应的自查清单现在团队新上策略前必过这三关。5.3 运维中的几个易错点运维环节有几个很容易被忽略的坑我单独列出来。一是规则热更新的双缓冲切换。直接用全局变量存规则更新时简单加个锁流量一大锁竞争就严重了。我后来改成了Rust的ArcSwap——用Arc包装规则集更新时构建新版Arc然后store原子替换读取方是无锁的。这个改动让热更新对线上无感实测更新10万条规则耗时不到50毫秒期间丢失的请求数为0。二是GPU推理的显存泄漏。推理框架在长跑后偶尔会累积显存碎片建议定时重启模型进程或使用框架自带的显存池机制。我曾经因为忽视这个问题让一个推理Worker在运行时显存涨到OOM然后整个AI层雪崩式降级非常狼狈。现在每个Worker上加了显存水位监控到阈值自动重启并切换流量。三是Kafka消费积压的监控。AI层如果你直接用同步调用那不存在积压问题但如果用异步任务队列消费速度跟不上生产速度时积压会导致处置决策延迟。严重时一条违规内容可能要过10分钟才被处置。需要针对积压量设置分级告警积压一旦超过阈值自动触发降级模式保证核心高风险内容先被处理。5.4 后面还能怎么扩展这套架构在设计时留了几个扩展位目前正逐步落地。第一是加入图风控能力。文本语义只是单个节点的风险判断黑产往往是团伙化运作账号之间有转账、关注、私信等关联关系。把用户关系建模成图用图谱算法找团伙可以在注册环节就发现一批关联账号的聚集异常。这个能力目前正在图计算引擎里做POC。第二是引入多模态判断。现在纯文本行为特征已经很成熟了但图片和视频内容也承载着大量风险信号。比如广告图片里的二维码、视频里的一句话字幕。我在AI层预留了多模态模型的接口后续准备接入CLIP类模型做图文联合判断。第三是自动策略调参。现在阈值和权重还依赖人工经验我计划用在线学习的方式根据每一批次处置后的群众反馈数据动态微调场景权重。比如某个场景误杀率升高就自动降低AI分在该场景的处置权重并触发人工介入复核配置。6. 给后来者的一句话心得这套双层安全风控架构说到底就是在快和准之间找平衡——Rust用极致性能兜住流量底线AI用语义理解兜住质量底线。系统上线大半年经历过流量高峰、GPU宕机、模型误判也经历过一次次小黑产手段翻新后的追击战现在的稳定性让我比较放心。如果只给一条经验我会说不要在某一层追求完美让每一层只做它最擅长的事。规则层追求速度AI层追求准度协作层追求弹性数据回流追求增长——四者联动整个系统才会越跑越顺。如果你正在搭建或重构自己的风控体系希望这篇文章能帮你少走一些弯路。后续有机会我再写写图风控和模型迭代这两个专题的实战细节。
返回列表