实战:一种在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 ...
随机推荐
- flink创建视图的几种方式
import org.apache.flink.api.common.typeinfo.BasicTypeInfo; import org.apache.flink.api.java.typeutil ...
- DAO层,Service层,Controller层、View层、entity层
1.DAO(mapper)层:DAO层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此,DAO层的设计首先是设计DAO的接口,然后在Spring的配置文件中定义此接口的实现类,然后就 ...
- MySQL遇见SELECT list is not in GROUP BY clause and contains nonaggre的问题
目录 报错现象 原因 解决方法 报错现象 执行SQL报错如下: SELECT student.s_no,student.s_name,SUM(result.mark) FROM student,res ...
- docker部署数据库
搜索数据库镜像images docker search mysql 搜索结果如下图所示: 选择合适自己的mysql版本 因为mysql新版本出来了,很多特性没有学习,所以笔者安装了mysql:5.6 ...
- zero:如何找到SEO流量的突破口
http://www.wocaoseo.com/thread-326-1-1.html 之前一篇文章已有提到过,SEO可以分为两个阶段: 一个阶段是了解点SEO知识,然后就到网站上去找页面,看哪些招式 ...
- springboot-swagger配置
原文地址 https://www.cnblogs.com/softidea/p/6251249.html https://www.cnblogs.com/xiebq/p/9181517.html 1p ...
- MySQL 字符类型
字符类型 MySQL提供了多种关于字符存储的类型,但是在大多数情况下我们只使用char和varchar即可 类型 大小 用途 CHAR 0-255字节 定长字符串 VARCHAR 0-65535 字节 ...
- 使用 Postman 做 API 自动化测试
Postman 最基本的功能用来重放请求,并且配合良好的 response 格式化工具. 高级点的用法可以使用 Postman 生成各个语言的脚本,还可以抓包,认证,传输文件. 仅仅做到这些还不能够满 ...
- python练习 - 系统基本信息获取(sys标准库)+ 二维数据表格输出(tabulate库)
系统基本信息获取 描述 获取系统的递归深度.当前执行文件路径.系统最大UNICODE编码值等3个信息,并打印输出. ...
- win10找不到wifi
禁用->启用 就能用了.