其他
百度搜索中台新一代内容架构:FaaS化和智能化实战
The following article is from 百度Geek说 Author 搜索中台团队
导读:百度搜索中台内容计算架构为在线提供了数十亿的异构且有丰富特征和信号的优质原材料。我们以 Serverless 理念为指引,通过FaaS化和智能化的系统性建设,构建了新一代内容数据计算系统,实现了业务研发效率、资源成本和架构稳定性维护性的显著提升。本文从搜索中台内容架构演进过程中遇到的问题入手, 分析系统设计思路,然后详细介绍具体实践方案。
全文10719字,预计阅读时间7分钟
学习成本大: 业务框架做了抽象,业务要上手开发需要学习完整的接入规范、开发规范,有的场景可能只要较少的业务代码开发,但是学习时间却要一周甚至更久,在新场景接入、尤其是简单业务场景,越来越多的情况下,学习成本变成了个棘手问题 资源成本高: 很多的业务场景有潮汐式特征,即每天只有一小段时间有内容计算,假设它只有1小时有,那么之前的架构浪费了23/24的资源,即另外23小时没有任何计算确占着资源,导致巨大的资源浪费 维护成本高: 搜索自身的复杂性,导致出现问题的时候开发者排查异常困难,有时候强依赖某些有经验的同学,整个系统的维护成本越来越高
二、思路与目标
一方面,虽然业务开发的功能需求千差万别,本质上仍然有很多通用共性的地方。对于业务特定化的处理逻辑都可以将逻辑转化成一个一个的函数。而共性的功能可以通过抽象成通用组件。通过函数的编排和组件的复用可以乐高式搭建出适合业务的搜索数据计算系统。同时业务完全聚焦于业务自身逻辑中去,高可用、高并发、高扩展这些用户都不需要关注, 极大的简化的业务接入成本。 另一方面,由于业务流量的波峰波谷异常明显,通过深入业务层的智能化调度的实现,不仅可以提升业务在流量峰值的扩展能力,而且通过调度可以实现资源的充分利用,节约大量的资源成本。同时,针对越来越复杂的的系统,必然导致问题的排查恢复的成本也越来越高,通过智能化控制系统的引入,实时发现分析处理异常问题,使得整个系统更稳定更有韧性。
通过FaaS化建设,业务从聚焦于服务研发转变为聚焦于函数开发,全面的提升业务的开发效率。这里的FaaS化改造不仅仅说的是技术底座的变革,更是全系统全流程整体的业务效率的提升。 通过智能化建设,让架构系统根据服务的容量和状态进行动态调整,使得可以在追求更低资源成本的同时提供更高质量服务。智能化建设即包括从0到n极致化的智能伸缩调度,还包括根据系统的多维度实时状态信息进行智能分析自愈的智能控制系统。
三、FaaS化改造: 追求业务明显感知的卓越效能
如上图所示业务在过去的普通云化服务中需要关注内容较多:从应用程序本身、组件和数据,以及服务的运行时环境,到最后的服务容器等基础设施的管理都需要业务方去关注。 当业务转变到FaaS化的思维中,业务需要开发处理的只是业务的一段逻辑表达,这里是以Function的方式表示, 其他部分(包括组件、数据、运行时环境和基础设施等一系列因素,业务甚至连原本应用程序本身)都不需要管理。
3.1 核心框架: 业务抽象与能力复用
极致抽象的业务框架:是核心框架基础中的基础,提供新的开发范式同时,为后续智能调度奠定良好基础 高度复用的基础服务:强大丰富的后端服务能力封装,支持业务低成本复用,降低开发成本同时提升稳定性。同时系统还提供强大的编排能力,低成本支持业务从简单到复杂的发展
极致抽象的业务框架
阶段1:基础框架引擎使用C++实现(原来业务框架阶段基于脚本语言实现),架构代码与业务代码的充分解耦,直接调用业务函数代码,业务开发效率已经有了质的飞跃。 阶段2:为了规避脚本语言在进程中只能使用单核(如Python、Php、JS等)特点,让业务函数具备容器内使用多核的能力,为后续支持极速扩容奠定基础。
流式计算框架: 我这边是直接基于百度StreamCompute流式计算框架开发,该框架原生支持基础流式计算数据流语义、支持拓扑函数的编排描述,为整个FaaS提供坚实的基础底座。大家实际使用过程中可以选取合适的流式计算框架开发。 数据预处理: 这里包含的功能比较多,从大体上协议解析、性能优化和数据观测等三个方面的工作 协议解析: 这里主要说明的框架的基础通信协议的定义解析,为了各业务数据通用性定义为 入参 和 出参均为原始字符串; 性能优化: 接入数据流框架本身,通过批量顺序读写、数据压缩的方式提高数据穿入过程中的服务吞吐; 数据观测: 进行基础指标汇报包括QPS、延时、内部队列等一系列信息,和异步的Trace信息(进入到Kafka中)。 进程管理&服务管理: 并不在数据的主通道上,主要是应对整个容器内部进程和服务的管理。 进程管理: 伴生服务,负责启动、维护、销毁整个子进程的生命周期。 服务管理: 伴生服务,负责初始化并且维护远端的rpc 的client,修改访问参数,如超时、重试、下游访问策略等。负责新进程的创建、回收,以及进程间交互信息的维护。 进程通信异步数据分发: 这里有三个关键点: 数据不丢 、异常健全 和支持下游竞争消费。调研了包括数据管道通信、共享内存、系统队列和RPC等操作方式,考虑到稳定性、扩展性和实现成本等因素选择基于Baidu-RPC框架实现进程异步数据分发; 单进程模式: 当进程个数为1的时候则跳过进程通信,直接在本进程内部进行方法调用; 多进程模式:每个进程完全独立启动,业务视角隔离,但是公用一套业务代码环境。子进程处理完成后将请求结果反馈给父进程。 业务逻辑处理: 主要包括校验解析&函数调用&本地优化加速几部分,如上图左边就是业务逻辑处理的展开图。 解析&校验&优化: 每个线程内会进行参数解析协议校验,为了方便老业务迁移,支持多用户协议解析,线程并发优化; 执行引擎: 函数接口是真正函数调用地方,支持不同语言的调用引擎。eg: 如果业务使用Python,使用pybind。 数据提交: 执行完成后会统一推送到本地输出队列,本地队列里面的信息会异步提交到远端的消息队列里面给后续算子消费。
高度复用的基础服务
架构通用能力:包括索引算分(倒排、正排、向量索引),数据审核(政治敏感数据/色情数据识别&过滤),多路分发、数据建库等能力; 与业务联合研发的能力:数据的低质过滤能力(实现数据清洗/归一化/数据去重/类目拼接),数据多元融合,数据质量打分计算(质量打分/作弊识别/物料打分) 基于公司强大基础能力: 多媒体处理服务(外链转内链/OCR/水印计算/重复图计算/主体识别/视频转储等),自然语言处理服务,数据沉淀服务
3.2 全流程效能提升: 提供极简的用户使用体验
快速接入:权限申请到数据接入的全面简化。简化的建设主要是两方面思路:其一是流程上的简化(例如: 权限申请流程无需架构同学参与,组内同学就可以审批处理);其二开发过程的简化,对于常见的流式数据系统(公司其他中台或者官方数据系统) & 通用存储(常用的公司数据存储 eg Mysql、Mongo、公司内部的表格存储甚至原生FTP本地文件) 支持配置化的批量导入。同时我们也提自定义(完美适配Docker)的任务系统提供做够的灵活性保证业务的低成本接入; 极速开发:平台完善函数内容。我们这边开发有两种模式,一种适合初学者的Air模式,一种是适合高端玩家的Pro模式;针对于Air模式本身,用户可以直接在平台完成代码的提交和调试功能,完全一键处理; 快速调试&测试:业务可以根据自己实际的需要可以通过平台化的方式调试通用的模板函数, 也可以通过线下集成调试环境一体化的对整个系统进行调试。针对于测试提供了平台化的测试方案,业务可以默认0配置的情况下进行服务性能和执行数据结果的DIFF; 问题定位: 这部分对于业务问题解决尤为重要。主要包括监控报警和云日志两部分功能(具体架构设计在2.1可观测性建设 中有详细的描述): 监控报警:包含两部分信息通用部分和业务自定义两部分。其中通用部分提供 包括算子总体堆积程度,每个算子的处理的信息,app 实例状态 等等20多项常用数据指标,直接集成到管理平台内部,可以不需配置直接使用。而自定义部分提供了基础的SDK函数装饰器,可以极低成本给监控自定义代码段的成功率,延时等信息; 云日志:包含数据Trace(数据流向)、日志Trace以及相关的数据报表服务,业务都可以极低成本进行服务接入。
四、智能化:追求更低成本、更高质量的服务
通过智能化的资源调度方案,极大的节约用户的资源成本,真正做到按需使用,而且可以有效处理流量洪峰,提高系统稳定性。 通过智能化的控制架构,有效处理异常问题,做到问题主动感知、决策并且主动处理,提升系统韧性的同时降低大量的维护人力成本。
4.1 智能调度: 极致化弹性伸缩
自动伸缩:根据当前服务流量的波动情况自动分配出来对应可以满足整体实例消费情况的实例数进行消费,包含纵向本地扩容+容器横向伸缩的方式相结合多阶段扩容; 服务资源回收&冷启动:保证长时间没流量的服务容器,资源完全被回收,不占用任何服务资源,当新流量资源到来的时候,服务接着过去资源的数据消费,保证数据生效稳定性的同时,使得业务完全做到按需使用; 异常实例迁移:主要通过热点实例迁移,长尾实例迁移保证服务全局的正常运行; 容器资源自适应:主要通过检测内存使用状态,对资源容器进行自适应的调整,保证容器资源在不浪费的同时,保证服务不会超限而造成服务的OOM。
设计思路:多阶段扩容的设计原因
启动时间分析: 容器的调度时间+rumtime初始化时间占据了整个启动时间的98%以上,一般需要5分钟,依赖于公司基础PaaS环境,优化成本非常高; 开发业务:业务都是通过脚本语言开发(通常是Python),受到解释器限制极限只能用满CPU单核, 有时甚至由于业务代码逻辑问题远远无法达到; 资源占用:容器规格很小(CPU规格极小、容器内存资源充足),多数机器上的剩余quota足够。
纵向本地扩容阶段:可以满足在高时效业务场景下突发流量到来的极速资源满足速度,通常可以瞬间满足5~10倍的资源。此外,扩容过程中是允许少数实例纵向扩容失败的,通过流量均匀分发的能力,将纵向失败的流量实例流量均摊到成功的实例上。 容器横向伸缩阶段:两种情况会进行横向扩容阶段: 其一,当高峰流量持续时间较长(一般超过10分钟)时,会进行横向扩容实让服务容器分裂(例如:2个实例10进程 → 20个实例1进程); 其二,纵向扩容后仍然不能完全满足吞吐要求(例如100倍的服务吞吐需求),则会在纵向扩容后瞬间触发横向扩容,不过此时业务完全满足效率退化成分钟级。
核心实现: 调度核心架构
采集层: 采集数据的基础信息,这里主要需要集中类型的信息,尤其是扩缩容其实主要关注两个队列信息: 数据流的队列信息 流式算子之间的队列信息 决策层: 根据历史调度信息和当前的实际状态信息进行决策,实现多阶段可变步长的扩容: 优先进行本地扩容,根据当前容器的资源使用量最多需要平均可以扩容5→20倍 长时间当本地扩容到(或者接近)极限,则会进行横向扩容,这个资源水平没有特殊限制 多阶段: 本地扩容(纵向) + 横向扩容 可变步长: 数据堆积都有多个阈值,每个阈值关系到不同的步长(默认每个APP至少两个步长)。eg: 政务业务的数据流堆积1000持续超过30s则触发扩容1倍,如果超过10000,则直接扩容到最大实例数 分析层: 在整体资源低于阈值(默认85%)的时候默认是跳过该阶段;在整体资源超过阈值后,为了保证高优先级的资源进行优先级调度使用的,必要的时候会对低优任务进行淘汰 执行层: 根据决策分析层提供的信息执行 本地扩容: 直接调整容器Quota信息的同时基础框架的进程管理启动服务的进程数来实现本地的极速扩容(比横向扩容快一个数量级) 横向扩容: 普通横向调整实例个数,由于涉及到资源调度,数据环境的初始化,需要的时间周期是分钟级 过滤: 扩容生效都有一个时间周期(本地扩容秒级,横向扩容分钟级),每个决策后都有一个静默期(比如10分钟)从而避免重复决策执行 跳档: 过滤只针对于完全相同的操作拦截,针对于不同步长扩容不拦截,保证业务在流量洪峰下的感知执行速度 执行: 真正执行操作,例如扩缩容操作
4.2 智能控制: 防止问题升级扩散,全自动实时处理
快速: 处理速度快,主动发现 与 消息通知相结合的方式,全面进行问题排查 准确: 历史出现过的问题转化成系统规则,整个过程模拟专家进行处理解决。只要规则合理,没有误操作,没有非预期行为 自动: 处理过程完全无需人工干预,全程自动化处理
基础采集层: 为所有的观测系统的数据提供最原始的基础数据采集。从数据类型来分主要是三类: 流式数据: 需要记录每条数据的信息,主要借助于Kafka的数据队列收集 指标数据: 对外汇报每个实例的指标数据,对外exporter汇报数,或者直接原始公司公司内的监控系统进行采集 自定义数据: 这种一般使用脚本以特定化的方式采集,作为基础指标采集的补充 数据处理层: 该层主要是针对于流式原始数据的数据处理,从图中可以看到主要是两部分数据,很多基础数据信息不需要额外聚合 指标聚合层: 主要是提供于拓扑分析系统,这里基于StatsD和Prometheus的转换接口,实现的指标动态分桶机制,极少资源完成大量数据信息 数据聚合层: 主要提供于实时成功率监控系统,这里是基于数据的动态Hash和流式计算完成的 存储层: 该层是可观测系统的中间核心,这里我们用到的数据存储既有开源的系统(包括ES/Prometheus/Mongo等),也有公司内的监控系统(以复用为主)。有两个大系统提供原始数据: 一方面,给上层应用系统提供数据展示的原始数据; 另一方面,给智能控制提供决策的原始数据。 展现层: 用户直接访问的前端接口,这里有我们自定义的平台,也有直接借助开源系统Grafana和Skywalking之上进行建设 应用层: 用户或者是架构所需的对外查看的系统,有6大业务系统,包括: Trace系统: 包括数据Trace 和 日志Trace,确认任意单条数据信息 指标系统: 最关键的基础数据信息,所有架构层和业务层的核心指标都收录于此 健康刻画系统: 通过当前全局的报警信息(报警级别、时间、个数)刻画出整体当前系统的健康程度 拓扑分析系统: 分析业务侧面和架构侧数据流是否存在异常(数据流量变化,异常点分析) 效果监控系统: 从数据生效结果监控,从架构效果端反推业务问题,比如 监控关键数据变更的时间戳反推架构系统问题 实时成功率监控: 查看数据流整体端到端的实时成功率信息
健全的自愈能力建设(手段)
服务管理类: 主要是基于资源&服务的管理,包括通路切换(主备切换,优先级切换)、数据拦截、数据回灌 和 服务降级 等 通路管理类: 主要是基于提供基础组件的管理功能, 包括流量清理、查询拦截(异常查询&慢查询查杀)
自动化问题分析引擎(核心): 规则+Function
阶段1: 传统配置化的规则引擎的配置(上图中右上角黄色部分),配置多个采集指标项的逻辑关系(与或交非), 这里主要是针对问题的基础分析功能,判定规则是否触发。 阶段2: 基于这个基础分析的结果,进行后置Function的执行分析,这个主要是针对复杂问题的分析补充, 最终执行引擎根据这个返回结果进行函数执行。
前提: 开发者需要配置好处理逻辑规则(以及规则依赖的数据项,必填) & 回调函数(选填)。 数据解析器: 数据解析器主要承担的数据的原始抽取的工作,一共分成如下3步;
配置解析: 逻辑执行根据开发者配置的数据信息解析; 数据抽取: 根据解析出来的配置通过数据接口进行获取,可以从统一接口根据配置的信息从不同的介质充抽取所需求的信息; 数据归一化: 将不同介质的原始数据归一化成为统一的数据格式供规则管理器使用。
规则解析: 根据开发者配置的规则逻辑,将原始配置信息,解释成原始的规则树; 执行计算: 根据数据解析器提供的数据结果和配置的函数规则分别执行计算。执行计算过程中最重要的就是基础分析器,整体提供了5大基础能力,数十种常见的逻辑计算来辅助规则配置。 规则逻辑运算: 根据上层解析出来的规则树 和 每个数据项执行完成的计算结果进行逻辑运算,并根据执行的结果确定是否进行高级数据分析器,如果判断结果为真则根据所配置的后置函数进行处理;
五、总结
通过FaaS化的建设,提升基础服务性能的同时全流程服务效率的提高, 具体来说包括两部分: 打造新一代的核心框架,提供强大的基础底座让业务核心关注点从原来的云化服务思维聚焦到逻辑实现,业务通过简单复用和编排实现复杂的功能,让业务开发更简单 提供一体化全流程系统建设,让业务从接入、开发、调试测试到最终系统维护全流程的流畅体验,助力业务更高效的交付 通过智能化建设,在稳定性有巨大提升的同时大幅度降低资源成本和系统的维护成本,具体来说也包含两部分: 通过智能化调度, 实现业务的按需分配(0→n), 秒级应对突发流量, 节约大量的资源成本; 通过智能化控制,实现全系统绝大多数问题问题的自动感知、自动分析、自动处理,提升稳定性的同时降低了系统的维护成本。
参考阅读:
技术原创及架构实践文章,欢迎通过公众号菜单「联系我们」进行投稿。