0. 写在前面
AI可以说是目前互联网行业炙手可热的“明星”。无论是老牌巨头,还是流量新贵,都在大力研发AI技术,为自家的业务赋能。美团很早就开始探索不同的机器学习模型在各种业务场景的应用,从最开始的线性模型、树模型,再到近几年的深度神经网络、BERT、DQN等,并成功应用于搜索、推荐、广告、配送等业务,也取得了较好的效果与产出。
美团配送技术部建设的算法平台——Turing(下称图灵平台),旨在提供一站式的服务,覆盖数据预处理、特征生成、模型训练、模型评估、模型部署、在线预测、AB实验、算法效果评估的全流程,降低了算法工程师的使用门槛,帮助他们脱离繁琐的工程化开发,把有限的精力聚焦于业务和算法逻辑的迭代优化。具体的实践,大家可参考美团技术团队此前推送的一篇技术博客《一站式机器学习平台建设实践》。
随着机器学习平台、特征平台、AB平台等陆续完成,配送技术团队发现在线预测部分逐渐成为算法开发和迭代的瓶颈,为此,我们开始启动图灵在线服务框架的整体研发。本文将与大家详细探讨图灵平台中的在线服务框架——图灵OS(Online Serving)的设计和实践,希望对大家能够有所帮助或者启发。
随着图灵平台逐渐成熟,包括美团配送在内,已经有超过18个业务方接入了图灵平台,整体概况大致如下:共接入10+个BU(业务单元),100%覆盖美团配送核心业务场景,支持500+个在线模型、2500+个特征、180+个算法策略,每天支持百亿次的在线预测。通过图灵平台赋能,算法迭代周期由天级别降至小时级别,大幅提升了配送算法的迭代效率。
1. 图灵平台介绍
图灵平台是一站式算法平台,总体架构如下图1所示,底层依托于Kubernetes和Docker,实现了对CPU/GPU等资源的统一调度和管理,集成了Spark ML、XGBoost、TensorFlow等机器学习/深度学习框架,包含特征生产、模型训练、模型部署、在线推理、AB实验等一站式平台功能,支撑了美团配送及闪购、骑行、买菜、地图等事业部的调度、时间预估、配送范围、搜索、推荐等各类AI应用。图灵平台主要包括机器学习平台、特征平台、图灵在线服务(Online Serving)、AB实验平台四大功能。
图1 图灵平台总体架构
-
机器学习平台:提供模型训练、任务调度、模型评估和模型调优等功能,基于DAG实现拖拽式的可视化模型训练。
-
特征平台:提供在线和离线特征生产、特征抽取和特征聚合等功能,并推送到在线的特征库,提供高性能的特征获取服务。
-
图灵在线服务:Online Serving,以下简称图灵OS,为特征获取、数据预处理、模型和算法策略的线上部署及高性能计算提供统一的平台化解决方案。
-
AB实验平台:提供事前的AA分组,事中的AB分流和事后的效果评估等功能,覆盖AB实验的完整生命周期。
图灵OS主要指图灵平台的在线服务模块,聚焦于机器学习/深度学习在线服务,目标是让离线训练好的模型能够快速上线,有效提升各业务部门的算法迭代效率,快速拿到结果,对业务产生价值。以下将重点介绍图灵在线服务(Turing Online Serving)。
2. 图灵OS的建设背景
在美团配送业务发展初期,为了支撑业务的快速发展,快速支持算法上线、快速试错,各个业务线的工程方独自开发在线预测的一系列功能,也就是我们所熟知的“烟囱模式”。此种模式各自为战,非常灵活,能够快速支持业务的个性化需求。但随着业务规模的逐渐扩大,这种“烟囱模式”的缺点就凸显了出来,主要表现在以下三个方面:
-
重复造轮子:特征获取和预处理、特征版本切换、模型加载和切换、在线预测和AB实验等都是各自研发,从零做起。
-
平台化能力缺失:缺乏对特征、模型迭代上线的完整生命周期的平台化运维、管理、监控和追踪能力,研发效率低下。
-
算法与工程耦合严重:算法与工程边界模糊,耦合严重,相互制约,算法迭代效率低下。
“烟囱模式”在业务发展早期做出了不可磨灭的贡献,但随着业务体量的增长,这种方式的边际收益逐渐降低到了不可忍受的程度,亟需一个统一的在线服务框架来进行改变。
目前,市面上大部分主流开源的机器学习在线服务框架仅提供了模型预测功能,不包含预处理和后处理模块,如下图2所示。
图2 机器学习在线服务示意图
比如谷歌TensorFlow Serving是一个用于机器学习模型Serving的高性能开源在线服务框架,提供gRPC/HTTP接口供外部调用,支持模型热更新与自动模型版本管理,同时解决了资源调度、服务发现等痛点,对外提供稳定可靠的服务。但是TensorFlow Serving不包含预处理和后处理模块,需要将业务工程方将输入预处理成张量传递给TensorFlow Serving进行模型计算,然后再对模型计算结果进行后处理。预处理和后处理的逻辑对于算法策略非常重要,迭代也比较频繁,这部分跟模型结合比较密切,更适合由算法同学负责,如果由工程方实现,则工程同学只是单纯的实现算法同学设计的逻辑,耦合过于严重,迭代效率低,而且还容易导致设计和具体实现不一致,引发线上事故。
为了解决上述问题,为用户提供更方便易用的算法平台,图灵平台建设了统一的在线服务框架,通过整合模型计算和预处理/后处理等模块,以算法版本的形式进行呈现,并进行迭代,免去了与算法与工程之间复杂的交互。
这里我们对算法定义进行了扩展,本文中的算法(也称算法策略)可以理解成一个组合函数:y=f1(x)+fi(x)+…+fn(x),其中fi(x)可以是规则计算、模型计算(机器学习和深度学习)或者非模型算法计算(比如遗传算法、运筹优化等)。该组合函数中任何组合因子的调整(比如模型输入输出变更、模型类型变更或者规则调整)都可看作是一次算法版本的迭代。算法迭代是算法开发-上线-效果评估-改进的循环过程。Turing OS的目标就是优化算法的迭代效率。
3. 图灵OS 1.0
3.1 图灵OS 1.0介绍
为了解决“烟囱模式”开发过程中的重复造轮子和平台化能力缺失的问题,我们着手搭建了图灵OS 1.0框架。该框架整合了模型计算和预处理、后处理模块,把繁杂的特征获取和预处理、模型计算、后处理等逻辑都封装在图灵在线服务框架中以SDK的形式对外提供。算法工程师基于图灵在线服务SDK开发个性化的预处理和后处理逻辑;业务工程集成图灵在线服务SDK和算法包,调用SDK提供的接口进行模型计算和算法计算。
通过图灵OS 1.0,我们解决了各业务方独自开发、独自迭代以及重复造轮子的问题,大大简化了算法工程师和工程研发人员的开发工作,而且工程是通过图灵在线服务框架间接调用算法预处理和模型计算,不直接跟算法进行交互,一定程度上也减轻了工程和算法的耦合问题。
如图3所示,该阶段的图灵在线服务框架集成了以下功能:
图3 图灵OS 1.0
3.1.1 特征获取
-
通过特征聚合、动态分组、本地缓存以及业务线级别物理资源隔离等手段,提供高可用、高性能的特征在线获取计算能力。
-
通过自定义MLDL(Machine Learning Definition Language)将特征获取流程配置化,并统一特征获取流程,提升在线服务特征的易用性。
-
DLBox(Deep Learning Box)支持将原始向量化特征和模型放在同一节点进行本地计算,解决深度学习场景下需要召回大规模数据的性能问题,支撑配送各个业务高并发及算法快速迭代。
3.1.2 模型计算
-
支持本地(Local)和远程(Remote)两种模型部署模式,分别对应将模型部署在业务服务本地和专用的模型在线服务集群中;通过多机异步并行计算,支持CPU/GPU资源异构等手段,解决大规模模型计算的性能问题;通过模型Sharding解决超大规模模型单机无法装载的问题。
-
在深度学习模型计算方面,利用高性能计算加速库MKL-DNN以及TVM等编译优化技术进一步提升深度学习模型的推理性能。
-
通过MLDL封装的模型特征关联关系以及预处理逻辑等配置,实现了特征获取、特征处理以及组装的自动化,提升了模型的开发迭代效率。
3.1.3 算法计算
-
支持算法版本管理、AB路由,支持动态获取算法版本所关联的模型、特征和参数等,支持模型和参数的热更新。
-
支持AB实验以及灵活的灰度发布放量,并通过统一埋点日志实现AB实验效果评估。
3.2 图灵OS 1.0遗留问题
图灵OS 1.0解决了各业务线重复造轮子、特征混乱和平台能力缺失等问题,通过提供一站式平台化服务,支撑了美团配送各业务线大规模算法在线预测的场景和高性能计算的需求;使算法同学更加关注算法策略本身的迭代优化,提高了算法迭代的效率。但是对于前述的工程、算法、平台三方耦合问题,还没有很好的解决,主要体现在:
-
业务工程静态依赖算法包,算法包部署在业务工程中,算法包更新迭代上线需要业务工程发版。
-
算法包与业务工程运行在同一个JVM中,虽然减少一次RPC消耗,但是算法包的计算性能会影响业务工程的性能,业务工程稳定性不可控,比如TensorFlow模型计算时对CPU的消耗过大、大模型的加载和切换对内存的消耗等问题。
-
随着图灵平台提供的功能越来越丰富,图灵在线服务SDK变得越来越臃肿,业务工程必须升级图灵在线服务SDK才能使用图灵平台新功能,但是业务工程升级SDK风险较高,而且会拖慢业务工程部署的速度。
图4 三方高耦合示意图
基于上述几点可知,算法、工程和图灵平台三方高耦合,导致各自都存在很多痛点,如图4所示。这些问题严重影响了算法迭代效率,算法迭代上线测试工期长,效率低:
-
算法痛点:算法包迭代强依赖业务工程上线,每次工程发版都需要走一个完整的研发测试周期,流程长,效率低。
-
工程痛点:算法包与业务工程在同一个JVM中,算法计算的性能将影响业务工程服务的性能;同时业务工程需要跟随算法包的迭代频繁发版,改动可能只涉及升级算法包的版本。
-
图灵平台痛点:图灵在线服务SDK部署在业务工程中,版本收敛难度大,兼容难度大;同时图灵新功能推广难度大,需要业务工程升级图灵在线服务SDK。
因此,必须将算法、工程和图灵平台更好的解耦,既满足算法快速迭代的需求,又能满足业务工程端稳定性的诉求,合作共赢。
4. 图灵OS 2.0
针对图灵OS 1.0框架中算法、工程和图灵平台三方高耦合的痛点,我们研发了图灵OS 2.0框架,目标是解决算法、工程、图灵平台三者耦合的问题,让算法迭代无需依赖工程发版,图灵平台新功能上线无需业务工程升级SDK,进一步提升算法迭代效率和工程开发效率。
围绕解耦算法、工程和图灵平台的目标,在图灵OS 2.0框架中,我们设计研发了算法包插件化热部署框架、算法数据通道和算法编排框架等功能,支持算法自助迭代上线。同时设计研发了以沙箱引流、实时回放、性能压测和Debug测试等功能为一体的算法验证平台,保证了算法策略的高性能、正确性及稳定性。图灵OS 2.0框架解耦了算法、工程和图灵平台,实现了算法与工程迭代的各自闭环。大部分算法迭代的整个流程无需工程研发人员、测试工程师的参与,算法工程师在小时级即可完成算法策略的迭代上线;通过图灵OS 2.0的赋能,算法的研发迭代效率得到了大幅提升。
图5 图灵OS框架V2.0
图灵OS 2.0具体功能特性如下:
-
标准化轻量级SDK:业务工程只需依赖一个轻量级的图灵OS SDK,无需频繁升级,降低工程端接入难度,解耦业务工程与图灵平台。
-
算法插件化:自研图灵算法插件框架,支持算法包作为一个插件在图灵OS服务中热部署,解耦算法与工程;图灵OS服务中可部署多个算法包的多个版本,每个算法包拥有独立的线程池资源。
-
数据通道:在一些复杂的算法场景下,算法策略还需依赖业务工程完成:1)算法内部获取数据,只能通过业务工程调用接口获取结果之后传递给算法;2)算法内部调用算法,只能通过业务工程中转同时调用算法A和算法B。为了解决上述两点,我们提出了数据通道(Data Channel)的概念,使得算法本身具备自主获取数据的能力,而不是所有数据都需要业务工程获取然后再透传给算法。
-
算法编排:多个算法按照串行或者并行的方式组合为有向无环图图(DAG),可以看作是一个算法编排;业务算法的抽象与沉淀,对应到新架构就是算法的组合与编排,算法编排为业务上线和算法迭代进一步赋能,进一步提升了业务算法迭代效率,进一步解耦算法和工程。
-
沙箱引流:图灵沙箱是一个与图灵OS物理隔离,但运行环境完全一致的服务,流量经过沙箱不会对线上业务造成任何影响;沙箱可验证算法逻辑的正确性,同时评估算法计算的性能,提升研发测试流程的效率。
-
图灵回放及统一埋点:在算法计算及模型计算的过程中会产生很多重要数据(算法策略、模型、特征、参数和数据通道等相关数据),这些数据不仅有助于快速排查定位系统问题,也为AB实验报告、沙箱引流和性能压测等模块提供了重要的数据基础,为了更好地自动记录、存储和使用这些数据,我们设计了实时回放平台和统一埋点。
-
性能压测:图灵OS通过整合美团全链路压测系统Quake的能力,复用统一回放平台采集的流量数据来构造请求,对部署了新版本算法包的沙箱进行压力测试,保证算法策略迭代的性能及稳定性。
图6 图灵OS 2.0总体架构
以下将对上述几个功能特性进行展开介绍,看看图灵OS 2.0是如何解决算法、工程和图灵平台三方耦合痛点的。
4.1 标准化轻量级SDK
为了解决业务工程和图灵平台的耦合痛点,即图灵在线服务SDK部署在业务工程中,SDK版本收敛难度大的问题,我们主要从SDK轻量化、简单易接入、稳定可扩展、安全可靠等几个方面考虑对图灵在线服务SDK进行了拆分和改造:
-
SDK轻量化:将原有图灵OS SDK逻辑下沉到图灵OS服务中,只提供简单通用的批量预测接口;该SDK无需过多暴露算法相关的细节,算法版本路由、实时/离线特征获取、模型计算等都隐藏到图灵OS内部。轻量级的SDK内部集成了图灵OS的自定义路由,业务方无需关注算法包部署在哪个图灵OS集群,对使用方完全透明。
-
简单易接入:提供统一且通用的Thrift接口进行算法计算,使用Protobuf/Thrift来定义算法输入输出,相对于目前Java类定义接口的优势是兼容性有保障;Protobuf接口定义完成后,算法和工程可以各自独立进行代码开发。
-
可扩展:轻量级SDK版本稳定,无需工程端反复升级;Protobuf天然支持序列化,后续流量拷贝、回放埋点等都可以基于此进行。
-
高性能:针对大批量算法计算且要求高可用的场景,例如面向C端用户的批量预测,我们设计了异步分批高度并行等手段提升算法计算性能;针对单任务计算耗时长、CPU消耗高且要求高可用的场景,例如分城市区域的调度路径规划,我们设计了客户端快速失败最优重试机制保证高可用,也均衡了图灵OS的计算资源。
-
安全可靠:针对单个图灵OS部署多个算法包的场景,提供线程池级别的资源隔离,针对各业务线不同的算法包,按业务场景垂直拆分,提供物理级别集群资源隔离,同时增加熔断降级机制,保证计算流程稳定可靠。
4.2 算法插件化
通过对图灵OS SDK进行标准化轻量化改造,我们解决了业务工程和图灵平台之间耦合的痛点。通过对图灵OS进行服务化改造,解决了算法和业务工程之间耦合的痛点。但是算法和图灵平台之间耦合的痛点依然存在且痛点增加:算法迭代上线依赖图灵OS服务发版,并未能达到三方解耦的目标。
为了解决算法与图灵平台之间的耦合痛点,进一步提升算法策略的迭代效率,我们下一步的设计思路是算法插件化,图灵OS容器化:将算法包作为一个插件,部署到图灵OS中,算法包发版不要求图灵OS发版,甚至不需要重启图灵OS,如图7所示。
-
算法插件化:我们自研了图灵OS算法插件框架,支持算法包以插件的形式部署到图灵OS服务中;具体实现方案是自定义算法类加载器ClassLoader,不同的ClassLoader加载不同的算法包版本,通过加载多版本算法包以及指针替换,实现算法包热部署。
-
图灵OS容器化:图灵OS充当一个插件容器,装载算法包不同的算法版本,执行算法版本路由以及算法策略计算,图灵OS经过容器化改造之后的流程:1)如果算法版本不需要新增参数,则工程端和图灵OS都不需要发版;2)业务工程主要工作是传递参数给算法,逻辑简单,如输入参数无变化则不需要发版,算法包发版节奏自己掌控。
图7 图灵OS容器化-算法插件化示意图
4.3 数据通道
通过上述手段,我们解决了算法、工程和图灵平台三者在发版迭代时的耦合问题。但是除了上述的耦合之外,还有一些复杂算法场景,算法与业务工程依然存在耦合,主要体现在算法依赖业务工程的以下两点数据:
-
算法内部获取数据:目前是通过业务工程调用接口获取结果之后传递给算法,例如一些服务化接口数据、分布式KV缓存数据等,算法和业务工程都需要进行开发迭代上线。
-
算法内部调用算法:目前通过业务工程同时调用算法A和算法B并编写中转逻辑来实现,例如算法A的输入需要用到算法B的结果,或者需要综合算法A和算法B的结果得到最终输出,这些操作一般都交由业务工程来处理。一种可选方案是将算法A和算法B合并成一个庞大的算法,但该方案的劣势是增加了算法A和算法B独立进行AB实验及灰度的研发成本。
为了解决上述两点,我们提出了数据通道(Data Channel)的概念,使算法本身具备自主获取数据的能力。在算法内部算法可通过图灵OS提供注解的方式支持数据通道,算法与业务工程的交互接口仅需传递一些关键参数及上下文数据即可,算法内部自行组装该数据通道所需参数。经过数据通道化的改造,算法接口进一步简化,算法与工程耦合度进一步降低,算法内部调用算法的问题,我们可通过下面介绍的算法编排来进行解决。
4.4 算法编排
一个完整的算法计算流程包括算法计算部分,以及针对输入的预处理逻辑和计算结果的后处理逻辑等,算法计算可以是N次规则计算,N次模型计算(机器学习和深度学习等),或者非模型的算法计算(比如遗传算法、运筹优化等),或者多种类型算法组合。我们把这种具有独立输入输出的计算逻辑单元抽象为一个算子,算子可编排、可复用,通用的两类算子如下:
-
模型计算算子:即模型计算引擎执行模型计算,我们支持Local和Remote两种模型计算模式,在Remote计算模式中,模型可能部署在不同的模型集群中,算子是对模型计算的进一步封装,将Local和Remote选择及模型集群路由等功能对用户透明,算法工程师无需感知,我们会根据整体计算性能进行动态调整。
-
算法计算算子:即图灵OS中的算法计算引擎执行算法策略计算,不同的算法插件可能部署在不同的图灵OS中,同时也将图灵OS集群的路由功能进行了封装,对用户透明。
多个算子之间通过串行或者并行的方式组合为一个有向无环图(DAG),形成了算子编排,当前我们有两种方式实现算子编排:
-
算法数据通道:不同图灵OS中的算法计算引擎互相调用或者算法计算引擎调用模型计算引擎,算法数据通道是实现算子编排的一种具体手段。
-
算法总控逻辑:我们在算法调用的上层抽离出一层算法总控逻辑层,满足复杂算法场景及多个算法关联依赖的情况,该算法总控逻辑由算法工程师在算法包中实现;通过算法总控逻辑功能,算法工程师可以任意编排算法之间的关系,进一步解耦算法和工程。
从算法工程师的视角来看,图灵OS以搭积木的方式提供服务,通过组合一个个独立的子功能及算子,以标准的方式串并联,从而形成满足各式各样需求的在线系统。
图8 基于算子编排的算法在线服务架构
在该架构下,算法的工作主要有如下三部分:1)算法工程师进行业务流程的抽象与建模;2)算法工程师进行独立的算子开发与测试;3)算法工程师基于业务流程抽象进行算子的编排与组合。算子编排为业务功能上线和算法迭代进一步赋能,业务算法迭代效率进一步提升。
4.5 多模式集成
上文介绍了图灵OS作为一个容器可部署多个算法包的多个版本,并支持算法包热部署。图灵OS通过插件化热部署以及编排等功能,解耦了业务工程、算法以及图灵的三方耦合,极大地提升了算法的迭代效率。为了进一步满足业务的要求,我们提供了两种图灵OS部署集成模式:Standalone模式和Embedded模式。
Standalone(独立模式)
Standalone模式下,图灵OS是独立于业务服务单独部署的,业务服务通过轻量级SDK调用算法,图灵轻量级SDK内部封装了图灵OS的自定义路由,以及Thrift-RPC调用图灵OS服务的逻辑。
Embedded(内嵌模式)
在某些高并发及高性能要求的复杂场景中,对我们图灵OS的集成模式及性能提出了更高的要求。在独立部署模式下,业务工程每一次算法计算都有RPC的消耗,因此我们实现了图灵OS新的集成模式——Embedded。在Embedded模式下,我们对外提供图灵OS框架代码包,业务方在自己的工程服务中集成图灵OS框架包,业务服务同时也作为一个图灵OS容器,还是通过轻量级SDK调用算法,在业务服务本地进行算法计算。内嵌图灵OS的特点如下:
-
业务工程因集成了图灵OS框架代码,而继承了算法包插件化和热部署的功能,具备了业务功能和图灵OS容器的双重属性。
-
业务工程并不直接依赖算法包,而是由图灵OS框架进行动态管理,算法包进行插件化热部署,达到了算法和工程解耦的目的。
-
业务工程直接进行本地算法计算,减少了算法调用的RPC及序列化消耗,同时复用了业务工程服务器资源,进一步减少集群资源消耗,提升了资源利用率。
在算法包插件部署时,以内嵌模式集成的业务工程将作为容器装载相应的算法包,路由到本地进行算法计算,如下图9所示。
图9 图灵OS集成模式Embed/RPC示意图
Standalone和Embedded模式各有利弊,谁都没有绝对的优势,使用时需要根据具体的业务场景进行选择。两种模式的对比如下:
部署模式
优点
缺点
适用场景
Standalone
耦合度更低,业务方只依赖图灵轻量级SDK
需要搭建图灵OS集群,占用机器资源;有RPC调用开销
适合大批量调用,需要分布式多机异步并行计算的业务场景
Embedded
复用业务方机器,资源利用率高;少了RPC调用,性能高
无法充分发挥多机异步分布式并行,只能单机并行
适合小批量调用,对单次调用RT性能要求较高的业务场景
4.6 图灵沙箱
暂无评论内容