美团App、大众点评App都是重运营的应用。对于App里运营资源、基础配置,须要根据城市、版本、平台、渠道等不一样的维度进行运营管理。如何在版本快速迭代过程当中,保持运营资源可以被高效、稳定和灵活地配置,是咱们团队面临的重大考验。在这种背景下,大众点评移动开发组必需要打造一个稳定、灵活、高效的运营配置平台。本文主要分享咱们在建设高效的运营配置平台过程当中,积累的一些经验,以及面临的挑战和思考。html
简单而言,运营资源能够理解为App中常常变更的一些广告、运营活动等等,譬以下图中电影首页顶部的Banner位,就是一个典型的运营资源。对于这类运营资源,它们有以下明显特征:算法
基础配置,常见的有入口资源的配置、网络的配置等。相对运营资源来讲,其变动的频繁度相对较低,与时间、城市的关系也没那么强。譬以下面大众点评App-个人页面里的入口。这类配置有以下几个特征:数据库
在从0到1打造运营配置平台的过程,咱们遇到了不少“坑”。特别是在早期“刀耕火种”的时代,对于入口的配置,每每是经过“hardcode(硬编码)”的方式写死在代码中。因此必然会遇到很大的问题,这主要体现为如下两方面:小程序
对于新的运营配置需求,研发同窗须要开发对应的配置页面,而后转给运营同窗进行配置的管理,最后运营人员对资源进行配置上线,其流程以下:后端
对于每一个运营配置需求都要通过需求评审、页面开发、配置管理、上线的流程。同时,对于配置页面的开发,少则须要1到2天的开发工时,研发成本高。问题总结以下:微信小程序
在早期,运营配置上线流程须要研发同窗参与。产品提出运营配置需求,研发同窗经过修改代码对配置进行变动,而后经过代码上线进行发布。总体流程以下:缓存
这种上线机制存在如下几个问题:安全
针对以上问题,咱们但愿经过设计一个通用的解决方案,去解决上文阐述的各类运营资源管理的问题。咱们把这个总体的项目称之为APPKIT,寓意是App的运营配置工具(Kit)。经过不断的实践和总结,咱们但愿能从三个维度解决上述问题:服务器
随着业务的不断迭代,不管采用怎样的数据字段组成,都没法知足业务变化的字段(这里是指像标题、副标题、图片、跳转连接等)要求。对底层数据进行JSON化,其对应的数据字段彻底可动态扩展,从而知足业务不断迭代的需求。JSON化随之也会带来运营位字段管理的问题,咱们经过字段管理的工具来解决这个问题。微信
设计一套总体的流程管理机制,解决运营的投放、审核、发布和回滚的问题。经过流程化的机制,咱们实现了“事前”、“事中”、“过后”的三级管理。
首先,在运营配置上线前,经过测试用户的预览功能,能够预览上线后的实时效果。同时,经过穿越功能可查看未来时段显示的效果。防止出现上线后连接出错、视觉效果达不到预期等问题。
其次,在流程阶段,引入审核机制,经过视觉和内容两方面的审核,保证投放数据的准确性。
最后,在运营配置上线后,若是发现问题,能够经过快速回滚,最大限度地实现“止损”。
对于运营数据,不管是经过数据库的落地方案、仍是经过分布式缓存的方案,都没法完全解决服务中心化和服务抖动的问题。经过接入的SDK化,能够作到数据的本地缓存更新机制,解除对中心化服务的依赖,大大提高服务的稳定性和性能。同时整个APPKIT服务变成可水平扩展,在扩展过程当中也不会影响中心服务的稳定性。
APPKIT运营配置系统总体框架以下(数据流向如箭头所示)。从功能角度,大致上分为四层:数据层、服务层、接入层和监控层。
数据层做为最底层的数据存储,其保存了最基本的运营后台数据、流程数据和线上数据。对持久化的数据,咱们采用MySQL进行存储;对于缓存数据,咱们采用了Redis的解决方案。这样数据层造成基本的两级存储结构:MySQL保证了数据的持久性,Redis保证了数据获取的速度。
这里咱们对底层数据划分为三个不一样域:后台数据,至关于草稿数据,运营人员全部的操做都记录在这里;流程数据,运营人员操做完成后,提供发布流程,预览及审核都在流程数据里进行;线上数据,审核经过后,数据同步到线上数据,最终C端用户获取到的数据都是来源于线上数据。
谈到数据层,这里咱们遇到了存储上的一个小问题。按城市运营的每条数据,都须要存储具体的城市ID列表,其在数据库里的存储为 “1,2,3,4...... ”这样字符串。而这种数据存储在业务请求和条件过滤过程当中,存在着以下两个问题:
美团、大众点评运营的城市成千上万,若是每条运营的投放数据都包含大量的城市列表信息,对机器内存势必产生必定消耗。
城市的过滤逻辑大致是这样:用户所在城市与从数据库获取到的城市列表(“1,2,3,4...... ”)进行匹配,在每次匹配过程当中都须要作字符串“split”的切割操做。这种操做的特色是流量越大,对机器CPU的消耗越大。
解决方案:基于以上两点考虑,再结合Java语言提供的BitSet机制。咱们从数据库里取出城市列表数据后只作一次“split”切割操做,将数据转化为BitSet类型。这样在实际过滤过程当中只须要经过BitSet的get机制就能够判断运营投放的城市是否包含了用户所在的城市。经过BitSet机制,咱们既解决了大数据存储对内存的消耗问题,又解决了城市过滤的性能问题。
服务层向下对底层数据进行操做;向上为接入层获取数据提供接入能力。其提供四个服务能力:运营后台、开放平台、数据服务、APPKIT-SDK,以下表所列:
接入层主要为运营人员、业务研发提供接入能力。经过运营流程化为事前、事中、过后提供保障。一个运营资源从制做到最后在C端展现,须要通过运营人员的投放、测试预览、审核及发布的中间流程。这里对于一些敏感的运营资源,须要经过安所有门的审查。安全审查主要涉及到敏感词的处理、敏感图片的检测等。对运营配置平台来讲,它彻底是一个“黑盒模型”。这里主要涉及到两种状况:
APPKIT-SDK运行在业务机器上,这里就涉及到多台机器的数据一致性问题。同时,随着业务接入运营数据的增多,SDK对机器内存势必有必定消耗。基于服务的稳定性考虑,咱们对SDK运行时的投放内容进行监控,其主要监控两个指标:运营位数及每一个运营位的配置总数。这样作能够带来如下几个好处:
同时,对于非SDK的其余性能指标,咱们采用统一的监控平台--CAT进行监控,其中包括:APPKIT中心服务的调用QPS,机器的性能,网络流量等通用指标。
数据模型每每与业务相关。业务越复杂,设计须要越简单,这样方能知足复杂业务的各类变化。由于数据模型太过于抽象,若是直接进行述说会有些乏味,咱们能够先从一个具体的业务实例入手。下面是大众点评App顶部金刚位的截图,对于这部分数据,如何作到运营可配?
首先,咱们对运营数据作需求拆解。对于这块数据,每一个 “节点”(对应每一个位置:如美食,技术上咱们称之为 “节点”),其基本的运营诉求以下:
上面这个运营场景算是很是经典、复杂的一个运营场景了,若是这个问题解决了,其余问题天然就会迎刃而解。
咱们作一下进一步的技术分析:
首先,这里有节点,每一个节点(Node)有其相应的内容(Content),节点与内容是“一对多”的关系。这里的内容,咱们指的是如标题、图片、跳转连接等信息,虽然是“一对多”的关系,但最后在同一个城市、同一个版本下(可选择)只显示一条内容。为何有这样的需求?举一个简单的业务场景实例,之外卖为例,在新版本10.0的时候作了一个全新的外卖频道页面,其连接信息与老版本的彻底不一样,这里咱们就须要按版本的不一样配置两条不一样的内容信息。
其次,节点与节点之间有两层关系,其一为“平级关系”,如美食与外卖的关系,这种关系就是一种简单的列表关系;其二为树关系(Tree),如外卖与下午茶之间的关系。这里咱们将角标(下午茶)视为一个节点,由于角标也须要按不一样维度进行过滤,所以下午茶成了外卖的子节点。其实这里有一些特殊的地方,若是角标不须要按城市、版本等维度进行运营,那很简单它就是一个内容信息(相似标题)。
最后,咱们谈一谈排序问题,对于这么多品类,如何排序,他们的优先级是什么?咱们须要定一个基本的基调,每一个节点都有一个基本的排序值(优先级)。但深刻业务分析,对于不一样的人(群),每一个人关注的点不同,须要一个“千人千面”的算法,来决定每一个人所看到的内容是其真正关心的内容。因此,这种应用场景下的排序应该经过机器学习算法而获得。
针对上面的技术分析,咱们提出了一种节点(Node)-内容(Content)-树(Tree)模型,简称为N-C-T模型。以下图所示:左边为抽象的数据模型,右边为以上实例的实现。
N-C-T数据模型设计的很是简单,其中C和T部分都是可选择的,这样使得其灵活性比较强,能够应对业务变化的大部分需求。注意,这里咱们只是对业务需求的宏观表现形式进行建模,对于具体Node和Content里的有哪些字段(标题、副标题、图片、跳转连接),这些都是JSON化的存储格式,能够知足任意字段的扩展。
经过以上经典实例,咱们能够很容易经过咱们的数据模型解决这个问题。咱们再回到文章最开头的背景章节的运营场景,Banner位,以下:
这种Banner位,套用咱们上的数据模型,它实际上是一种只有一个Node节点、多个Content节点的模型。这也是一种典型的应用场景,为此咱们总结了两种应用场景。
其实,大部运营场景均可以套用以上两种经典的运营组合。
将运营资源的管理进行流程化,具备如下几个好处:
对于流程化的实现,咱们是将数据域切分红三个不一样的部分:后台数据、流程数据和线上数据,以下图所示:
后台数据:咱们能够简单理解为草稿数据,这里的数据多用户可同时进行操做,也不会对线上数据有影响。
流程数据:当用户后台数据编辑完成后,对数据提交一个发布流程,数据进入流程数据区域;这时可对数据进行测试预览、审核等操做。
线上数据:这块数据是C端用户真正获取到的数据,当流程数据审核经过后,数据会自动同步到线上数据域,完成上线操做。
整个上线流程以下:
为了能平稳上线,咱们设计了一个测试预览功能。当数据处于流程中时,用户能够经过扫描二维码加入到测试用户名单,可对处于审核流程中的数据进行预览,用美团、大众点评App查看上线后实时效果,其实现的数据流以下:
稳定性是一个运营配置平台最重要的能力,没有稳定性,其余任何功能都会失去实际意义。运营系统的稳定性经历了不一样的迭代时期,总结起来,可归纳为如下三个阶段:
这是APPKIT最先期的经典方案,它的实现也很是简单,以下图所示:
C端用户经过业务接入层获取数据,业务接入层经过服务调用获取配置后台数据(APPKIT服务),配置后台数据服务读取缓存数据。若是缓存数据不存在,则从数据库中读取数据,同时将数据库数据同步到Redis缓存中。这是经典的数据获取模型,但它有如下几个缺点:
针对以上经典方案的缺点,咱们作了进一步的改进,对配置后台数据服务作了一层本地内存缓存,以下图所示:
样作能够解决数据调用的部分网络时延问题,同时Redis缓存的抖动也不会影响总体服务的性能。不过,这个方案也有其自身的缺陷。
为完全解决缓存方案的问题,尤为是服务中心化带来的流量、容量等问题,咱们将运营数据的获取、Web缓存的管理集成进SDK。以下图所示:
不过,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、H五、微信小程序)能力,正在构建移动化的运营能力。这样保障用户不管在什么办公环境都能进行运营配置的管理。
国宝,美团点评移动运营平台负责人,Java后端架构师,APPKIT项目发起人,负责APPKIT项目的架构设计。专一于高性能、高稳定、大并发系统的设计与应用。
小龙,目前为APPKIT项目负责人,主要负责APPKIT项目开发、技术对接和实施、开放平台等。专一于先后端全栈技术开发,喜欢挑战新的技术和业务问题。