本文首发网易有数公众号:网易云音乐数据服务之路
数据服务作为统一数据中台建设的最上层,能够将数据仓库数据以服务化、接口化的方式提供给数据使用方,屏蔽底层数据存储、计算的诸多细节,简化和加强数据的使用;同时避免烟囱式建设、加强数据API的开发和交付效率,提升数据利用率。网易云音乐数据团队与网易有数进行了数据服务平台共建,并基于实际场景从无到有落地了数据服务在云音乐的使用,本文主要对共建进程及数据服务使用情况进行介绍。
如前所述,数据服务旨在提供全面的数据服务及数据共享能力,能够作为数据仓库的统一出口,处于数据中台的最上层,对外提供统一数据服务,其位置如图。
从图可以看出,日志、业务数据等通过DataStream、NDC等平台同步、再经过实时离线等计算平台进行处理后落地成数据仓库的各层数据模型,同时借助于数据地图、元数据中心、数据质量中心等等数据中台套件对数据进行管理和校验等、使之成为资产。数据仓库的数据借助于数据传输,可以将数据从Hive离线数仓同步到HBase、Redis、DDB等在线存储中,数据服务即将数据从在线存储中读取的API服务,上层的数据产品、数据报表甚至于线上业务等都可以读取这些方便快捷地读取这些接口。
数据服务开发平台是一个集成了服务API开发、测试、部署、调用等一站型服务平台,能够非常便捷地基于在线存储快速生成数据服务API的平台。目前已集成到网易有数大数据开发套件中,平台如下:
平台用户分为服务调用者和服务创建者两个角色。
调用者即要通过服务接口消费数据的人,在音乐可能为各业务方的服务端、前端、算法等技术同学,平台支持调用者通过API集市找到需要调用的API,同时可以根据API的详情来查看API的调用方式、输入输出并申请调用权限。
服务的创建者即提供数据的人,在音乐即为数据开发,数据服务平台通过平台化的方式赋予数据开发一站式快速开发数据API的能力,包括API的创建、测试、一键发布等。之前数据开发要提供一个数据API需要写Java代码,然后申请机器、应用部署等一系列流程,目前只需要通过数据传输将数仓Hive数据同步到HBase、Redis、MySQL等在线存储中,然后在平台上以配置化或者简单SQL的方式即可快速生成一个API,同时绑定相应的资源组即可实现测试和快速发布。熟悉后整个流程可以到分钟级。平台也提供了报警监控功能,服务的创建者可以配置相关的报警信息,在已发布的API详情中看到API调用情况,如果调用有错误会受到报警信息。
下面详细介绍平台的共建进程及如何在云音乐得到落地使用。
我们是从20年Q4开始与网易有数大数据平台团队开始确定共建项目及规划到云音乐的落地使用,此时平台已经有了V1版本,以开源Kong网关的方式提供API的创建、测试、发布功能,这些功能后端都由管理服务来承载,管理服务功能如下:
v1版本管理服务提供了数据源管理、API管理、应用授权管理等基本核心功能,同时服务治理、监控统计报警等依赖于kong网关。
在平台上创建好的API调用者即可以通过kong网关对应的域名进行http调用,API发布后和调用时跟平台已无关系,已经注册到了Kong网关上,服务调用的数据流如图
v1版本查询调用时所有API走同一个Kong网关,由Kong网关来分发到后端的查询服务。由于Kong网关是开源的,团队目前只是限于使用,对于线上运维等并无较好经验且云音乐后端线上都使用的是自研的batch网关,由此Q4我们将Kong网关作为了数据报表、数据产品、运营系统数据使用等内部使用场景的网关,且这些内部场景API混布于一个资源组中,来较好地利用资源,主要落地数据报表、产品等低调用量的内部系统来前期落地。
这一阶段在使用时发现平台的v1版本功能无法满足一些使用场景,因此Q4我们主要围绕平台的功能性做了几个大的迭代,大大提升了平台的易用性,主要有以下几点:
数据服务平台除了管理员之外,用户应该有两个角色,一个是主要由数据开发担任的服务创建者,在平台上进行API的创建并发布,另一个角色是服务调用者,能够在平台上浏览检索有哪些API,能够看到API的调用方式、入参出参,申请调用权限等。API集市即为API的地图,能够提供给服务调用者去检索和查看已发布的所有API,并申请调用权限。
平台提供了数据源管理功能,并以jdbc的方式支持了ClickHouse、Druid、Kylin、ES等诸多OLAP数据源,能够支持一些OLAP场景的API调用;
这些数据源跟元数据中心打通,能够跟数据传输模块共用一套元数据,同时数据源绑定了已发布的API时,不允许再对其进行修改。由于我们将数据源进行了充分的抽象,添加JDBC类型的新数据源在代码中只需要配置即可得到,非JDBC类型的实现接口的相关方法即可。
平台支持了自定义入参转换和返回结果转换等功能。
平台将API输入参数分为普通入参和函数入参,普通入参即基本数值、字符串、布尔类型的参数,由调用者自己传入,函数入参对普通入参进行了处理和转换,API创建者能够通过自定义Java代码的方式对普通入参进行转换来生成函数入参,从而能够进行复杂的和自定义的参数转换,函数入参对调用者不可见,由创建者自己来封装和转换底层取数逻辑,屏蔽了底层细节。如图:
此函数入参能够将id转成对应底层存储HBase表的rowkey,调用者只需要传入id即可,无需自己拼接rowkey,屏蔽了存储细节,调用者无需感知底层存储是用的HBase还是其他,函数入参只有创建者才可见。
实现上来讲,函数入参通过codegen+动态编译+反射的技术生成反射的实体对象放置于内存中,在实际调用的时候普通入参实际调用的值作为invoke方法的args传入来获取真实函数入参的结果。
平台对所有类型数据源生成的API统一了返回格式,但有些场景下需要将API转成自己需要的格式,平台提供了udf的功能,通过实现相关接口并打包上传注册的方式来达到这样的目的。
实现上来讲也是通过JAR包管理,然后异步执行下载JAR包、加载类、反射生成udf实现类。调用的时候直接获取即可。
平台还支持了条件SQL,通过引入MyBatis相关的包,能够支持类似MyBatis动态SQL方式根据入参刻画条件SQL,从而大大提升了通过SQL生成API的能力。
一阶段结果:通过以上一阶段的平台迭代,随着功能的提升较好地支撑了数据服务在云音乐内部数据场景的建设,支撑了丰收项目、muse、歌曲profile、日志查询服务等一些数据产品、系统的使用,共建设30+接口、10余个调用者。这些API混合部署于一套资源组中并对接Kong网关。
从今年Q1开始,数据服务开始探索接入线上场景。跟内部场景不同,云音乐线上服务API要支持高并发低延时,服务要直接供给后端算法等C端应用调用,整个技术栈也要跟云音乐后端架构相融合。此外,线上服务对稳定性也有较高要求,服务治理、监控报警、日常巡检回归等都要接入进来。由此,Q1我们围绕接入音乐RPC框架以及服务稳定性提升做了许多工作,以支持用户画像线上服务的落地。
之前查询服务还是单网关架构,使用的都是开源Kong网关,为了支持多种类型的HTTP网关以及RPC等,剥离了核心facade层充当门面,上层Ingress层可直接对接各类HTTP网关的controller以及RPC协议,架构如下:
上层的Ingress层可支持各类网关、RPC,跟核心服务层解耦。如要支持Dubbo也只需要新开发一个Ingress即可。服务facade层支持springboot cache作为缓存,能够对单个API进行缓存配置。
下层QueryService层插件化,支持各类数据源的查询。对数据源类型分为支持向导模式(如Redis、HBase等KV类型)及SQL模式(如MySQL、ClickHouse、Kylin)等通过JDBC的方式去调用。
一个API请求进来的时候,查询服务依赖管理服务去获取API的元数据信息以及API对应的数据源元数据信息,这些都在管理服务统一封装并提供服务,查询服务只要依赖管理服务即可,而无需去关心API、数据源的元数据具体的存储细节。目前管理服务不只服务于云音乐,并且内部API元数据等存储于RDS、依赖于元数据服务,在线上服务高并发场景下若查询服务每次请求都去访问管理服务则一方面rt会有显著增加、另一方面管理服务也非高可用。考虑到API的信息一旦发布后基本是不可变的,只会增加API与调用方的绑定关系等,基于此,通过异步线程定时去管理服务获取API及数据源信息 并作compareAndSet操作,在内存中维护API的元数据信息即可。其整个架构如下:
这样查询服务对管理服务是弱依赖,即使管理服务挂掉,对线上运行中的API亦没有影响,只会影响新API的发布。
在一阶段所有内部应用都是部署在Kong网关上,而线上服务以云音乐RPC的方式提供,我们在代码层通过不同的Ingress来支持了不同网关或RPC通信,复用一套核心service。同时在部署层面,API是要绑定到资源组的,一个资源组对应后端一个集群。由此,为线上服务申请了独立的集群和机器,整个API独享单独的资源组即集群。同时,在存储层也做了隔离。用户画像线上服务用的冷热存储,即HBase+Redis两级存储,HBase的写入读取IO没有隔离,一个表的写入可能会影响其余表的读取造成抖动。基于此,我们也为用户画像线上服务申请了专门的HBase画像集群,之前的内部Kong网关应用使用东冠的公用集群。
作为只给音乐内部调用的线上服务,我们将数据服务充分与云音乐现有的后端技术栈相融合。对于服务的治理、报警监控、日志查询等,Kong网关有自己的一套模式且已经可以在平台上进行配置,但不适用于线上服务。在这一阶段,我们主要还是在平台的后方接入Mlog、云音乐统一治理平台、报警平台等,即只有我们自己知道线上的这一RPC接口接入了这些稳定性保障工具,平台上是看不出来的。同时我们也应用了GOAPI作为巡检与线上回归、应用了NPT压测平台改进rt,但这些也都是在后方进行的操作。从平台的角度来讲,这些稳定性工具没有嵌入到数据服务平台上,即我们开发部署线上数据服务应用到了平台的能力,但在相应的线上运维工具上并没有。这也是我们下一阶段要做的事情,将这些线上运维工具引入平台并进行整合,使得不太熟悉线上服务保障机制和工具的数据同学也能运用平台进行线上数据服务的开发和保证稳定性。
二阶段结果:经过上述一系列的稳定性整改,Q1支持了用户画像线上服务的落地,画像服务是一个通用型的底层RPC服务接口,能通过用户id和标签列表两个参数来获取用户的标签数据,标签范围可以很广泛,如听歌次数、歌曲风格等用户行为统计型标签;融合年龄、性别等算法模型标签;事实型标签等。总之,可以作为数据仓库中用户数据的统一出口, 使用方相比于之前通过读取数据开发离线写入DDB、消费消息队列等数据交付方式 在开发效率上能够大大提升,无需再管理数据的存储。目前用户画像数据服务接口已服务于会员活动实验、云音乐8周年活动、推荐高校歌单等三个场景,巅峰时QPS达到8000~9000,平均rt稳定在3ms内。
经过两个季度的迭代和落地真实场景尤其是线上场景,目前平台和更多通用服务建设都在规划和进行中,主要包括:
建设歌曲画像、艺人画像等更多通用数据服务,接入更多的数据使用场景;
支持API多版本、已发布状态的API在线滚动发布;
平台统一多网关、多协议(HTTP、RPC)的服务治理、监控报警配置,监控粒度细化到调用方;
函数studio建设、在线udf编辑、调试、保存;
拥抱云原生,资源云化。
希望通过上述的工作能够使平台在功能性和稳定性上继续增强,同时统一数据出口,将数据服务作为音乐标准化的数据交付方式。
作者简介
刘源,网易云音乐资深数据开发工程师。主要参与过云音乐用户行为分析、实时计算平台、数据服务等系统的设计与开发工作。目前专注于数据服务的建设及在云音乐的落地。