爱奇艺海外 App 是一个重运营的应用。对于 App 里的顶导航、我的页面、弹窗等,需要根据模式、版本、平台、语言、渠道等不同的维度进行运营管理。随着业务快速发展,版本快速迭代,如何保持运营资源能够被高效、稳定和灵活地配置,如何高效稳定的为新的运营需求提供支持,是我们需要解决的问题。
在这种背景下,爱奇艺海外 Phone 后端研发组通过打造一个稳定、灵活、高效的运营配置平台来解决前面遇到的问题。本文主要分享我们在建设高效的运营配置平台过程中积累的一些经验以及面临的挑战和思考。
运营类配置可以分为两块,运营资源和基础数据的配置。
简单而言,运营资源可以理解为 App 中经常变动的一些广告、运营活动等。比如上图中弹窗广告,就是一个典型的运营资源。对于这类运营资源,它们一般有如下特征:
时效性强:只在一定时间范围内显示在 C 端固定位置。
模式强相关:每个活动、广告都只会出现在固定的某些模式。
数据变动频繁:特别是活动类数据,展示的图片文案等变动较为频繁。
支持多语言展示:基于爱奇艺海外站面向全球用户的情况,不同模式下需要展示不同的语言文案。
基础数据配置相对于运营资源来说其变更的频率相对较低,与时间、版本的关系也没那么强。譬如下面爱奇艺海外 App-底部导航栏(样式如上图所示)。这类配置有如下几个特征:
多维度:需要针对不同的模式、语言做不同的配置。
长期有效:这种类型的配置一般长期存在,过期场景较少。
面对接二连三的运营配置需求,我们最初通过实现不同的配置界面来对接各类运营产品需求。但这必然会遇到很大的问题,这主要体现为以下方面:
运营效率低
对于新的运营配置需求,研发同学需要开发对应的配置页面,然后转给运营同学进行配置的管理,最后运营人员对资源进行配置上线,其流程图如下:
对于每个运营配置需求都要经过需求评审、页面开发、配置管理、上线的流程。同时,对于配置页面的开发,少则需要 1 到 2 天的开发工时,研发成本高。问题总结如下:
1. 研发成本高,每个需求要开发新的配置管理页面。
2. 研发周期长,运营效率低,从需求的提出到运营上线周期长。
3. 灵活性差,对不同的运营维度(模式、版本、时间等)都需要事先确定好,无法动态调整。
重复开发工作多
对于通用型的运营配置后台,某些特有的功能特别对于前后端来说重复开发工作明显。如操作记录,审核机制,根据不同的模式版本语言过滤数据等功能,在每次出现的配置需求中都需要重复的开发。
针对以上问题,我们希望通过设计一个通用的解决方案,去解决上文阐述的各种运营资源管理的问题。我们把这个项目称为 IQ 运营位。
通过调研我们确认项目设计的原则主要有以下三个:
通过不断的实践和总结,我们希望能从以下三个方面实现上述原则:
随着业务的不断迭代,无论采用怎样的数据字段组成,都很难满足业务变化的字段(这里是指像标题、副标题、图片、跳转链接等)要求。对底层数据进行 JSON 化,其对应的数据字段即可实现可动态扩展,从而满足业务不断迭代的需求。JSON 化随之也会带来运营位字段管理的问题,我们通过在运营后台提供了相应的字段管理功能来解决这个问题。
通过持久化存储,分布式缓存,以及接入业务方的本地缓存,运营数据的多方存储,保证极端情况下都有降级数据获取,降低系统异常的损失。
对于运营数据,无论是通过数据库的落地方案、还是通过分布式缓存的方案,都无法彻底解决服务中心化和服务抖动的问题。通过接入的 SDK 化,可以做到数据的本地缓存更新机制,解除对中心化服务的依赖,大大提升服务的稳定性和性能。同时整个 IQ 运营位服务变成可水平扩展,在扩展过程中也不会影响中心服务的稳定性。调用方请求流程图如下:
IQ 运营位配置系统整体框架图。从功能角度,大体上分为四层:数据层、服务层、接入层和监控层。IQ 运营位架构图如下:
数据层主要是存储接入 IQ 运营位的各类运营数据。数据层主要面临以下难点。难点 1,数据量大;难点 2,QPS 高。基于以上两大难点,我们通过 redis 集群做中间缓存,通过 SDK 使各业务方接入本地缓存、通过消息监听异步更新的方式来解决中心服务的流量压力。
服务层向下对底层数据进行操作;向上为接入层获取数据提供接入能力。其提供四个服务能力:运营后台、开放平台、数据服务、IQKIT-SDK。
其中运营后台主要面向运营人员和产品,提供数据的配置后台。
开放平台收归于开发技术人员,提供一个增加运营位配置的后台。
数据服务主要是为调用数据的开发提供一个统一的、高可用的、高性能的 api 接口。
SDK 为数据服务服务。主要目前是简化开发人员的接入成本,提供数据服务性能和可用性。
C 端接入如何更方便?
为了简化开发人员的接入成本,调用逻辑在 SDK 内实现,用户只需要引入 maven 包,注入 OppkitClient,封装 OppkitRequest,通过 OppkitClient 直接调用即可返回过滤并且翻译后的数据。
B 端配置如何更便捷?
在设计项目的时候后台配置秉持的原则有且只有一个:一切皆可配置。通过开放后台来配置 IQ 运营位,每个 IQ 运营位相当于一个业务形态,比如导航栏,而运营位内包含多个数据,比如 title,link 等,而 title 包含多种语言,需要配置多语言 key。开放平台的作用就是创建 IQ 运营位,为 IQ 运营位配置字段。运营后台则用于配置开放平台创建的 IQ 运营位数据。
除了数据存储层的监控以及烽火台对数据层与服务层的监控外,我们还对 SDK 内实现的本地缓存进行了监控。
C 端的接入即数据的获取在 SDK 内部实现,SDK 内部我们做了以下功能:
1. 如果请求包含某些特定离散字段如设备 id,因为包含的数据量极大,存入本地缓存会给业务方的机器内存带来很大压力,则避开缓存直接请求服务。
2. 为了满足数据实时性要求较高的业务方,新增不接入本地缓存的逻辑。
3. 如果只包含某些聚合度高的字段如平台字段,版本,模式,语言等,则把请求的数据存入本地缓存。本地缓存通过监听运营平台的方式进行异步更新,当异步更新获取数据失败,则保持之前的数据返回,避免极端情况运营数据全部为空,将业务损失降至最低。
4. SDK 内部通过异步线程,将本地缓存的使用情况通过定时线程存入,通过后台界面展示各缓存使用情况,对各类缓存的使用情况实时监控。
如上文所说在运营后台的设计考虑中,我们秉持了以下几个原则:
下面我们介绍下运营后台稳定性与性能保障所作出的解决方案。
整体请求流程图如下:
作为各类运营数据配置的运营后台,稳定性尤为重要。
除了在操作机制上即运营流程化数据配置机制、多级数据存储使用分布式缓存以及分布式数据库以外,我们还提供了一个 SDK 方案来对服务的故障进行降级。下面我们将详细介绍该方案的落地过程。
SDK 本地缓存方案
我们考虑到在实现本地缓存,有这样几个好处:
1. 缓解中心服务的流量压力,更多的流量将会请求到本地服务的内存中。
2. 基于爱奇艺海外站业务的特点,国外网络环境不可预测,环境差等情况,尽可能的减少网络请求链路。
3. 一旦中心服务故障,周知各业务方不要重新部署,以本地缓存实现数据降级。
但是本地缓存的方案缺点也非常明显,即一旦有运营后台数据更新,各业务方无法实时获取到最新的数据。基于此,我们对 SDK 进行了以下几个版本迭代工作。具体见下图:
技术架构演进到第三版,可以较好的解决中心服务流量问题,使得运营后台的流量由用户请求量决定改为后台的数据更新频率决定,从而解决流量过载问题。但是该版实现也需要解决以下几个难点:
1. 各业务方本地缓存的使用情况种类繁多,如何进行提供系统监控?
2. MQ 的方案该如何设计?
针对问题 1,我们在 SDK 内部实现一套这样的机制,通过 scheduledexecutorservice 定时任务,周期性的将缓存使用情况拉取到库内,这样在通过后台界面就可以根据时间展示本地缓存的使用情况。这样,可以系统的掌握各个不同的业务方缓存的使用情况,供业务方的内存申请和分配提供数据支撑。
针对问题 2,涉及到的难点主要有两个:
(1)业务服务机器一般都是一个服务有多台机器,所以一个消息的更新需要被多台部署相同代码的服务器同时消费,这样确保每台机器都获取到最新的数据。
(2)运营位有多个,但对于业务方来说没有必要在没有接入的运营位更新数据时去异步地请求运营后台中心服务更新数据(因为这些数据这个业务方压根没接入)。
针对(1),明确的是消息的生产者是运营后台服务,而一个消息需要被所有业务方监听,具体的说是所有业务方的每台机器。所以,每台机器应该属于不同的消费组。所以我们需要找到一个每台机器都不一样的标识节点,以这个节点做为消费组。显然,这个节点最好的就是机器地址,可以保证每台机器所在分组都不一样。
针对(2),我们提供一个配置文件,各业务方需要在配置文件内写入各自业务方使用的 IQ 运营位名称,当一个消息来临时,首先需要判断这个消息中的运营位名称是否包含在配置文件内,如果不在,则这条消息被忽略(空消费),如果在,则请求响应的运营位更新本地数据。
以上的 SDK 提供的本地缓存可以提高后端服务的性能,除此以外,我们还做了其他一些工作。
在运营位的实践配置中我们发现,运营数据的变化或者说运营人员更改运营数据的情形相比网络请求来说是非常低频的,比如之前分析的基础运营数据。因此,数据缓存在客户端可以避免客户端与后端服务的网络消耗,极大的提高性能。
我们的方案是为每个运营位数据提供一个版本的概念。通过保存各运营位的操作最新时间,在客户端开屏时发起一次请求,将所有的运营位最近的数据更新时间返回给客户端,客户端将该时间戳缓存在本地,当下次开屏请求时,同样会获取到服务端返回的运营位最近更新时间戳,将本地的与服务的进行匹配,来确认是否去更新各个运营位的数据,如果客户端缓存的运营数据时间与运营后台返回一致,则直接展示缓存在客户端的数据。
这种方案的另一个好处是可以在极端的情况下,如对外暴露的 api 出现故障,通过禁止运营后台的数据更新,可以使业务数据正常展示,避免出现运营数据消失的严重故障。
具体的请求流程图如下:
本文主要介绍了 IQ 运营位的设计与开发的相关内容,首先根据遇到的痛点提出了运营后台的设计原则:一切数据皆可配置,运营数据高可用,接口性能高效。针对提出的原则去思考与实现具体的技术方案。
通过配置数据的 Json 化实现业务字段的可扩展性。通过设计的数据模型来介绍满足多语言情况下的各类运营配置数据方法。通过提供 SDK 内部实现本地缓存,MQ 监听,异步更新的机制解决了服务中心化的大流量问题和缓存导致的数据不一致问题。针对海外的具体情况,提出了客户端缓存的相关方案。
IQ 运营位从今年 5 月开始规划,历时近半年时间,由于中途穿插了很多的产品需求,所以在自身使用与用户反馈两个渠道进行问题收集,前后共经过了两个版本的迭代。目前在运营后台的界面与使用便利度上在持续优化。
IQ 运营位上线 2 个多月以来在爱奇艺海外站得到广泛使用,在工程效率上更是有质的提高,拿最近的错误码配置来举例,错误码需要给客户端返回各类错误码以及对应的相关文案,文案是多语言场景的,通过 IQ 运营位配置化实现,只需要在分析需求,拆分业务字段和数据露出的条件后,5min 以内就可以给出相应的运营后台。
当然,随着业务的迭代与场景更新,IQ 运营位仍存在一些不完善的地方,在未来我们将会在工程实践中的持续迭代过程中做更进一步的工作,解决各类问题,更好的服务好 IQ 运营位的客户与广大爱奇艺海外用户。
团队介绍:
爱奇艺海外 phone 后端团队:爱奇艺海外事业部下,负责爱奇艺海外 phone 后端服务的开发和维护,为广大用户提供稳定、高效、流畅的视频内容服务。
正飞:IQ 运营位项目负责人,IQ 运营位的设计与开发者。
本文转载自:爱奇艺技术产品团队(ID:iQIYI-TP)
领取专属 10元无门槛券
私享最新 技术干货