查看原文
其他

用户行为数据收集系统--(2)客户端SDK设计

金麟 大数据与人工智能 2019-10-31
点击标题下「蓝色微信名」可快速关注


导Lead语导语:今天是春节假期的第五天,相信大家都在家里和家人一起过年吧,在这里笔者祝大家新年快乐,万事如意,红包满满。本人也在家里过年,本想偷个懒,停更一周,但是转念一想,放假了仍在学习的人应该大有人在,我要对得起这些勤奋学习的读者呀,所以春节期间依旧按照进度更新,和大家一同学习进步。

上篇文章《互联网从业人必须知道的「用户行为数据收集系统」》,我们讲解了用户行为数据收集系统的整体架构设计,主要围绕整体架构中需要实现的核心功能点以及需要考虑的重要特性和难点来探讨系统架构设计。在整体架构设计中,我们提到客户端SDK是非常重要的组件之一,它是所有数据收集的源头,收集系统中几乎所有的特性都需要客户端的配合才能完成。

因此,今天这篇文章,我们将接着讲讲,用户行为数据收集系统中,客户端SDK的设计。


基于上一篇文章的要求和考量点,如果让你来实现这个系统,你会考虑如何设计呢?我想有几个问题一定是躲不开的:

(1)如何尽可能保证数据不丢失,一定会上传到服务端呢?

(2)如何避免脏数据的混入,造成数据污染?

(3)如何保证上传到服务端的数据不重复,避免数据质量下降?

(4)如何尽可能地节省网络资源,有效降低服务端压力?

(5)如何实现日志的分级处理呢?

本文将围绕上述疑问,以OTT端安卓应用为例,将客户端SDK的设计,给大家细说清楚。


客户端SDK的生命周期


其生命周期,主要包含三个阶段,初始化、提供服务和销毁。

首先,随着应用的启动,SDK需要进行初始化,初始化的主要目的是做一些准备工作,为顺利进入下一阶段提供支撑,因此该阶段需要是阻塞的,在这个阶段SDK不能对外提供服务,阻塞过程中的外部调用需要被暂存,待初始化完成后再处理。初始化阶段的具体内容将会在下一小节详细介绍。

其次,初始化结束后,SDK将进入服务状态,可以供外部调用,接收外部传入的数据,并进行一系列的处理后,上传到服务端。SDK多数时间都处于这个阶段,不断接收数据,处理完成后上传到服务端,如此循环往复,中间处理的具体逻辑会在后文中详细讲述。

最后,当应用要退出时,SDK会进入销毁阶段,将内存中待处理的所有数据存储在客户端存储介质中,释放相应的资源。


客户端SDK初始化


1与配置下发接口交互,获取相应的运行配置解析并存储


SDK初始化的第一步,便是要从服务端获取相关配置,这是其正常运行所需的基础数据。配置下发的内容通常是用于管控SDK的上传行为,例如各种日志类型的日志级别,用于日志分级处理;客户端的上传条件或阈值,用于管控日志上传的频次。SDK在初始化之前,由代码或者配置文件维护一套初始配置,在获取到相应的配置并解析完成后,需要进行本地缓存存储,替换初始配置。这样设计的目的是为了保证通过网络未能正确获取配置时,SDK也能正常工作。另外,通过使用CDN缓存服务,也可以进一步有效避免上述情况的发生。


2生成唯一的session_id,并初始化log_count_id


session_id是指会话ID,代表一次会话,其值具备唯一性,可以用于区分标识一次会话。log_count_id则指日志序列ID,每调用一次SDK接口,该值就会自动加1,是一个自增变量。相信聪明的读者已经想到了,唯一的session_id加上自增的log_count_id便可以唯一标识一条日志了,这对组合,可以用于服务端对收到的日志去重,避免重复数据上传到数据中心,对业务造成影响。在初始化阶段执行的操作是,生成唯一的session_id,并将log_count_id初始化为1


3申请需要的相关资源


为了可以节省网络资源,减少对服务端接口的访问次数,SDK会在客户端对日志进行一定的聚合,然后再一并上传至服务端,因此就需要使用客户端的本地资源,对日志先进行缓存。所以,需要先申请好需要的内存和磁盘资源。


客户端SDK的工作流程



1接受客户端调用,接收数据并补充必要的信息


SDK在服务状态下,可以接受客户端的调用,接收数据,并补充一些必要信息。如,增加行为发生的时间戳、自增的log_count_id等。


2格式拼装&组合打包


为了提升传输效率,对于延时上传的日志,要在客户端侧完成聚合。我们采用的聚合方式是合并多条日志中的相同信息,只保留不同的信息,实际上就是对信息内容做压缩。聚合后的内容需要组装成特定的格式,以便在服务端能够方便的解析出来。


3日志加密或校验


日志加密或增加校验码的主要目的是为了增强数据的安全性,防止一些脏数据的混入所造成的数据污染,避免数据质量下降。


4日志分级上传&失败重试机制


日志分级上传,主要是针对数据的价值大小采用不同的上传策略。对于时效性比较强的数据,采用立即上传的策略,而对于可以接受延迟上传的日志,则采用聚合后再上传的方式。失败重试机制,是为了确保数据尽可能上传至服务端,避免数据丢失,在上传失败后,SDK会将数据暂时保存起来,等待合适时机再进行重试上传。


客户端SDK实现的注意事项


1初始化过程需要阻塞上传


初始化过程中需要获取一些必要的基础信息,准备好后,才可以进入服务状态。而在这个阶段是不能上传数据的,因此需要阻塞上传,可以选择将数据暂时缓存在内存中,待SDK初始化完成后,再重新执行上传流程。


2适当“丢车保帅”


客户端的网络环境是比较复杂的,有时会因为运营商、DNS服务商或者网络抖动等因素导致数据一直上传不成功,这样会在客户端本地大量堆积,可能会对客户端应用的正常运行造成影响。因此,为了保证应用的正常运行,可以采用“丢车保帅”的策略,在达到一定阈值后,将本地缓存的日志清空。笔者现在公司的策略是本地存储最多2000条,超过后将进行清空。


3环境检测机制


有时某些特定的业务场景会有一些特定的需求,例如,想在生产环境下做某些操作,但是需要将日志上传至测试环境进行某些测试或debug。面对这样的业务场景,笔者公司的处理方案是,在SDK初始化阶段增加环境检测环节,可以在服务端通过配置下发控制日志要上传到哪个环境。


结语

上文我们详细介绍了客户端SDK的设计要点和运行过程,对于客户端SDK来说,其进行大部分数据预处理都是为了方便服务端对数据的各种处理和分析。因此,下一篇文章,我们将继续介绍服务端接收服务的设计,敬请期待。


更多精彩内容

长按扫码可关注



    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存