zoukankan      html  css  js  c++  java
  • 实战:一种在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/
  • 相关阅读:
    CF1280G Kirchhoff's Current Loss【表达式解析,不等式】
    [AGC040C] Neither AB nor BA
    [AGC040B]Two Contests
    [ARC101E]Ribbons on Tree(容斥,dp)
    [GXOI/GZOI2019]旧词
    [SDOI2015]寻宝游戏
    半平面交初步
    [CF585E]Marbles
    [P5348]密码解锁
    NOIP2018 保卫王国
  • 原文地址:https://www.cnblogs.com/arli/p/11304264.html
Copyright © 2011-2022 走看看