本文由【友盟+】技术专家马巍源、张永峰共同撰稿
随着移动互联网和大数据技术的发展,智能手机的普及,几乎全部工做、学习、生活中的全部场景都离不开手机,手机 APP 已经取代了传统的生活方式,让人们能够体验便捷高效的服务,固然它也承载着大量丰富的信息,收集这些 APP 的数据,集中对数据进行清洗和分析,就能将这些海量数据变为有价值的数据能源。数据采集是开发数据能源的第一步,如何采集数据,什么样的技术架构可以支持海量数据的采集、甄别和传输,这是本文须要讨论的问题。缓存
与 PC 端不一样,对于手机、iPad、智能手表、电视盒子等移动设备,咱们触达它们的载体就是 APP。原生 SDK 在多语言上支持上须要投入不少的开发资源,跨平台应用开发渐成趋势,但 JS SDK 在各框架上的实现也各有差别,所以,目前移动采集 SDK 在对多平台、多语言的支持上难度较大。 安全
难度更大的是对 Android 设备的机型适配问题。因为 Android 系统的开源特性,各厂商为了在各家机型上有更好的用户体验,都有针对性的作了 ROM 改良,尤为近些年 Android 在虚拟机、编译器上的改动较大,这就给机型适配带来更大的难度。为了避免给 APP 带来卡顿、闪退、黑屏、崩溃、加载速度慢等差的体验,还须要支持开发者各类异常方式的接口调用,须要有极强的容错性。服务器
移动端的流量在持续的增加,【友盟+】在移动端覆盖的 APP 超过 135 万款,覆盖全球移动设备日活跃数超过 14 亿个,天天处理的数据量达 280 亿,庞大的数据天天都在考验着咱们的采集 SDK 和服务端的承载能力,【友盟+】在移动端采集技术上不断更新迭代,持续多年保持市场覆盖领先的地位。网络
咱们最初 SDK 的设计思想是简单高效,所以在 SDK 端没有任何对数据预处理的逻辑,甚至缓存策略也很是简单,全部实时产生的数据都会实时上报服务器。但随着移动端流量的暴涨,这种高并发的请求对服务器带来很大的压力。下图是 1.0 版本的通讯协议。架构
因而考虑经过控制发送频率来减少并发,开发者能够根据业务须要采用不一样的发送策略:启动、间隔、退出发送,而且在【友盟+】平台可随时变动。虽然有效减少了服务端的压力,但又带来了另外一个问题,单条数据的包体大小有可能超过 request-body 的上限,致使请求超时。而且流量压力一样是须要亟待解决的问题,因而,在 2.0 版本上咱们对数据进行了压缩,并增长了安全机制。服务端增长了数据预处理的逻辑,完善了对数据的校验。并发
只能单向通讯的协议是不灵活的,有不少时候咱们须要 SDK 的行为进行一些控制,好比发送策略的修改、屏蔽错误埋点数据,或者发现数据被污染决定抛弃,这些操做服务器须要通知到 SDK,而且在没有长链接的状况下该怎么作。在 3.0 版本上咱们把 http 请求的 response 的信息包体设计控制语义,SDK 除了从 response 得到服务器的接收状态,同时能够得到服务器的控制指令,从而实现服务器想要获得的效果。框架
若是每一条 Log 都必须等待并解析服务器返回的控制信息,显然服务器对数据处理的时效性和并发处理能力会大大折损,而且有些业务数据其实无需解析并执行这些控制信息。所以,咱们对业务数据进行了精细的分解,一些业务数据使用双向通讯协议,可以解析并执行控制指令,其他的业务数据属于状态无关数据,仍然使用单向通讯协议。异步
那么将来其实还能够将控制协议与业务传输协议分离,各自使用不一样的发送频率,但又能保证全部业务数据是受服务器指令控制的。高并发
移动数据采集 SDK 架构主要由三部分组成:用户接口、业务模块和控制模块。组件化
咱们能够从几个场景的时序图来解析这几个模块的工做原理。
用户启动 App 的时候,实际上是触发了开发者调用的初始化接口,Service Moudle 和 Control Moudle 会异步的进行一些初始化的操做:建立 Session、加载设备信息等。
当用户在 APP 中有点击、滑动屏幕的行为,会触发开发者在 APP 中预设置埋点事件。
Servie Moudle 会生成相应的事件数据,调用 Control Moudle 的接口检查发送策略和安全策略,以后 Servie Moudle 会将事件数据放到缓存队里中待发送。
不管用户退出 APP 后,SDK 还会在短暂的瞬间完成不少操做:结束 Session、持久化保存数据,在 iOS 中还会直接完成数据封装、打包、上报的工做。
咱们提供的产品功能愈来愈多,业务场景愈来愈复杂,为了知足各类各样的解决方案的需求,SDK 须要为各个业务场景维护多个分支、多个版本,开发资源浪费、版本迭代周期拉长,为了解决这个问题,咱们必需要设计一个灵活的架构,使每一个产品功能变成可自由组合、拆卸的组件。
组件化将统一约定 package 和 public API 的文件规范。针对当前【友盟+】业务的需求,创建标准的 SDK 产品公共库(如:network,serialize,configure,cache 等),组件化结构分为两部分,Common 将做为一个独立的 library package,而 Component 中每一个产品做为独立 library。
其结构以下:
组件的划分的颗粒度,能够根据业务需求,咱们的设计是根据产品,或者业务来划分组件。一个产品可能包含不少功能,好比统计产品包含事件数据采集、错误数据采集、A/B Test 等功能,Push 产品包含消息推送和应用内消息,在某些场景下,可能有些开发者会只使用部分功能,好比,只用错误分析功能和 Push 的消息推送,那么组件颗粒细化到功能层,就会更加灵活,可知足更多场景的需求,而且体积的减少是对开发者来讲是很是有吸引力的。
组件化的架构改变了之前业务逻辑与基础功能深度耦合的情况,业务开发人员能够专一于业务逻辑的实现,而不须要考虑如网络通讯、消息队列管理、设备信息采集等基础功能的实现。业务逻辑代码的任何改动,不会影响基础功能逻辑,增强了代码的健壮性,同时在回归测试周期上也大大缩短。
【友盟+】数据采集技术将持续的适应业务场景的变化,将来咱们的目标是让咱们的 SDK 更加智能,更加安全,让企业及开发者集成更加简单、数据更加精准。