• 一个一站式流式处理云平台解决方案


    随着互联网、IT、大数据等技术的爆发式发展,企业系统产生的大量爆发数据。对于保存在数据库中的业务数据,可以通过DBus数据总线+Wormhole流式处理平台的日志方式实时地无侵入同步和落地到任意sink端,提供下游系统分析使用;对于业务系统产生的日志数据,这些包含了业务高低峰、用户轨迹、系统异常/错误信息、调用链等诸多信息,也蕴含着无价的宝藏。一些公司通过埋点等方式和手段,往日志数据里输出他们想要监控和跟踪的信息,以便提供客观的数据支撑,做出更高效、更准确的决策。

    DBus-https://github.com/bridata/dbus

    Wormhole-https://github.com/edp963/wormhole

    在这种背景下,各种各样的日志收集、结构化、分析工具如雨后春笋般出现,业界目前已有不少发展得比较成熟的方案,例如:Logstash、Filebeat、Flume、Fluentd、Chukwa. scribe、Splunk等,更有整合了日志采集、转换分析和展示的ELK集成方案。这些方案各有所长。在结构化日志这个方面,大多采用配置正则表达的方式:用于提取日志中模式比较固定、通用的部分,例如日志时间、日志类型、行号等。对于真正的和业务比较相关的信息,我们权且称之为message部分,原因主要是这部分千变万化,很难有一个特定、通用的模式来一劳永逸地描述及囊括所有情形。然而,这部分内容对于企业来说,比前面相对固定的部分更有价值。

    本文就是介绍一种通过简单、可视化、所见即所得即席验证的方式,为用户提供高效、灵活地采集和加工利用数据日志的工具。

    常见的日志处理方案

    目前业界常见的日志分析代表为ELK:

    1. 通过Logstash实时收集和转换数据,保存到Eleaticsearch中,通过Kibana进行展示。

    2. 或者通过Filebeat 作为前端抓取数据,Logstash进行数据转换,保存到Eleaticsearch中,通过Kibana进行展示。

                                                 

    结构化日志的原理

    DBUS设计的数据日志同步方案如下:

    1. 日志抓取端采用业界流行的组件(例如Logstash、Flume、Filebeat等)。一方面便于用户和业界统一标准,方便用户的整合;另一方面也避免无谓的重造轮子。抓取数据称为原始数据日志(raw data log)放进Kafka中,等待处理。

    2. 提供可视化界面,配置规则来结构化日志。用户可配置日志来源和目标。同一个日志来源可以输出到多个目标。每一条“日志源-目标”线,中间数据经过的规则处理用户根据自己的需求来自由定义。最终输出的数据是结构化的,即:有schema约束,可以理解为类似数据库中的表。

    3. 所谓规则,在DBUS中,即“规则算子”。DBUS设计了丰富易用的过滤、拆分、合并、替换等算子供用户使用。用户对数据的处理可分多个步骤进行,每个步骤的数据处理结果可即时查看、验证;可重复使用不同算子,直到转换、裁剪得到自己需要的数据。

    4. 将配置好的规则算子组运用到执行引擎中,对目标日志数据进行预处理,形成结构化数据,输出到Kafka,供下游数据使用方使用。

    系统流程图如下所示:

    根据配置,我们支持同一条原始日志,能提取为一个表数据,或者可以提取为多个表数据。

    每个表是结构化的,满足相同的schema。

    • 每个表是一个规则 算子组的合集,可以配置1个到多个规则算子组

    • 每个规则算子组,由一组规则算子组合而成

    拿到一条原始数据日志, 它最终应该属于哪张表呢?

    每条日志需要与规则算子组进行匹配:

    • 符合条件的进入规则算子组的,最终被规则组转换为结构化的表数据。

    • 不符合的尝试下一个规则算子组。

    • 都不符合的,进入unknown_table表。

    规则算子

    规则算子是对数据进行过滤、加工、转换的基本单元。常见的规则算子如下:

    算子之间是独立的,通过组合不同的算子达到更复杂的功能,对算子进行迭代使用最终达到对任意数据进行加工的目的。

    我们试图使得算子尽量满足正交性或易用性(虽然正则表达式很强大,但我们仍然开发一些简单算子例如trim算子来完成简单功能,以满足易用性),算子的开发也可以随意扩充,比如可以开发提取JSON节点值或XML节点值的算子。算子的开发也很容易,只要遵循基本接口原则,就可以开发任意自定义算子。

    结构化日志的例子

    下面以提取heart_beat_status表为例子进行配置说明,整个数据日志结构化过程如下:

    使用通用抓取端抓取原始日志

    使用Logstash 读取log4j文件作为数据输入源,输出到Kafka中(这里具体配置就不说了,可参考Logstash配置)

    这里抓取端不限制,你可以使用Flume、Filebeat,甚至你自己写的端,只要输出到Kafka中就可以。

    使用可视化方式进行规则算子的配置

    首先配置一个输出表的规则组, 查看heartbeat_log_new这个topic中,我们直接实时的可视化操作配置。

    1、读取原始数据日志

    可以看到由Logstash 预先提取已经包含了log4j的基本信息,例如path、@timestamp、level等。但是数据日志的详细信息在字段log中。由于不同的数据日志输出是不一样的,因此可以看到log列数据是同的。

    需要指出的是:使用logstash预先提取其它列是可选的,其实对于Flume这样直接抓取到的就是raw data log,这对我们后面的提取没有影响

    2、提取感兴趣列

    例如我们提取timestamp、log 原始信息等,可以添加一个toindex算子,提取感兴趣的字段,如下:

    这里需要指出,我们考虑使用数组下标方式,是有原因的:

    • 并不是所有列天生就有列名(例如flume抽取的原始数据,或者split算子处理后的数据列);

    • 下表方式对可以使用数组方式指定列(类似python方式, 例如:1:3 表示1,2,3列);

    因此后续操作全部基于数组下标方式访问。

    特别说明一下:如下?号所在的地方,鼠标移上去就会显示一个在线帮助,告诉你这个算子怎么使用,每个算子怎么用不需要记。

    执行一下,就可以看到被提取后的字段情况:

    3、过滤不相关数据

    在这个例子中,我们只对插入心跳包的数据感兴趣。因此添加一个filter算子,对第2列进行过滤”插入心跳包”:

    执行后,不符合条件的日志行就被过滤了。

    4、以切分方式进行提取

    添加一个split算子,我们对“数据源”,“插入心跳包”,还有后面的“node”进行切分。

    可以看到切分后,原来的第1列变新的1,2,3,4,5列了。

    特别需要说明的是:提取的方式非常多,Split只是一种常见方式。我们可以substring提取,replace掉不需要的数据等,我们还也可以配置正则表示式提取。我们不积极推荐用正则表示的原因是正则表达式很容易写错,并不是最简单可视化的选择。

    5、以trim方式出来数据

    我们想提取4列的值,使用trim算子进行过滤掉不需要的数据。

    执行后,这样新的5列就拿到干净的值。

    6、选择输出列

    最后我们把感兴趣的列输出,使用saveAs算子进行输出, 指定列名和类型。

    执行后,这就是处理好的最终输出数据样本。

    查看结构化输出结果

    保存上一步配置好的规则组,运用到DBus执行算子引擎,就可以生成相应的结构化数据了。目前根据项目实际,DBus输出的数据是UMS格式。UMS是DBus开源项目(https://github.com/bridata/dbus)定义并使用的,通用的数据交换格式,是标准的JSON。其中同时包含了schema和数据信息。更多UMS介绍请参考DBus开源项目主页的介绍。

    输出结果的数据格式和结构,不想使用UMS的,可经过简单的开发,实现定制化。

    以下是测试案例,输出的结构化UMS数据的例子:

    {

        "payload": [

            {

                "tuple": [

                    "127046516736228867",

                    "2017-12-17 13:57:30.000",

                    "i",

                    "320171788",

                    "2017/12/17 13:57:30.877",

                    "edpdb",

                    "成功",

                    "/DBus/HeartBeat/Monitor/edpdb/TEST1/T1000"

                ]

            },

            {

                "tuple": [

                    "127046516736228869",

                    "2017-12-17 13:57:30.000",

                    "i",

                    "320171790",

                    "2017/12/17 13:57:30.946",

                    "edpdb",

                    "成功",

                    "/DBus/HeartBeat/Monitor/edpdb/TEST4/ONEYI"

                ]

            },

            {

                "tuple": [

                    "127046520930532871",

                    "2017-12-17 13:57:31.000",

                    "i",

                    "320171792",

                    "2017/12/17 13:57:31.026",

                    "edpdb",

                    "成功",

                    "/DBus/HeartBeat/Monitor/edpdb/TEST3/USER_REGISTER"

                ]

            }

        ],

        "protocol": {

            "type": "data_increment_data",

            "version": "1.3"

        },

        "schema": {

            "batchId": 0,

            "fields": [

                {

                    "encoded": false,

                    "name": "ums_id_",

                    "nullable": false,

                    "type": "long"

                },

                {

                    "encoded": false,

                    "name": "ums_ts_",

                    "nullable": false,

                    "type": "datetime"

                },

                {

                    "encoded": false,

                    "name": "ums_op_",

                    "nullable": false,

                    "type": "string"

                },

                {

                    "encoded": false,

                    "name": "ums_uid_",

                    "nullable": false,

                    "type": "string"

                },

                {

                    "encoded": false,

                    "name": "event_time",

                    "nullable": false,

                    "type": "datetime"

                },

                {

                    "encoded": false,

                    "name": "datasource",

                    "nullable": false,

                    "type": "string"

                },

                {

                    "encoded": false,

                    "name": "heartbeat_state",

                    "nullable": false,

                    "type": "string"

                },

                {

                    "encoded": false,

                    "name": "heartbeat_node",

                    "nullable": false,

                    "type": "string"

                }

            ],

            "namespace": "heartbeat_log.heartbeat_log_schema.heartbeat_table.3.host1.0"

        }

    }

    查看监控

    为了便于掌握数据抽取及规则匹配等情况,我们提供了日志数据提取的可视化实时监控界面,如下图所示,可随时了解:

    • 实时数据条数

    • 错误条数情况(错误条数是指:执行算子时出现错误的情况,帮助发现算子与数据是否匹配,用于修改算子)

    • 数据延时情况

    监控中还有一张表叫做__unkown_table__ 表明所有没有被匹配上的数据条数。例如:logstash抓取的日志中有5种不同模式的数据,我们只捕获了其中3种模式,其它没有被匹配上的数据,全部在_unkown_table_计数中。

    总结

    DBus日志同步方案总结如下:

    1、集成整合现有日志抓取工具(Flume、filebeat、logstash等),方便用户接入及整合;

    2、DBUS提供了丰富的算子及可视化配置界面,供用户结构化数据日志使用。

    • 通过可视化的,自由地使用各种规则算子对日志进行处理,生成结构化的数据日志;

    • 每个算子配置过程都可以看到原始数据和加工后的数据;

    • 算子可以随意增减,处理顺序可以随意调换,每个步骤的算子相互叠加使用;

    • 用户也可以扩展开发自己需要的算子;

    • 提供源到目标一对多的配置,让用户想怎么玩就怎么玩,从而可从任意多个角度挖掘数据价值;

    • 监控让用户更直观地了解到数据结构化实时转换的情况,一切尽在掌控;

    3、将原始数据日志转换为结构化数据,输出到kafka中提供给下游数据使用费进行使用。

    最终使得日志业务数据结构化的过程,变得简单、可视化、配置集中化, 使得大家都能轻松地玩转日志数据。

    本文提到的日志结构化方案计划于2018年1月发布到开源项目DBus 0.4版本中,项目地址https://github.com/bridata/dbus

    系统架构和工作原理

    DBUS主要分为两个部分:貼源数据采集和多租户数据分发。两个部分之间以Kafka为媒介进行衔接。无多租户资源、数据隔离需求的用户,可以直接消费源端数据采集这一级输出到kafka的数据,无需再配置多租户数据分发。

    GlobalOverview

    1 DBUS源端数据采集

    DBUS源端数据采集大体来说分为2部分:

    • 读取RDBMS增量日志的方式来 实时获取增量数据日志,并支持全量拉取;
    • 基于logtash,flume,filebeat等抓取工具来实时获得数据,以可视化的方式对数据进行结构化输出;

    以下为具体实现原理 system arch

    主要模块如下:

    • 日志抓取模块:从RDBMS的备库中读取增量日志,并实时同步到kafka中;
    • 增量转换模块:将增量数据实时转换为UMS数据,处理schema变更,脱敏等;
    • 全量抽取程序:将全量数据从RDBMS备库拉取并转换为UMS数据;
    • 日志算子处理模块:将来自不同抓取端的日志数据按照算子规则进行结构化处理;
    • 心跳监控模块:对于RDMS类源,定时向源端发送心跳数据,并在末端进行监控,发送预警通知;对于日志类,直接在末端监控预警。
    • web管理模块:管理所有相关模块。

    2 多租户数据分发

    对于不同租户对不同源端数据有不同访问权限、脱敏需求的情形,需要引入Router分发模块,将源端貼源数据,根据配置好的权限、用户有权获取的源端表、不同脱敏规则等,分发到分配给租户的Topic。这一级的引入,在DBUS管理系统中,涉及到用户管理、Sink管理、资源分配、脱敏配置等。不同项目消费分配给他的topic。

    route2Project

    主要功能:

    • 无侵入方式接入多种数据源: 业务系统无需任何修改,以无侵入性读取数据库系统的日志获得增量数据实时变化。目前RDBMS支持mysql,oracle数据源(Oracle数据源请参考Oracle相关协议), 日志方面支持基于logstash,flume和filebeat的多种数据日志抽取方案。
    • 海量数据实时传输: 使用基于Storm的流式计算框架,秒级延时,整体无单点保证高可用性。
    • 多租户支持: 提供用户管理、资源分配、Topology管理、租户表管理等丰富的功能,可根据需求,为不同租户分配不同的源端表数据访问权限,应用不同的脱敏规则,从而实现多租户资源隔离、差异化数据安全。

    grafana

    2intr_proj_table

    2intr_router_topo

    • 感知源端schema变更: 当源端发生schema变更时,能自动感知schema变化,调整UMS版本号,并通过Kafka消息和邮件通知下游diff

    • 数据实时脱敏: 可根据需求对指定列数据进行实时脱敏。脱敏策略包括:直接替换、MD5、murmur等脱敏算法,脱敏加盐,正则表达式替换等。支持用户开发jar包实现DBUS未覆盖的个性化脱敏策略。 docs/encode

    • 初始化加载: 支持高效的初始化加载和重新加载,支持任意指定输出topic,灵活应对客户需求。 docs/fuller

    • 统一标准化消息传输协议: 使用统一的UMS(JSON格式)消息schema格式输出便于消费,提供数据线级ums_id保证数据顺序性,输出insert,Update(before/after),Delete event数据。 ums

    • 可靠多路消息订阅分发: 使用Kafka存储和传递消息保证可靠性和便捷的多用户订阅

    • 支持分区表/系列表数据汇集: 支持分区表的数据汇集到一个“逻辑表” 。也可将用户自定义的系列表数据汇集到一个“逻辑表“。例:

      grafana

    • 实时监控&预警: 可视化监控系统能随时查看各数据线实时流量和延时状况;当数据线发生异常时,根据配置策略自动发邮件或短信通知相关负责人

      grafana

    Wormhole  Architecture

    设计理念

    • 统一 DAG 高阶分形抽象
      • 构建由 Source DataSys,Kafka Topic,Spark Stream(Flink Stream),Sink DataSys 组成的物理 DAG
      • 每个物理 DAG 里可以并行处理多个由 Source Namespace,Flow,Sink Namespace 组成的逻辑 DAG
      • 每个 Flow 本身是典型的 Spark RDD DAG
    • 统一通用流消息 UMS 协议抽象
      • UMS 是 Wormhole 定义的流消息协议规范
      • UMS 试图抽象统一所有结构化消息
      • UMS 自身携带结构化数据 Schema 信息
      • Wh4 支持用户自定义半结构化 JSON 格式
    • 统一数据逻辑表命名空间 Namespace 抽象
      • Namespace 唯一定位所有数据存储所有结构化逻辑表
      • [Data System].[Instance].[Database].[Table].[Table Version].[Database Partition].[Table Partition]

    主要特性

    • 支持可视化,配置化,SQL 化开发实施流式项目
    • 支持指令式动态流式处理的管理,运维,诊断和监控
    • 支持统一结构化 UMS 消息和自定义半结构化 JSON 消息
    • 支持处理增删改三态事件消息流
    • 支持单个物理流同时并行处理多个逻辑业务流
    • 支持流上 Lookup Anywhere,Pushdown Anywhere
    • 支持基于业务策略的事件时间戳流式处理
    • 支持 UDF 的注册管理和动态加载
    • 支持多目标数据系统的并发幂等入库
    • 支持多级基于增量消息的数据质量管理
    • 支持基于增量消息的流式处理和批量处理
    • 支持 Lambda 架构和 Kappa 架构
    • 支持与三方系统无缝集成,可作为三方系统的流控引擎
    • 支持私有云部署,安全权限管控和多租户资源管理
    正因为当初对未来做了太多的憧憬,所以对现在的自己尤其失望。生命中曾经有过的所有灿烂,终究都需要用寂寞来偿还。
  • 相关阅读:
    Java线程volatile(二)
    Java线程synchronized(一)
    Java 平衡二叉树和AVL
    Data striping
    分布式系统的事务处理
    什么是面向对象
    Redis为什么是单线程
    spring 自定义事物同步器(一): TransactionSynchronizationManager 解析
    understand EntityManager.joinTransaction()
    spring 拾遗
  • 原文地址:https://www.cnblogs.com/candlia/p/11920035.html
Copyright © 2020-2023  润新知