打通大前端最后一公里之前端埋点与日志系统架构设计
优采云 发布时间: 2022-04-30 23:13打通大前端最后一公里之前端埋点与日志系统架构设计
什么是埋点?
所谓“埋点”,是数据采集领域(尤其是用户行为数据采集领域)的术语。指的是针对特定用户行为或事件进行捕获、处理和发送的相关技术及其实施过程。埋点的技术实质,是先*敏*感*词*软件应用运行过程中的事件,当需要关注的事件发生时进行判断和捕获。
埋点的意义何在?埋点的难点
现在的业务技术架构都不仅仅是单独的一种技术方案能解决的。现在只要是做互联网的公司,其业务系统都会包含如下系统模块:
埋点的方式
埋点方式多种多样,按照埋点位置不同,可以分为前端(客户端)埋点与后端(服务器端)埋点,其中前端埋点包括:代码埋点、全埋点、可视化埋点。这些埋点方式的比较如下:
前端埋点:
埋点准确性顺序:侵入式(代码)埋点 > 可视化埋点 > 全埋点
常见埋点属性
通常前端是按照页面维度统计埋点的,常见的事件属性如下:
常见埋点事件
页面停留: 当前页面切换或者页面卸载时, 记录前一页浏览时间
pv: 进入页面时, 页面访问次数,uv只需要根据deviceId过滤
交互事件: 用户交互事件触发时,比如点击、长按等
逻辑事件: 符合逻辑条件时, 比如登陆、跳转页面等
性能数据采集方案常见性能指标后端埋点:
后端埋点 指触发了服务端接口调用(如:接口回调成功触发)的事件埋点,如最典型的注册成功事件、付费成功事件。后端埋点对数据的准确度要求更高,同时也可以通过变量字段的扩展支持数据拆分、聚合和下钻。需要强调的是,后端事件一般采集的是已登录状态下的用户行为,如果想使用后端埋点事件作为流程分析的其中一环(如漏斗分析),则可能出现未登录的用户会漏掉的情况。
后端埋点为了避免前端埋点的以下问题:
前端埋点需要对采集的数据压缩、暂存,为减少移动端的数据流量,除一些需要实时上报的重要事件不限制网络环境,其它事件一般只在wifi情况下上报,因此数据会有延迟,丢数据等弊端,而在后端采集数据,由于数据是在内网传输,数据传输的即时性强,丢失数据的风险小。
前端埋点采集程序由于需要常驻,监测实时和延迟埋点上报,不可避免的带来额外的耗电。
前端埋点若要新增或调整采集方案,需要开发人员修改客户端代码,然后发版之后才能解决,受发布周期的影响较大,而且通常用户的版本更新并不会及时,这将导致新方案不能及时覆盖所有用户。虽然现在部分埋点管理后台也支持热配置更新,但功能一般都很弱,只支持一些基础的埋点事件热更新部署,
注意:
很多时候并不把后端埋点独立出来,而是混合在前端埋点中,等用户和服务器端的交互返回结果之后,将结果进行上报。
对一下需要精确采集的数据,比如代金券发放等,实施的时候尽量采用后端埋点,除非后端无法采集到所需要的数据,前端埋点只是用来参考。此外也可以将业务数据库代金券领取数据同步到数据仓库中进行分析。
其它埋点路径埋点和独立埋点:
这部分的埋点根据业务对路径的追踪需求和SDK的开发能力,可为每个事件设计上下文的路径信息,路径信息的组成一般由页面、控件、行为三部分组成,而路径的深度也不宜太深,一般小于五层。
显性埋点和隐性埋点:
显性和隐性是从用户有感和无感来区分的,有感事件是用户的主动事件,比如展示和点击事件;无感事件主要用来处理后台的数据请求和拉取,用以监控和服务器的数据交互是否正常等,无感事件中常用的是扫描采集,比如app启动之后,扫描各设置开关的状态信息进行上报等
业务埋点和监测埋点:
业务埋点是从业务需求的角度而言,比如产品需要统计某个页面的曝光和点击,算法人员需要的推荐项点击率等;而监测埋点是从业务的流程上来讲的,一般是指隐性的(比如服务器交互的内容拉取情况、本地潜在信息的生成情况等),此外业务埋点中的关键部分也可以用作监测埋点。
最理想的埋点方式?
回到一开始的问题:何种埋点方式最理想呢?
正如同*敏*感*词*有两面,任何单一的埋点方式都存在优点与缺点,企图通过简单粗暴的几行代码/一次部署、甚至牺牲用户体验的埋点方式,都不是企业所期望的。要满足精细化、精准化的数据分析需求,可根据实际需要的分析场景,选择一种或多种组合的采集方式,毕竟采集全量数据不是目的,实现有效的数据分析,从数据中找到关键决策信息实现增长才是重中之重。
因此,数据采集只是数据分析的第一步,数据分析的目的是洞察用户行为,挖掘用户价值,进而促进业务增长,故最理想的埋点方案是根据根据不同的业务和场景以及行业特性和自身实际需求,将埋点通过优劣互补方式进行组合,比如:
埋点上报方式
对于一个埋点方案来说,数据上报有两个点需要着重考虑:
图片请求
有下面几点优势:
GET 请求
GET把参数包含在URL中,也就是说我们的上报的数据是在一个url 参数中或者是几个参数中,例如 ?data=XXXX 这里的data 就是我们上报的数据
GET 请求 最大的特点就是简单,但是同时也带来了很多其他的问题,首先是安全问题因为GET 请求参数被暴露在IURL 中,GET请求只能进行url编码,而POST支持多种编码方式,其次GET请求在URL中传送的参数是有长度限制的,也就是如果你上报的数据内容比较多,可能会被截断。
POST 请求
POST 请求 相比GET 请求首先就是更加安全,其次是支持多种编码,而且所能发送的数据量也更大,看起来是个不错的选择,但是还是不如图片请求好
埋点管理设计
下面是APP 端的一个例子
事件模型
事件的设计
下面分别是 H5、APP 、小程序 端埋点的一个设计
基本规范
我们在设计的时候要注意一些基本的规范,例如我们属性的命名,这样才能可以更好的维护
预置属性
设计原则
整个埋点的设计我们应该遵循一下几个原则,从而可以更好的维护和管理整个埋点系统
埋点时间能通用则不单独埋点,不是说单独埋点越多越好,我们应该尽可能的从上层设计比较通用的事件,这样方便复用。
重要事件单独处理,统一上报,保证采集的可用性
对于主要的业务流程,我们可以设计独立的事件,从而方便更好的分析
后端 日志收集系统架构设计
具体日志发送流程如下图:
抽象出来架构模型如下:
这是一个再常见不过的架构了:
(1)Kafka:接收用户日志的消息队列
(2)Logstash:做日志解析,统一成json输出给Elasticsearch
(3)Elasticsearch:实时日志分析服务的核心技术,一个schemaless,实时的数据存储服务,通过index组织数据,兼具强大的搜索和统计功能。
(4)Kibana:基于Elasticsearch的数据可视化组件,超强的数据可视化能力是众多公司选择ELK stack的重要原因。
(5)Zookeeper: 状态管理,监控进程等服务
日志从产生到检索,主要经历以下几个阶段:采集->传输->缓冲->处理->存储->检索
日志接入
日志接入目前分为两种方式,SDK 接入和调用 Http Web 服务接入
SDK 接入:日志系统提供了不同语言的 SDK,SDK 会自动将日志的内容按照统一的协议格式封装成最终的消息体,并最后最终通过 TCP 的方式发送到日志转发层(rsyslog-hub);
Http Web 服务接入:有些无法使用 SDk 接入日志的业务,可以通过 Http 请求直接发送到日志系统部署的 Web 服务,统一由 web protal 转发到日志缓冲层的 kafka 集群。
日志采集
可选 rsyslog,flume
日志缓冲
Kafka 是一个高性能、高可用、易扩展的分布式日志系统,可以将整个数据处理流程解耦,将 kafka 集群作为日志平台的缓冲层,可以为后面的分布式日志消费服务提供异步解耦、削峰填谷的能力,也同时具备了海量数据堆积、高吞吐读写的特性。
日志切分
日志分析是重中之重,为了能够更加快速、简单、精确地处理数据。日志平台使用 spark streaming 流计算框架消费写入 kafka 的业务日志,Yarn 作为计算资源分配管理的容器,会跟不同业务的日志量级,分配不同的资源处理不同日志模型。
整个 spark 任务正式运行起来后,单个批次的任务会将拉取的到所有的日志分别异步的写入到 ES 集群。业务接入之前可以在管理台对不同的日志模型设置任意的过滤匹配的告警规则,spark 任务每个 excutor 会在本地内存里保存一份这样的规则,在规则设定的时间内,计数达到告警规则所配置的阈值后,通过指定的渠道给指定用户发送告警,以便及时发现问题。当流量突然增加,es 会有 bulk request rejected 的日志会重新写入 kakfa,等待补偿。
日志存储
原先所有的日志都会写到 SSD 盘的 ES 集群,logIndex 直接对应 ES 里面的索引结构,随着业务增长,为了解决 Es 磁盘使用率单机最高达到 70%~80% 的问题,现有系统采用 Hbase 存储原始日志数据和 ElasticSearch 索引内容相结合的方式,完成存储和索引;Index 按天的维度创建,提前创建index会根据历史数据量,决定创建明日 index 对应的 shard 数量,也防止集中创建导致数据无法写入。现在日志系统只存近 7 天的业务日志,如果配置更久的保存时间的,会存到归档日志中;对于存储来说,Hbase、Es 都是分布式系统,可以做到线性扩展。
写给前端同学的疑问
在mysql中,是以id简历b+树索引,然后通过目录页对应到数据页,然后找到数据。对于传统的增删改查(用id)没有任何问题,速度也很快,但是对于全文检索来说,就很尴尬。比如查询like %北大%。这样是走不到索引的,需要全表扫描。但是对于es来说,这就好办多了。
倒序索引:以name为倒序索引来看。
我们是将内容进行了分词(这里是最细粒划分)。然后指向了我们document的一个唯一的标识,能够找到位置的地址。
这样,当我们在程序发出一个查询请求后,比如“北大青年”。首先会把这个查询内容分词:“北大”、“青年”。然后就找到对应的数据[1,2,3]。这三条数据了,比我们在mysql中模糊查询快的多。这是其中的一个原因。
我们将“北大”、“河北”、“大学...这样的叫做term。如果有很多个term,那么我们如何找到对应的term呢。我们以term是英文为例:假如有Carla,Sara,Elin,Ada,Patty,Kate,Selena。
第一个方法:遍历?遍历是不可能遍历的,这辈子都不可能遍历的。
第二个方法:采用二分查找(悄悄的告诉你,mysql的inndb中在目录页的查找过程中和数据页的查找对应的数据中均有体现)可以用 logN 次磁盘查找得到目标。但是磁盘的随机读操作仍然是非常昂贵的(一次random access大概需要10ms的时间)。而相比于mysql,term的dictionary要大得多。无法完整地放到内存里,于是就有了第三个方法。
第二个方法:term index。term index有点像一本字典的大的章节表。如果所有的term都是英文字符的话,可能这个term index就真的是26个英文字符表构成的了。但是实际的情况是,term未必都是英文字符,term可以是任意的byte数组。而且26个英文字符也未必是每一个字符都有均等的term,比如x字符开头的term可能一个都没有,而s开头的term又特别多。实际的term index是一棵trie 树:
这里只考虑前缀并不考虑完整的分词字,例子是一个包含 "A", "to", "tea", "ted", "ten", "i", "in", 和 "inn" 的 trie 树。这棵树不会包含所有的term,它包含的是term的一些前缀。通过term index可以快速地定位到term dictionary的某个offset,然后从这个位置再往后顺序查找。再加上一些压缩技术(搜索 Lucene Finite State Transducers) term index 的尺寸可以只有所有term的尺寸的几十分之一,使得用内存缓存整个term index变成可能。整体上来说就是这样的效果。
这种方式就很快就能够查找到对应的分词,然后在对应的分词就找到了对应的主键,然后就可以直接找到对应的数据了。
HDFS容错率很高,即便是在系统崩溃的情况下,也能够在节点之间快速传输数据。HBase是非关系数据库,是开源的Not-Only-SQL数据库,它的运行建立在Hadoop上。HBase依赖于CAP定理(Consistency, Availability, and Partition Tolerance)中的CP项。
HDFS最适于执行批次分析。然而,它最大的缺点是无法执行实时分析,而实时分析是信息科技行业的标配。HBase能够处理*敏*感*词*数据,它不适于批次分析,但它可以向Hadoop实时地调用数据。
HDFS和HBase都可以处理结构、半结构和非结构数据。因为HDFS建立在旧的MapReduce框架上,所以它缺乏内存引擎,数据分析速度较慢。相反,HBase使用了内存引擎,大大提高了数据的读写速度。
HDFS执行的数据分析过程是透明的。HBase与之相反,因为其结构基于NoSQL,它通过在不同的关键字下进行排序而获取数据。
最后, 送人玫瑰,手留余香,觉得有收获的朋友可以点赞,关注一波 ,我们组建了高级前端交流群,如果您热爱技术,想一起讨论技术,交流进步,不管是面试题,工作中的问题,难点热点都可以在交流*敏*感*词*流,为了拿到大Offer,邀请您进群,入群就送前端精选100本电子书以及下方前端精选资料添加下方小助手二维码就可以进群。让我们一起学习进步.