背景

app打点日志的上报和收集,是互联网公司的基本需求。

一.方案选择

1.1 protobuffer vs json

探究一种以最高效的方式上报和解析打点数据是一个系统性的问题,需要解决的子问题有很多,例如降低网络传输成本,减少序列化反序列化的性能开销,可靠性和高峰期的水平扩展,以及非耦合的编码等等。

很多公司的打点日志会采用比较简单通用的json格式来上报,比如"第四范式"的先荐系统就是使用json格式作为数据上报格式的,这样做便于开发和理解,但是从处理性能方面来考虑并不是最好的选择。

附上protobuffer和json的序列化反序列化性能评测对比: http://www.52im.net/thread-772-1-1.html

在2019年的数据库峰会上,腾讯广告联盟的负责人曾介绍了广告数据平台的原始日志格式,用的就是protobuffer,并且为了方便直接查原始数据格式,自研了一个名为dragon的数据存储格式。

1.2  OpenResty (nginx+lua)

Nginx作为一款开源高性能且稳定的web服务器,经历了10年的发展,已经打败了Apache,IIS等巨头,成为了互联网界的新宠。

Nginx的异步非阻塞,以及模块化的特性,再加上lua脚本的轻量级的特性,让我们很方便的就能开发出一套可扩展且高可靠性的日志收集系统,开发人员只需要关注功能实现本身即可。

1.3 处理流程图

这里只画出了收集部分的步骤,通过Flume收集和处理日志的步骤请见我的另一篇博客:《将nginx收集的日志通过flume转到hive》

二.实现步骤

2.1 定义日志格式

由于每个客户端5秒发送一批日志,可能会包含1条或者多条,为了防止重复发送uuid、客户端版本号等在一次发送周期中不会改变的数据,可以抽取这部分客户端公共的属性作为独立字段;而如点击、播放、翻页等非公共的属性才通过protobuf数组的形式发送。

post日志的上传格式如下:

1) body就是事件体数组部分,每个事件单独一条数据;

2)其他的字段是可共用的公共属性部分,一批事件中这些属性相同。

3)token字段是信令字段,如果token错误,则可能是身份不明者伪造的上报数据。token的格式是(时间戳+密钥)的md5编码。密钥部分可以随意指定,客户端和服务端保持一致即可。出于安全考虑本处打码。

 eventobj的格式定义:

event:{

'eventtype': 'sv', #事件类型

'pg': 'home' #事件发生的一级页面

'spg': 'recommend' #事件发生的二级页面

 'ts': 1527238632,  #timestamp 为事件发生的unix时间戳(+当前时区),精确到秒 

 'arg': ''  # 字符串类型,每个事件对应的其他参数,可能0个或者多个,0个的为空字符串,多个的话用符号&链接。

 }

2.2 编写event.proto文件

本文中不会详细的介绍protobuffer的知识,只会针对该案例讲解操作步骤。如需要了解更多protobuffer的知识可以自行学习。

(有个比较坑的地方是工信部禁了developers.google.com,苦了找文档的各位童鞋。)

如下示例中指定了若干事件类型,若干一级页面和二级页面。文件名为event.proto。

syntax = "proto3";  //protobuff 

option java_outer_classname = "EventsProtos";

message Event {

  enum T { // event type
SCANV = 0; // sv, scan video
PLAYV = 1; // pv, play video
LIKEV = 6;//lv, like video
CLIKEV = 7; // clv, canceld like video
SHAREV = 8; //shv, share video
} enum Pg{ // first level page type
HOME = 0; //
SEARCH = 1; //
UPLOAD = 2; //
} enum Spg{ // second level page type
RECOMMEND = 0; //home
FRESH = 1; // home
HOT = 2; //home
} T eventtype = 1;
Pg pg = 2;
Spg spg = 3;
int32 ts = 4;
string arg = 5; } message Events {
repeated Event events = 1;
}

2.3 生成protobuffer客户端文件。

EventsProtos.java 为Android 端用, Events.pbobjc.h Events.pbobjc.m 为ios端用,

2.4 让OpenResty的lua模块支持protobuffer

1 mkdir /root/project/
2 mkdir /root/project/lua-protobuf
3 git clone https://github.com/starwing/lua-protobuf lua-protobuf/
4 cd lua-protobuf/
5 gcc -O2 -I/usr/local/openresty/luajit/include/luajit-2.1/ -fPIC -shared -Wl,-rpath=./ pb.c -o pb.so
6 cp pb.so /usr/local/openresty/lualib/
7 cp serpent.lua /usr/local/openresty/lualib/
8 cp protoc.lua /usr/local/openresty/lualib/

最新文章

  1. J2EE学习(2)--何謂容器【良葛格学习笔记搬】
  2. ibatis轻松入门
  3. JAVA经典算法40题(1-20)
  4. 重新想象 Windows 8.1 Store Apps (83) - 文件系统的新特性
  5. itoa
  6. Win32 SDK程序创建一些控件(简单调用InitCommonControlsEx,并指定ICC_LISTVIEW_CLASSES控件就可以了)
  7. java新手笔记33 多线程、客户端、服务器
  8. 理解TCP为什么需要进行三次握手
  9. android UI进阶之弹窗的使用(2)--实现通讯录的弹窗效果
  10. h5图片上传预览
  11. Android:Field can be converted to a local varible.
  12. 我发起了一个 .Net 开源 跨平台 GUI (界面开发框架)项目 HtmlCore
  13. 数学与猜想 合情推理模式 (G. 波利亚 著)
  14. Linux开机自动挂载windows网络共享
  15. Python 中docx转pdf
  16. AngularJS $scope 继承性 作用 生命周期
  17. 使用生活实例理解Asp.net运行时
  18. 浅谈HashMap 的底层原理
  19. MySql查询生日的两种方式
  20. 匹配IP的正则表达式

热门文章

  1. pandas电子表格的读取(pandas中的read_excel)
  2. Locust性能测试2--登录示例
  3. SpringBoot(19)---SpringBoot整合Apollo
  4. 从零开始的SpringBoot项目 ( 二 ) 使用IDEA创建一个SpringBoot项目
  5. WebApi之DOM的基本介绍
  6. 测试必须学spring RESTful Service(上)
  7. Flyway版本化管理数据库脚本
  8. 力扣Leetcode 33. 搜索旋转排序数组
  9. Angular 之我见
  10. URL的字符编码