云原生日志数据分析上手指南

Posted 云原生数据湖

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了云原生日志数据分析上手指南相关的知识,希望对你有一定的参考价值。


背景信息

本指南主要涉及阿里云云产品:

  • 日志服务(SLS, aliyun.com/product/sls

  • 对象存储服务(OSS, aliyun.com/product/oss

  • Data Lake Analytics(DLA, aliyun.com/product/data)

上述三款云产品均属于Serverless化的云原生服务型产品,无维护成本、高可用,简单配置即可在云上搭建起企业级的日志数据分析链路和应用。


日志作为一种特殊的数据,对处理历史数据、诊断问题以及了解系统活动等有着非常重要的作用。对数据分析人员、开发人员或者运维人员而言,日志都是其工作过程中必不可缺的数据来源。
通常情况下,为节约成本,我们会将日志设定一定的保存时间,只分析该时间段内的日志,此类日志称之为“热”日志。这种做法,短期内可以满足使用需求,但从长期来看,大量的历史日志被搁置,无法发挥其价值。
对于许多企业而言,对日志分析的需求特征通常为低时效和低频率。并且在一个企业中,为偶发性的日志分析去构建一套完整的日志分析系统,无论在经济成本还是运维成本上都是不划算的。如何在降低存储成本的同时满足大批量日志的分析需求,是摆在企业面前的一道难题。


实施方案

从用户角度,这套云原生日志数据分析方案非常轻量化。利用日志服务 LOG(Log Service,简称LOG/原SLS)来投递日志,阿里云对象存储服务(Object Storage Service,简称OSS)来存储日志,Data Lake Analytics(DLA)来分析日志。该方案有以下三个优势:

  • LOG是针对实时数据一站式服务,在阿里集团经历大量大数据场景锤炼而成。提供日志类数据采集、智能查询分析、消费与投递等功能,全面提升海量日志处理/分析能力。LOG强大的日志投递能力,能够从源头对接各种类型的日志格式,并且稳定地将日志投递到指定的位置。

  • OSS极低廉的存储成本,能够让您的日志文件存储任意长的时间。

  • DLA强大的分析能力,Serverless的架构,按扫描量收费。DLA可以对投递到OSS上的日志按年、按月、按日进行多维度的分区,提高日志的命中率,降低扫描量,从而以极低的成本、极高的性能来完成大数据量历史日志分析。分析完的数据,还可以利用DLA的云上数据源打通能力,回流到多种云数据系统(RDS, OSS, Table Store, AnalyticDB,PolarDB等)中。





前提条件

在开始实施步骤之前,需要先完成以下准备工作。

  • 参考文档LOG快速入门,开通日志服务、创建项目、创建日志库。

  • 开通OSS服务、在日志服务项目所在的地域创建存储空间。

  • 开通并初始化DLA服务。

实施步骤

步骤一:通过Logtail采集ECS日志

详细操作请参见通过Logtail采集ECS日志。


根据本示例中的日志文件特点,Logtail配置如下所示。本截图示例中是以正则表达式的方式进行采集和字段提取为例,当然,日志服务支持多种采集和提取方式,本文只是示例其中一种。

云原生日志数据分析上手指南



模式选择完整正则模式,需要提供完整正则表达式。

云原生日志数据分析上手指南



步骤二:投递日志到OSS

详细操作请参见投递日志到OSS,并且日志服务投递OSS使用Parquet存储的相关配置。
OSS投递功能页面,配置各项参数,关于各项参数配置说明:help.aliyun.com/documen



云原生日志数据分析上手指南




云原生日志数据分析上手指南



参数说明:

  • OSS BucketOSS Prefix设置日志投递到OSS的哪个目录。

  • 修改分区格式,将分区列的名字填入到目录中:

    • 格式为分区列名=分区列值
      如图所示,修改分区格式默认值,即一级分区列的列名为year,列值为%Y;二级分区列的列名为month,列值为%m;三级分区列的列名为day,列值为%d;如果分区粒度想到小时(每小时产生的数据量较大时),可以设置四级分区,列名为hour,列值为%H。

    • 如果不使用分区列名=分区列值的形式也可以,即保留日志服务保留的默认分区格式:%Y/%m/%d/%H/%M,但是这里是到分钟级别的分区,粒度通常太小,可以改成%Y/%m/%d/%H%M,到天级别分区。

  • 存储格式设置为parquet

  • 压缩方式设置为snappy,使用snappy算法对数据做压缩,可以减少OSS Bucket存储空间使用量。

日志数据投递到OSS中以后,就可以通过DLA读取并分析OSS中的日志。


步骤三:在DLA中创建OSS连接

登录DLA控制台,登录DMS,在DLA中创建一个到OSS的连接。语法如下:

CREATE SCHEMA oss_log_schema with DBPROPERTIES(
catalog='oss',
location = 'oss://myappbucket/sls_parquet/'
);



location:日志文件所在的OSS Bucket的目录,需以/结尾表示目录。myappbucket是OSS Bucket名字。


步骤四:在DLA中创建指向OSS日志文件的外表(分区表)

如果在步骤二中,SLS投递到OSS分区配置的分区为year、month、day,则建表示例如下:

CREATE EXTERNAL TABLE sls_parquet (
content STRING,
client STRING,
process_id STRING,
start_time STRING,
total_time STRING,
status STRING,
original_sql STRING,
rewritten_sql STRING
) PARTITIONED BY (year STRING, month STRING, day STRING)
STORED AS PARQUET
LOCATION 'oss://myappbucket/sls_parquet/';


注意:

  • 新建表中的列名要和生成的parquet文件中设置的列名一致。

  • 分区列的名称、顺序需要和步骤二:投递日志到OSS中的分区列一致。更多创建分区表信息,请参见通过DLA创建OSS分区表。

  • LOCATION中,根据示例,OSS上文件路径示例应该类似:oss://myappbucket/sls_parquet/year=2019/month=01/day=01/,或者oss://myappbucket/sls_parquet/2019/01/01/,LOCATION应该指定到实际分区开始目录的父目录一层,即oss://myappbucket/sls_parquet/。

步骤五:使用命令添加、维护分区信息

步骤四外表创建成功后,执行MSCK REPAIR TABLE将分区信息同步到DLA中。


MSCK REPAIR TABLE sls_parquet;


注意:

  • MSCK命令只能识别符合DLA分区列命名规则的目录,即分区列的目录名为分区列名=分区列值,例如:oss://myappbucket/sls_parquet/year=2019/month=01/day=01/;

  • MSCK命令可以一次性识别当前OSS上实际存在的符合分区命名规则的所有分区,如果后面OSS上有新增分区,需要再次执行上述MSCK命令;

  • 可以通过SHOW PARTITIONS sls_parquet命令查看当前实际DLA能看到的分区情况,如果初次没有执行MSCK命令,SHOW PARTITIONS sls_parquet应该返回空,看不到任何分区,执行MSCK完后,再执行SHOW PARTITIONS sls_parquet应该返回当前OSS上实际符合分区命名规则的所有分区。

如果之前配置投递到OSS上的数据目录如:oss://myappbucket/sls_parquet/2019/01/01/


则执行:


ALTER TABLE sls_parquet ADD
PARTITION (year='2019', month='01', day='01')
LOCATION 'oss://myappbucket/sls_parquet/2019/01/01/';



该命令只添加了一个分区:2019/01/01/


也可以一次添加多个分区:


ALTER TABLE sls_parquet ADD
PARTITION (year='2019', month='01', day='01')
LOCATION 'oss://myappbucket/sls_parquet/2019/01/01/',
PARTITION (year='2019', month='01', day='02')
LOCATION 'oss://myappbucket/sls_parquet/2019/01/02/',
PARTITION (year='2019', month='01', day='03')
LOCATION 'oss://myappbucket/sls_parquet/2019/01/03/',
PARTITION (year='2019', month='01', day='04')
LOCATION 'oss://myappbucket/sls_parquet/2019/01/04/';



该命令添加了四个分区。

另外一个类似的例子,如果之前配置投递到OSS上的数据目录如:
oss://myappbucket/sls_parquet/2019-01-01
oss://myappbucket/sls_parquet/2019-01-02
oss://myappbucket/sls_parquet/2019-01-03
oss://myappbucket/sls_parquet/2019-01-04

则对应的DLA建表语句:

CREATE EXTERNAL TABLE sls_parquet (
content STRING,
client STRING,
process_id STRING,
start_time STRING,
total_time STRING,
status STRING,
original_sql STRING,
rewritten_sql STRING
) PARTITIONED BY (day STRING)
STORED AS PARQUET
LOCATION 'oss://myappbucket/sls_parquet/';

则执行如下语句添加分区:

ALTER TABLE sls_parquet ADD
PARTITION (day='2019-01-01') LOCATION 'oss://myappbucket/sls_parquet/2019-01-01/',
PARTITION (day='2019-01-02') LOCATION 'oss://myappbucket/sls_parquet/2019-01-02/',
PARTITION (day='2019-01-03') LOCATION 'oss://myappbucket/sls_parquet/2019-01-03/',
PARTITION (day='2019-01-04') LOCATION 'oss://myappbucket/sls_parquet/2019-01-04/';


注意:

  • 可以通过SHOW PARTITIONS sls_parquet命令查看当前实际DLA能看到的分区情况,如果初次没有执行ALTER TABLE ADD PARTITION命令,SHOW PARTITIONS sls_parquet应该返回空,看不到任何分区,执行ALTER TABLE ADD PARTITION完后,再执行SHOW PARTITIONS sls_parquet应该返回实际添加的分区信息。

步骤六:查询分区表数据

分区信息同步完成后,使用SELECT语句对日志进行查询分析。例如,对于本示例中,查询sls_parquet表得到某一天查询最慢的5条语句。

SELECT original_sql, total_time 
FROM sls_parquet
WHERE client != '' AND year='2019' AND month = '01' AND day = '01'
ORDER BY total_time DESC
LIMIT 5;

后续操作

上述示例中,日志数据投递OSS的存储格式为Parquet格式,除了Parquet格式,LOG还可以将投递文件的格式设置为JSON和CSV。详细的配置,请参见JSON格式和CSV格式。


JSON格式

  • 当投递文件的格式设置为JSON且无压缩时,建表语句为:

CREATE EXTERNAL TABLE sls_json (
content STRING,
client STRING,
process_id STRING,
start_time STRING,
total_time STRING,
status STRING,
original_sql STRING,
rewritten_sql STRING
) PARTITIONED BY (year STRING, month STRING, day STRING)
STORED AS JSON
LOCATION 'oss://myappbucket/sls_json/';


  • 当投递文件的格式设置为JSON且使用标准Snappy压缩时,建表语句为:

CREATE EXTERNAL TABLE sls_json_snappy (
content STRING,
client STRING,
process_id STRING,
start_time STRING,
total_time STRING,
status STRING,
original_sql STRING,
rewritten_sql STRING
) PARTITIONED BY (year STRING, month STRING, day STRING)
STORED AS JSON
LOCATION 'oss://myappbucket/sls_json_snappy/'
TBLPROPERTIES(
'text.compression'='snappy',
'io.compression.snappy.native'='true'
);


  • 注意:

  • 必须指定TBLPROPERTIES( 'text.compression'='snappy', 'io.compression.snappy.native'='true')的属性。

CSV格式

  • 当投递文件的格式设置为CSV,不包含header,使用标准Snappy压缩时,建表语句为:

CREATE EXTERNAL TABLE sls_csv_snappy (
content STRING,
client STRING,
process_id STRING,
start_time STRING,
total_time STRING,
status STRING,
original_sql STRING,
rewritten_sql STRING
) PARTITIONED BY (year STRING, month STRING, day STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES(
'separatorChar'=',',
'quoteChar'='"',
'escapeChar'='\\'
)
STORED AS TEXTFILE
LOCATION 'oss://myappbucket/sls_csv_snappy/'
TBLPROPERTIES(
'text.compression'='snappy',
'io.compression.snappy.native'='true',
'skip.header.line.count'='0'
);



  • 当投递文件的格式设置为CSV无压缩,且包含header时,建表语句为:

CREATE EXTERNAL TABLE sls_csv (
content STRING,
client STRING,
process_id STRING,
start_time STRING,
total_time STRING,
status STRING,
original_sql STRING,
rewritten_sql STRING
) PARTITIONED BY (year STRING, month STRING, day STRING)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES(
'separatorChar'=',',
'quoteChar'='"',
'escapeChar'='\\'
)
STORED AS TEXTFILE
LOCATION 'oss://myappbucket/sls_csv/'
TBLPROPERTIES(
'skip.header.line.count'='1'
);


关于更多的文件格式对应的建表支持情况,请参考:yq.aliyun.com/articles/


更多参考

  • Data Lake Analytics学习路径:help.aliyun.com/learn/l

  • Data Lake Analytics知乎专栏:zhuanlan.zhihu.com/data

  • 阿里云Data Lake Analytics产品专栏:yq.aliyun.com/teams/396

  • 云栖社区:yq.aliyun.com/topic/138

1元10TB的数据分析流量包和流量包优惠活动:et.aliyun.com/bdad/data

以上是关于云原生日志数据分析上手指南的主要内容,如果未能解决你的问题,请参考以下文章

云原生应用的测试指南

杉岩数据参与撰写的《2020行业云原生应用报告指南》正式对外发布

云原生架构下日志服务数据预处理

云原生架构下日志服务数据预处理

Quarkus技术系列「云原生架构实战」配置参考指南相关的功能机制配置介绍分析

使用loki+promtail实现云原生日志分析