跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析

这篇具有很好参考价值的文章主要介绍了跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、背景

在之前的分享中,我们通过引入用户行为分析Growing IO的客户端SDK,介绍了Spring Boot Starter的开发方法,同时也介绍了Spring Boot Starter中的常见的几项高级配置的玩法

本文来介绍该客户端SDK埋点的Java源码设计,希望可以借助这个源码分析和设计,可以让大家在日后的工作中,对于业务性的服务端的埋点上报之类的功能设计思想有所了解,能够自主的学会如何开发一个服务端的埋点上报的SDK组件,正如之前所说,这个东西其实不需要我们依赖服务端的运行,我们直接在客户端上面进行模拟数据上报这个操作即可。也可以自行登录到growingio网站上注册个试用账号。

二、基本概念

源码分析前,我们有必要了解下这种的业务知识与概念,有助于帮助我们统一语言与概念,通过如下文档,可以知道该SDK是如何使用的,建议先自己花费5分钟过一遍,同时思考下自己不明白和不理解的地方,同时也给自己提出几个问题。

docs.growingio.com/v3/develope…

在该网页文档中的代码使用案例可以知道,对于一个客户端SDK埋点的使用,需要提供一个服务器端的URL、项目ID、传输的队列大小和间隔、网络超时时间、日志等,同时需要再客户端构造出如下的变量数据:

(1)、事件时间:即一个行为操作上报或触发的时间点,需要告诉服务端,什么时候发生的。

(2)、事件标识:即一个业务场景的标识,比如创建订单事件、支付事件、用户注册事件、取消订单事件,可以为每种场景定义一个唯一标识:

(3)、用户ID:即触发的用户是谁,既然是用户行为分析,肯定是要把用户ID上报给服务端

(4)、事件级别变量:即当前业务场景的核心参数、核心数据,服务端可以根据该数据进行分组统计分析

SDK使用的示例代码如下:

 

java

复制代码

//事件行为消息体 GIOEventMessage eventMessage = new GIOEventMessage.Builder() .eventTime(System.currentTimeMillis()) // 事件时间,默认为系统时间(选填) .eventKey("BuyProduct") // 事件标识 (必填) .loginUserId("417abcabcabcbac") // 登录用户ID (必填) .addEventVariable("product_name", "苹果") // 事件级变量 (选填) .addEventVariable("product_classify", "水果") // 事件级变量 (选填) .addEventVariable("product_price", 14) // 事件级变量 (选填) .build(); ​ //上传事件行为消息到服务器 GrowingAPI.send(eventMessage);

请大家牢记如下4个内容,这是一个基本的用户行为分析埋点SDK的基本元素,如果然你去设计一个埋点SDK,这四个必不可少,对于学习其他家的埋点SDK源码也是如此。

梳理的一个图如下所示:

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

此时,我们最好思考几个问题,比如:

(1)、SDK是如何构造事件消息的

(2)、SDK是同步上报数据还是异步上报数据

(3)、SDK是如何使用高性能上报数据

(4)、SDK上报的数据格式是什么样的

(5)、SDK这个埋点上报过程中都做了哪些事

为什么要梳理问题呢,其实,这也是一种源码学习方法,在源码学习方法中,其中一个方法就是带着问题/目标去学习,在持续的梳理和跟进中,一步步的来解决自己的问题。

三、源码分析

3.1、源码下载与编译

1、首先在Github上面,找到该SDK的仓库,下载源码:

github.com/growingio/g…

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

2、然后再IDEA中,导入该项目,选择Maven的编译:

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

3、导入工程后,可以发现,其实该SDK的源码设计并不多,但是也是值得我们学习和思考的:

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

4、然后写个测试类,运行一下简单的结果,可以看到控制台输出了一个日志消息,同时对消息结构封装为了数组结构。

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

看到这里不知道大家是什么感觉,我这里个人感觉是,个人完全可以模拟一个服务端的接口,来接收这个数据,从而体验一下客户端数据埋点上报。

3.2、源码分析

源码分析,我们先从程序入口开始。

3.2.1、GIOEventMessage源码分析

1、事件消息的构造GIOEventMessage类,该类本质就是一消息数据结构,从源码中可以看到几个关键点:

(1)、定义了非常精简的HTTP事件请求参数名称:

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

(2)、定义了2个map存储基本事件参数和变量级别的事件参数

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

(3)、存储和更新变量数据:

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

3.2.2、GrowingAPI源码分析

接下来就是核心的消息时间发送方法: GrowingAPI.send(msg),先来看下GrowingAPI这个类都做了那些内容:

(1)、服务端初始化参数配置,并校验服务端的URL是否可用:

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

(2)、封装对外提供的发送方法,将消息传递给消息存储策略处理器中。

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

这样growingapi的分析就结束了。然后它在这里为我们引入了一个新的组件:StoreStrategyClient,也就是说当我们调用send方法发送的时候,SDK将一个个的消息,传递给了StoreStrategyClient类。

3.2.3、StoreStrategyClient源码分析

通过刚才的类可以知道当发送了消息数据,通过 StoreStrategyClient.getStoreInstance().push(msg);代码将消息传递给了消息存储策略处理器,我们接下来分析这个:

(1)、通过单例,提供了一个默认的存储策略

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

(2)、push消息的时候,父类的抽象逻辑,定义了一个数量的线程池,具体如何push交给子类实现:

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

(3)、当前工程中只有一个默认存储实现DefaultStoreStrategy,我们来分析一下他,这个也是整个SDK中最核心的设计,非常值得每个人学习,也是一种典型的生产消费模式的代码设计:

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

(4)、消息加入内存队列,在存储其中维护了这几个发送相关的参数:阻塞队列、阻塞队列的大小、发送间隔、发送器、批量发送数量等

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

接下来的方法是非常重要的,多多理解:

 

scss

复制代码

static { sendMsgSchedule.scheduleWithFixedDelay(new Runnable() { @Override public void run() { while (!queue.isEmpty()) {//队列不为空则执行 if (currentBatchMsgSize() < sendMsgBatchSize) {// 当前小于批量发送数量 GIOMessage gioMessage = queue.poll();// 从队列中取出来 if (gioMessage != null) { String projectId = gioMessage.getProjectId(); if (batchMsgMap.containsKey(projectId)) {//通过项目ID区分批量消息 List<GIOMessage> list = batchMsgMap.get(projectId);//将消息放到某个项目标识下 list.add(gioMessage); } else { List<GIOMessage> list = new ArrayList<GIOMessage>(); list.add(gioMessage);//消息不存在滴1次增加一个 batchMsgMap.put(projectId, list); } } } else {break;}// 大于批量阈值就终止循环,进入发送流程 } // 队列为空时,取出批量消息数据结构中的数据,开始调用发送器批量发送 for (Map.Entry<String, List<GIOMessage>> entry : batchMsgMap.entrySet()) { if (entry.getValue() != null && !entry.getValue().isEmpty()) { sender.sendMsg(entry.getKey(), entry.getValue()); } } batchMsgMap.clear();// 发送完清除数据 } }, sendInterval, sendInterval, TimeUnit.MILLISECONDS); }

通过以上逻辑可以看到,这里采用了一个异步的定时任务线程池,每隔100ms检测一次,当前内存队列中是否存在消息,如果消息小于批量发送的数量就取出来,大于批量发送数量,就开始批量发送。如果说100ms产生了10条消息,则10条消息会整体发送。

3.2.4、消息发送器

通过上一步知道了,消息是每隔100ms异步传递给消息发送器的,然后我们接着分析,看到了发送器的实现,它又是一个线程池异步的调用网络进行发送。

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

看到它调用了网络发送器,网络发送的源码如下,这里就是纯HTTP发送了,然后也可以看到它发送了网络IO错误后也会进行重试处理。

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

这样一个消息从构建到发送,我们就已经分析完了,我们回顾一下消息的流程,如下图所示:

跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析,开源

通过这8个步骤,可以非常清晰的看到它是如何将一个消息发送到服务端的。

四、可以学习到的知识点

通过本文我们可以学习到的知识点如下:

建造者设计模式、策略模式、模板方法模式、单例模式、生产者消费者模式、固定线程池/调度线程池、高性能埋点数据上报、批量数据异步发送上报、扩展点设计等。

大家是否清楚对于上面的知识点都是如何在源码中体现的吗?

可以多花费一点时间来品味一下哦。

本文这个SDK其实源码设计的非常不错了了,经常听到很多人说多线程这项技术无法再实际工作中使用,其实业务功能可能确实很少使用,但是提到高性能和中间件类型的工具、项目、SDK一般都会大量的使用,来完成异步、批量这种处理。

希望本篇文章可以帮助到大家,学习到一种客户端SDK的埋点的设计。

我相信看完了这个SDK设计,大家应该也可以自己手写一个客户端埋点的SDK工具包了,我相信这个对自己的设计、技术也有一定的提升的。如果未来公司的业务,是XXX上报类的,我相信这个SDK的精髓一定会帮助到你。本文没有讲述源码中关于压缩数据上报的内容,感兴趣的可以自己研究下。

五、总结

本文也是开源设计专题的第三篇文章,感兴趣的小伙伴,在阅读后,可以尝试基于该SDK进行下源码的深入理解和学习。

同时,本文也分享了一种源码学习方法,即:带着问题/目标去学习,针对XX问题,进行跟踪和分析。通过最近3篇的文章,希望大家可以具备了:

Spring Boot Starter的设计能力

埋点类的SDK设计能力

一种基于队列的高性能处理能力

异步/批量思想的能力。

六、练习

感兴趣的小伙伴,既然学习了,也不能白学习,可以尝试实现和完成如下内容:

(1)、抽取这个项目中的精髓,封装出自己的埋点SDK Client和埋点Server端,然后进行一些基本的数据展示和分析。

(2)、使用typora文档中提供的mermaid这个东西来梳理当前SDK的业务时序交互流程图文章来源地址https://www.toymoban.com/news/detail-807494.html

到了这里,关于跟我一起学开源设计第3节: 开源的服务端用户埋点SDK源码设计与实现分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 跟我一起从零开始学python(十)Hadoop从零开始入门

    回顾之前讲了python语法编程 ,必修入门基础和网络编程,多线程/多进程/协程等方面的内容,后续讲到了数据库编程篇MySQL,Redis,MongoDB篇,和机器学习,全栈开发,数据分析前面没看的也不用往前翻,系列文已经整理好了: 1.跟我一起从零开始学python(一)编程语法必修

    2024年02月11日
    浏览(28)
  • 【埋点探针】微信小程序SDK安装

    选择Wechat,复制sdk代码 在项目根目录下,创建sdk文件,webfunny.event.js 首先引入sdk代码 引入兼容代码,兼容代码是为了防止SDK加载失败时,避免埋点代码可能因找不到方法的问题。需要手动执行,在代码最开始的地方执行一次即可。 一般获取userId需要在登录之后,这一步可以

    2024年04月26日
    浏览(20)
  • 跟我一起学Adams虚拟样机: 基础篇(一) 运动学仿真基操,以一个简单的曲柄摇杆机构为例

    这篇博文是Adams虚拟样机系列的第一篇,将通过一个最简单的曲柄摇杆机构,介绍用Adams建立虚拟样机,进行运动学仿真,以及对仿真结果做后处理的基本流程。 其中将涉及:Adams View工作环境的设置、已知各杆件位姿时的放置法建模、各杆件姿态未知时的装配法建模、连杆的

    2024年02月04日
    浏览(29)
  • Flink实时数仓之用户埋点系统(一)

    用户行为采集 行为数据:页面浏览、点击、在线日志等数据 活跃数据:用户注册、卸载安装、活跃等数据 App性能日志:卡顿、异常等数据 业务数据采集 业务数据:支付等 维度表:渠道、商品等 用户行为日志 日志结构大致可分为两类,一是页面日志,二是启动日志和在线

    2024年04月11日
    浏览(34)
  • 前端埋点设计/小程序+友盟埋点方案

    所谓埋点就是在应用中特定的流程收集一些信息,用来跟踪应用使用的状况,后续用来进一步优化产品或是提供运营的数据支撑,包括访问数(Visits),访客数(Visitor),停留时长(Time On Site),页面浏览数(Page Views)和跳出率(Bounce Rate)。这样的信息收集可以大致分为两

    2024年02月10日
    浏览(34)
  • 开源Reader阅读3多用户服务器版

    今天是上海全域静态管理的第 27 天。 周一抗原,周二抗原加核酸叠加,周三继续抗原。 原本以为东门物业是假阳性,但是最终还是确诊了,好在政策做了调整,小区内部划了三区,只是把东门+物业划为了封控区,而不是整个小区一起陪绑,所以进步还是有的。 周一开始,

    2024年02月04日
    浏览(20)
  • Android源码解析--享元设计模式,handler消息传递机制(基于Android API 33 SDK分析)

    使用共享对象可有效地支持大量的细粒度的对象 核心:对象复用。 1.1 享元模式Demo 火车票购票Demo 缓存对象在一个Map中。下面我们还会分析 用法 跟进去 这就是最明显的一个享元设计模式。 Android 开发一个知识点:UI 不能够在子线程中更新。 我们跟进post函数 Handler 传递了一个

    2024年02月11日
    浏览(24)
  • 漫谈大数据 - 如何设计业务埋点方案与数据采集应用

            业务埋点和数据分析是在用户行为和业务数据上进行跟踪、收集和分析的关键方法,用于了解用户行为模式、改进产品和服务,并做出数据驱动的决策。         全文1.5万字,建议阅读时间35min。 目录 业务埋点 埋点的重要性 埋点的类型 全埋点 代码埋点 埋点

    2024年02月11日
    浏览(42)
  • 毕业设计 大数据电商用户行为分析及可视化(源码+论文)

    今天学长向大家介绍一个机器视觉的毕设项目,大数据电商用户行为分析及可视化(源码+论文) 项目运行效果: 毕业设计 基于大数据淘宝用户行为分析 项目获取: https://gitee.com/assistant-a/project-sharing 这是一份来自淘宝的用户行为数据,时间区间为 2017-11-25 到 2017-12-03,总计

    2024年02月22日
    浏览(40)
  • 【开源与项目实战:开源实战】77 | 开源实战一(下):通过剖析Java JDK源码学习灵活应用设计模式

    上一节课,我们讲解了工厂模式、建造者模式、装饰器模式、适配器模式在 Java JDK 中的应用,其中,Calendar 类用到了工厂模式和建造者模式,Collections 类用到了装饰器模式、适配器模式。学习的重点是让你了解,在真实的项目中模式的实现和应用更加灵活、多变,会根据具体

    2024年02月11日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包