10 月,开发者不可错过的开源大数据大会-2021 WeDataSphere 社区大会深圳站 了解详情
写点什么

APPKIT 打造稳定、灵活、高效的运营配置平台

2020 年 2 月 25 日

APPKIT打造稳定、灵活、高效的运营配置平台

一、背景

美团 App、大众点评 App 都是重运营的应用。对于 App 里运营资源、基础配置,需要根据城市、版本、平台、渠道等不同的维度进行运营管理。如何在版本快速迭代过程中,保持运营资源能够被高效、稳定和灵活地配置,是我们团队面临的重大考验。在这种背景下,大众点评移动开发组必须要打造一个稳定、灵活、高效的运营配置平台。本文主要分享我们在建设高效的运营配置平台过程中,积累的一些经验,以及面临的挑战和思考。


运营资源

简单而言,运营资源可以理解为 App 中经常变动的一些广告、运营活动等等,譬如下图中电影首页顶部的 Banner 位,就是一个典型的运营资源。对于这类运营资源,它们有如下明显特征:


  1. 时效性,只在一定时间范围内显示在 C 端固定位置。

  2. 城市强相关,这类运营资源往往是基于 LBS 类服务,每个活动、广告都只会出现在固定的某些城市(或区域)。



基础配置

基础配置,常见的有入口资源的配置、网络的配置等。相对运营资源来说,其变更的频繁度相对较低,与时间、城市的关系也没那么强。譬如下面大众点评 App-我的页面里的入口。这类配置有如下几个特征:


  1. 多维度:需要针对不同的版本、平台、渠道,做不同的配置。

  2. 长期有效:这种类型的配置一般长期存在,不会存在过期问题。



二、遇到的问题

在从 0 到 1 打造运营配置平台的过程,我们遇到了很多“坑”。特别是在早期“刀耕火种”的时代,对于入口的配置,往往是通过“hardcode(硬编码)”的方式写死在代码中。所以必然会遇到很大的问题,这主要体现为以下两方面:


运营效率低

对于新的运营配置需求,研发同学需要开发对应的配置页面,然后转给运营同学进行配置的管理,最后运营人员对资源进行配置上线,其流程如下:



对于每个运营配置需求都要经过需求评审、页面开发、配置管理、上线的流程。同时,对于配置页面的开发,少则需要 1 到 2 天的开发工时,研发成本高。问题总结如下:


  1. 研发成本高,每个需求要开发新的配置管理页面。

  2. 研发周期长,运营效率低,从需求的提出到运营上线周期长。

  3. 灵活性差,对不同的运营维度(城市、版本、时间等)都需要事先确定好,无法动态调整。


上线流程“粗糙”

在早期,运营配置上线流程需要研发同学参与。产品提出运营配置需求,研发同学通过修改代码对配置进行变更,然后通过代码上线进行发布。整体流程如下:



这种上线机制存在以下几个问题:


  1. 配置上线过多依赖于代码的发布。

  2. 整体上线过程无审核机制,无法对配置资源进行合规审核。

  3. 配置容易出错,上线前不能提前预览上线后的效果,只有“事后”(上线后)才能验证效果。


三、我们的思考

针对以上问题,我们希望通过设计一个通用的解决方案,去解决上文阐述的各种运营资源管理的问题。我们把这个整体的项目称之为 APPKIT,寓意是 App 的运营配置工具(Kit)。通过不断的实践和总结,我们希望能从三个维度解决上述问题:


数据 JSON 化

随着业务的不断迭代,无论采用怎样的数据字段组成,都无法满足业务变化的字段(这里是指像标题、副标题、图片、跳转链接等)要求。对底层数据进行 JSON 化,其对应的数据字段完全可动态扩展,从而满足业务不断迭代的需求。JSON 化随之也会带来运营位字段管理的问题,我们通过字段管理的工具来解决这个问题。


运营流程化

设计一套整体的流程管理机制,解决运营的投放、审核、发布和回滚的问题。通过流程化的机制,我们实现了“事前”、“事中”、“事后”的三级管理。


首先,在运营配置上线前,通过测试用户的预览功能,可以预览上线后的实时效果。同时,通过穿越功能可查看将来时段显示的效果。防止出现上线后链接出错、视觉效果达不到预期等问题。


其次,在流程阶段,引入审核机制,通过视觉和内容两方面的审核,保证投放数据的准确性。


最后,在运营配置上线后,如果发现问题,可以通过快速回滚,最大限度地实现“止损”。



接口 SDK 化

对于运营数据,无论是通过数据库的落地方案、还是通过分布式缓存的方案,都无法彻底解决服务中心化和服务抖动的问题。通过接入的 SDK 化,可以做到数据的本地缓存更新机制,解除对中心化服务的依赖,大大提升服务的稳定性和性能。同时整个 APPKIT 服务变成可水平扩展,在扩展过程中也不会影响中心服务的稳定性。


四、APPKIT 架构

APPKIT 运营配置系统整体框架如下(数据流向如箭头所示)。从功能角度,大体上分为四层:数据层、服务层、接入层和监控层。



4.1 数据层

数据层作为最底层的数据存储,其保存了最基本的运营后台数据、流程数据和线上数据。对持久化的数据,我们采用 MySQL 进行存储;对于缓存数据,我们采用了 Redis 的解决方案。这样数据层形成基本的两级存储结构:MySQL 保证了数据的持久性,Redis 保证了数据获取的速度。


这里我们对底层数据划分为三个不同域:后台数据,相当于草稿数据,运营人员所有的操作都记录在这里;流程数据,运营人员操作完成后,提供发布流程,预览及审核都在流程数据里进行;线上数据,审核通过后,数据同步到线上数据,最终 C 端用户获取到的数据都是来源于线上数据。


谈到数据层,这里我们遇到了存储上的一个小问题。按城市运营的每条数据,都需要存储具体的城市 ID 列表,其在数据库里的存储为 “1,2,3,4…… ”这样字符串。而这种数据存储在业务请求和条件过滤过程中,存在着如下两个问题:


a. 大数据存储对内存的消耗

美团、大众点评运营的城市成千上万,如果每条运营的投放数据都包含大量的城市列表信息,对机器内存势必产生一定消耗。


b. 过滤性能问题

城市的过滤逻辑大体是这样:用户所在城市与从数据库获取到的城市列表(“1,2,3,4…… ”)进行匹配,在每次匹配过程中都需要做字符串“split”的切割操作。这种操作的特点是流量越大,对机器 CPU 的消耗越大。


解决方案:基于以上两点考虑,再结合 Java 语言提供的 BitSet 机制。我们从数据库里取出城市列表数据后只做一次“split”切割操作,将数据转化为 BitSet 类型。这样在实际过滤过程中只需要通过 BitSet 的 get 机制就可以判断运营投放的城市是否包含了用户所在的城市。通过 BitSet 机制,我们既解决了大数据存储对内存的消耗问题,又解决了城市过滤的性能问题。


4.2 服务层

服务层向下对底层数据进行操作;向上为接入层获取数据提供接入能力。其提供四个服务能力:运营后台、开放平台、数据服务、APPKIT-SDK,如下表所列:



服务层


4.3 接入层

接入层主要为运营人员、业务研发提供接入能力。通过运营流程化为事前、事中、事后提供保障。一个运营资源从制作到最后在 C 端展示,需要经过运营人员的投放、测试预览、审核及发布的中间流程。这里对于一些敏感的运营资源,需要通过安全部门的审查。安全审查主要涉及到敏感词的处理、敏感图片的检测等。对运营配置平台来说,它完全是一个“黑盒模型”。这里主要涉及到两种情况:


  1. 资源上线时



  1. 资源上线后



4.4 监控层

APPKIT-SDK 运行在业务机器上,这里就涉及到多台机器的数据一致性问题。同时,随着业务接入运营数据的增多,SDK 对机器内存势必有一定消耗。基于服务的稳定性考虑,我们对 SDK 运行时的投放内容进行监控,其主要监控两个指标:运营位数及每个运营位的配置总数。这样做可以带来以下几个好处:


  1. 对接入的业务数及机器数进行统计。

  2. 通过 SDK 的配置总数监控,防止数量超过最大限制。


同时,对于非 SDK 的其他性能指标,我们采用统一的监控平台–CAT进行监控,其中包括:APPKIT 中心服务的调用 QPS,机器的性能,网络流量等通用指标。


五、底层模型–灵活性设计

5.1 从一个例子切入

数据模型往往与业务相关。业务越复杂,设计需要越简单,这样方能满足复杂业务的各种变化。因为数据模型太过于抽象,如果直接进行述说会有些乏味,我们可以先从一个具体的业务实例入手。下面是大众点评 App 顶部金刚位的截图,对于这部分数据,如何做到运营可配?



首先,我们对运营数据做需求拆解。对于这块数据,每个 “节点”(对应每个位置:如美食,技术上我们称之为 “节点”),其基本的运营诉求如下:


  1. 节点内容信息:标题、图片、跳转链接、排序。

  2. 节点的过滤维度信息:城市、版本、平台、渠道等。

  3. 节点其他信息:角标,如外卖节点,其有一个下午茶这样的角标。值得注意的是,像下午茶这样的角标,除去文案、文案颜色这些基本信息之外,我们也可以按城市、平台、进行过滤(不周的城市对应的文案可能不一样,如上海为“下午茶”,北京因为嘉年华活动可以改成“嘉年华”)。


上面这个运营场景算是非常经典、复杂的一个运营场景了,如果这个问题解决了,其他问题自然就会迎刃而解。


5.2 技术分析

我们做一下进一步的技术分析:


首先,这里有节点,每个节点(Node)有其相应的内容(Content),节点与内容是“一对多”的关系。这里的内容,我们指的是如标题、图片、跳转链接等信息,虽然是“一对多”的关系,但最后在同一个城市、同一个版本下(可选择)只显示一条内容。为什么有这样的需求?举一个简单的业务场景实例,以外卖为例,在新版本 10.0 的时候做了一个全新的外卖频道页面,其链接信息与老版本的完全不同,这里我们就需要按版本的不同配置两条不同的内容信息。


其次,节点与节点之间有两层关系,其一为“平级关系”,如美食与外卖的关系,这种关系就是一种简单的列表关系;其二为树关系(Tree),如外卖与下午茶之间的关系。这里我们将角标(下午茶)视为一个节点,因为角标也需要按不同维度进行过滤,因此下午茶成了外卖的子节点。其实这里有一些特殊的地方,如果角标不需要按城市、版本等维度进行运营,那很简单它就是一个内容信息(类似标题)。


最后,我们谈一谈排序问题,对于这么多品类,如何排序,他们的优先级是什么?我们需要定一个基本的基调,每个节点都有一个基本的排序值(优先级)。但深入业务分析,对于不同的人(群),每个人关注的点不一样,需要一个“千人千面”的算法,来决定每个人所看到的内容是其真正关心的内容。所以,这种应用场景下的排序应该通过机器学习算法而得到。


5.3 数据建模

针对上面的技术分析,我们提出了一种节点(Node)-内容(Content)-树(Tree)模型,简称为 N-C-T 模型。如下图所示:左边为抽象的数据模型,右边为以上实例的实现。



N-C-T 数据模型设计的非常简单,其中 C 和 T 部分都是可选择的,这样使得其灵活性比较强,可以应对业务变化的大部分需求。注意,这里我们只是对业务需求的宏观表现形式进行建模,对于具体 Node 和 Content 里的有哪些字段(标题、副标题、图片、跳转链接),这些都是 JSON 化的存储格式,可以满足任意字段的扩展。


5.4 模型的应用与小结

通过以上经典实例,我们可以很容易通过我们的数据模型解决这个问题。我们再回到文章最开头的背景章节的运营场景,Banner 位,如下:



这种 Banner 位,套用我们上的数据模型,它其实是一种只有一个 Node 节点、多个 Content 节点的模型。这也是一种典型的应用场景,为此我们总结了两种应用场景。



其实,大部运营场景都可以套用以上两种经典的运营组合。


六、运营流程化

将运营资源的管理进行流程化,具有以下几个好处:


  1. 资源上线前可进行严格的审核。

  2. 出问题时可快速回滚。

  3. 记录用户的(上线)操作历史。

  4. 上线前可提前预览线上效果。


数据域

对于流程化的实现,我们是将数据域切分成三个不同的部分:后台数据、流程数据和线上数据,如下图所示:



后台数据:我们可以简单理解为草稿数据,这里的数据多用户可同时进行操作,也不会对线上数据有影响。


流程数据:当用户后台数据编辑完成后,对数据提交一个发布流程,数据进入流程数据区域;这时可对数据进行测试预览、审核等操作。


线上数据:这块数据是 C 端用户真正获取到的数据,当流程数据审核通过后,数据会自动同步到线上数据域,完成上线操作。


上线流程

整个上线流程如下:


  1. 运营同学对后台数据进行修改,提交发布流程,同时进行预览测试。

  2. 审核同学对提交的发布流程进行审核。

  3. 审核通过,自动发布到线上(对审核不通过的流程,数据回退到后台进行再次编辑)。


为了能平稳上线,我们设计了一个测试预览功能。当数据处于流程中时,用户可以通过扫描二维码加入到测试用户名单,可对处于审核流程中的数据进行预览,用美团、大众点评 App 查看上线后实时效果,其实现的数据流如下:



七、稳定性的演进

稳定性是一个运营配置平台最重要的能力,没有稳定性,其他任何功能都会失去实际意义。运营系统的稳定性经历了不同的迭代时期,总结起来,可概括为以下三个阶段:


7.1 经典方案

这是 APPKIT 最早期的经典方案,它的实现也非常简单,如下图所示:



C 端用户通过业务接入层获取数据,业务接入层通过服务调用获取配置后台数据(APPKIT 服务),配置后台数据服务读取缓存数据。如果缓存数据不存在,则从数据库中读取数据,同时将数据库数据同步到 Redis 缓存中。这是经典的数据获取模型,但它有以下几个缺点:


  1. 数据调用有网络时延。

  2. Redis 缓存抖动(网络抖动)会对服务的稳定性产生影响。

  3. 缓存的单 Key 存储的容量限制。


7.2 缓存方案

针对以上经典方案的缺点,我们做了进一步的改进,对配置后台数据服务做了一层本地内存缓存,如下图所示:



样做可以解决数据调用的部分网络时延问题,同时 Redis 缓存的抖动也不会影响整体服务的性能。不过,这个方案也有其自身的缺陷。


  1. APPKIT 服务成了中心节点,业务方对中心节点强依赖,随着业务接入越来越多,中心服务的压力会等比例增加。

  2. 业务接入层与配置后台数据服务间调用的网络时延问题仍然存在。

  3. 单机的 Web 缓存容量有限,随着业务接入越多,APPKIT 服务器本地缓存的数据量越大。


7.3 SDK 方案

为彻底解决缓存方案的问题,尤其是服务中心化带来的流量、容量等问题,我们将运营数据的获取、Web 缓存的管理集成进 SDK。如下图所示:



这样的话,无论接入再多的业务,也不会对中心服务产生过大的流量压力和容量压力。SDK 同时也解决了服务间调用的网络时延问题。所有同步数据的网络调用都是通过后台线程异步完成,不会影响业务线程的正常处理逻辑。


不过,SDK 方案也引进了如下的新问题:


  1. 数据时效性和一致性如何保证?

  2. SDK 本地缓存如何监控?过期数据如何删除?

  3. SDK 版本如何升级?


为了解决数据的时效性和一致性问题,我们引入了监听更新机制,如下图所示:



运营人员在运营后台操作完成后,提交上线流程,流程发布后通过 ZooKeeper 的变化监控发送一个变化事件;SDK 通过监听变化事件,拉取变化后的运营数据更新到本地。这里,为了防止这种监听机制失效,我们也做了一个兜底策略:每分钟定期进行一次数据同步。这样保证数据最迟一分钟内就能实现同步。对于 SDK 本地缓存,我们设计了监控上报机制,如下图所示:



这里有两条线路,其一为 SDK 在请求数据时,带上数据的 accessTime 时间戳,APPKIT 服务会根据 accessTime 时间戳判断 SDK 本地数据是否过期。当 accessTime 时间超过 24 小时,说明这个运营位在一天内都没有使用,可以从本地内存中进行删除。其二为 SDK 定期进行监控上报,上报 SDK 本地缓存的数目,这样可以对 SDK 本地缓存进行监控和告警。对 SDK 版本升级问题,现有的解决方案,是通过 CI 构建时对 SDK 版本升级进行提示(必要时进行强制),不过大部分运营位使用的都是基础功能,在很大程度上不需要进行频繁地升级。


效果对比

缓存方案与 SDK 方案的效果对比如下:



注: SDK 方案的平均线为 0.0 是因为统计时舍入引起的,真实值其实非常小。


八、总结与展望

本文通过美团点评移动运营平台的实践,详细介绍了我们在打造稳定、灵活、高效的运营配置平台过程中遇到的问题和挑战,同时本文也提供我们的解决思路:通过数据 JSON 化,运营流程化,接口 SDK 化分别解决了运营平台的灵活性、高效性和稳定性。APPKIT 帮助产品、运营和研发提升 C 端的开发和运营效率,加速产品的迭代进程。


目前基于 APPKIT 的平台化特性,对 App 的模块化配置、Picasso的 JS 的管理、ABTest、个人中心入口管理、鲁班(面向 C 端的 Key/Value 配置系统)等业务提供了底层的数据存储和数据获取的支持,为移动端业务提供了运营配置的基础保障。


同时,为了进一步提升运营效率,我们基于 Picasso 的多端(Android、iOS、H5、微信小程序)能力,正在构建移动化的运营能力。这样保障用户无论在什么办公环境都能进行运营配置的管理。


作者简介

  • 国宝,美团点评移动运营平台负责人,Java 后端架构师,APPKIT 项目发起人,负责 APPKIT 项目的架构设计。专注于高性能、高稳定、大并发系统的设计与应用。

  • 小龙,目前为 APPKIT 项目负责人,主要负责 APPKIT 项目开发、技术对接和实施、开放平台等。专注于前后端全栈技术开发,喜欢挑战新的技术和业务问题。


2020 年 2 月 25 日 20:33380

评论

发布
暂无评论
发现更多内容

百分点大数据技术团队:政务数据安全管理实践

百分点大数据团队

【案例】新基建下星环科技城轨智能视频分析系统建设

星环科技

立体水性石头拉浆

C13713145387

不反粘水性台板胶Waterborne table glue

C13713145387

不反粘水性台板胶

LiteOS内核源码分析:静态内存Static Memory

华为云开发者社区

内存管理 LiteOS 静态内存 Static Memory Membox

TcaplusDB五一假期返工通告

TcaplusDB

数据库 nosql TcaplusDB NoSQL数据库

Google官方关闭binary后,Android工程师怎么办?

Changing Lin

5月日更

爽面弹力胶浆、哑面弹力胶浆

C13713145387

爽面弹力胶浆

回顾 Alex Smola 讲述的“自动化机器学习(AutoML)”,本文带你了解 AutoGluon!

亚马逊云科技 (Amazon Web Services)

哑面爽滑肤感胶浆

C13713145387

哑面爽滑肤感胶浆

高并发之存储篇:关注下索引原理和优化吧!躲得过实践,躲不过面试官!

Coder的技术之路

数据库 高并发 索引结构 索引优化

流媒体:依托于声网的连麦解决方案

小岛上的黑桃六

架构 音视频 架构师 流媒体 声网

水性硅胶防滑透明浆

C13713145387

水性硅胶防滑透明浆

一文抽丝剥茧带你掌握复杂Gremlin查询的调试方法

华为云开发者社区

调试 图数据库 Gremlin 遍历源 图遍历

Flink on Zeppelin 系列之:Yarn Application 模式支持

Apache Flink

flink

高并发系列:存储优化之也许可能是史上最详尽的分库分表文章之一

Coder的技术之路

高并发 分库分表 高并发系统设计

弹力抗刮硅油布胶浆

C13713145387

弹力抗刮硅油布胶浆

夏季不塞网胶浆、夏季不堵网胶浆

C13713145387

夏季不塞网胶浆

架构实战营模块三作业

日照时间长

架构实战营

高并发系列:架构优化之从BAT实际案例看消息中间件的妙用

Coder的技术之路

高并发 高并发系统设计 消息队列 消息中间件

唯奋斗最青春 | Tcaplus祝大家五四青年节快乐!

TcaplusDB

数据库 nosql 分布式 TcaplusDB Tcaplus

哑面防水尼龙胶浆Nylon printing paste

C13713145387

哑面防水尼龙胶浆

INNOVATE 2021 圆满落幕,一起盘点那些 AI 前沿实例!

亚马逊云科技 (Amazon Web Services)

华云大咖说 | 安超DCM给数据中心“做主”

华云数据

牛仔底色保护浆(喷砂工艺)

C13713145387

牛仔底色保护浆

聊聊我的编程时如何入门的

C语言与CPP编程

c++ 编程 程序人生 C语言 数据结构与算法

负载均衡续:万亿流量场景下的负载均衡实践

Coder的技术之路

负载均衡 高并发 负载均衡架构 架构·

用机器学习操控无人驾驶小车,竟然和训练狗狗的原理一样!?

亚马逊云科技 (Amazon Web Services)

云图说|云数据库MySQL内核小版本升级全攻略

华为云开发者社区

MySQL 云数据库 内核 华为云数据库 小版本升级

【LeetCode】解码异或后的数组Java题解

HQ数字卡

算法 LeetCode 5月日更

一次过透气浆、印一次透气浆

C13713145387

透气胶浆 一次过透气浆

APPKIT打造稳定、灵活、高效的运营配置平台-InfoQ