实战:一种在http请求中使用protobuffer+nginx+lua收集打点日志的方案
背景
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/
实战:一种在http请求中使用protobuffer+nginx+lua收集打点日志的方案的更多相关文章
- 一次请求中,经过 nginx+uWSGI+flask应用程序搭建服务的执行过程
Flask框架有自带的http server,但是缺点非常明显,并发能力,及时响应非常差,只适合开发时自测使用. 在我接触过的项目中,生产环境使用nginx+uWSGI+flask应用程序进行部署服务 ...
- Spring RestTemplate中几种常见的请求方式
https://github.com/lenve/SimpleSpringCloud/tree/master/RestTemplate在Spring Cloud中服务的发现与消费一文中,当我们从服务消 ...
- Spring RestTemplate中几种常见的请求方式GET请求 POST请求 PUT请求 DELETE请求
Spring RestTemplate中几种常见的请求方式 原文地址: https://blog.csdn.net/u012702547/article/details/77917939 版权声明 ...
- HTTP协议以及HTTP请求中8种请求方法
HTTP协议以及HTTP请求中8种请求方法 什么是协议? 协议,是指通信的双方,在通信流程或内容格式上,共同遵守的标准. 什么是http协议? http协议,是互联网中最常见的网络通信标准. http ...
- (七)四种常见的post请求中的参数形式
原文链接:https://blog.csdn.net/jiadajing267/article/details/87883725 1).HTTP 协议是以 ASCII 码 传输,建立在 TCP/IP ...
- 将前端请求中的数据绑定到Spring MVC响应方法中参数的四种方法
一.映射URL绑定的占位符到方法参数 1.方法 使用@PathVariable注解 2.代码示例 a.接收请求方法 @RequestMapping(value = "/deleteInfo/ ...
- Python接口测试实战2 - 使用Python发送请求
如有任何学习问题,可以添加作者微信:lockingfree 课程目录 Python接口测试实战1(上)- 接口测试理论 Python接口测试实战1(下)- 接口测试工具的使用 Python接口测试实战 ...
- MySQL实战 | 06/07 简单说说MySQL中的锁
原文链接:MySQL实战 | 06/07 简单说说MySQL中的锁 本文思维导图:https://mubu.com/doc/AOa-5t-IsG 锁是计算机协调多个进程或纯线程并发访问某一资源的机制. ...
- Spring Security 实战干货:OAuth2授权请求是如何构建并执行的
在Spring Security 实战干货:客户端OAuth2授权请求的入口中我们找到了拦截OAuth2授权请求入口/oauth2/authorization的过滤器OAuth2Authorizati ...
随机推荐
- 牛客网PAT练兵场-部分A+B
题解:简单循环 题目地址:https://www.nowcoder.com/questionTerminal/fb581ea099a14f5d97c6149cbeee249f /** * *作者:Yc ...
- static,private,final,abstract,protected
1,static:静态变量:位于方法区中,只有一份,这个类的所有实例共享,不可以被继承 静态方法:直接通过类就能调用,静态方法中只能使用静态变量,不可以被继承 2,private:类不能用privat ...
- Kafka与RabbitMQ区别
RabbitMQ 和 Kafka 的显著差异 RabbitMQ 是一个消息代理,但是 Apache Kafka 是一个分布式流式系统.好像从语义上就可以看出差异,但是它们内部的一些特性会影响到我们是否 ...
- Babel知识点相关
本篇是根据最新babel 7版本写的,里面用到的一些babel相关包都是babel 7的 1,babel是如何工作的 babel是一个转译器,这里我严格区分了转译器和编译器,因为编译器最终生成 ...
- cometoj(A-D+F+H)代码
A #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> ...
- Funny Positive Sequence (思维+前缀)
There are n integers a 1,a 2,…,a n-1,a n in the sequence A, the sum of these n integers is larger th ...
- .net mvc web api上传图片/文件并重命名
#region 上传图片 /// <summary> /// 上传图片到服务器 当error为0时成功,为1时失败 并从errmsg获取消息 /// </summary> // ...
- pycharm可以运行但无法debug的解决方法
错误信息:pydev debugger: process 4588 is connecting 如果您尝试了网上的很多方法如防火墙设置,去掉 ".idea"文件,甚至重装pycha ...
- 转载:MYSQL数据库三表联查的SQL优化过程
地址:https://database.51cto.com/art/202002/609803.htm 作者用了三张有设计缺陷的表做例子,使得优化效果空前,优化手段仅为拨乱反正和加索引,此行可为一哂.
- AP、AC、无线路由器
起因 AP.AC.无线路由器 一直都傻傻的分不清,今天就好好的研究一下他们之间到底有什么联系和区别~ AP 什么是AP? 无线AP(Access Point):即无线接入点,它用于无线网络的无线交换机 ...