ADB日志分析最佳实践

本文涉及的产品
阿里云百炼推荐规格 ADB PostgreSQL,4核16GB 100GB 1个月
云原生大数据计算服务 MaxCompute,5000CU*H 100GB 3个月
云原生大数据计算服务MaxCompute,500CU*H 100GB 3个月
简介: ## 背景 利用服务器日志做分析是很多公司进入大数据分析的第一步,也是很关键的一步。大部分情况下,这些公司在考虑进行大数据分析的时候,都会遇到以下问题: * 团队里面缺乏了解大数据技术栈的工程师 * 都听过Hadoop,想要学习Hadoop,但是不知道从何入手 * 从市面上寻找大数据人才效果不理想 * 不愿意一下子投入过多的资金去组建一个专门的大数据团队 虽然Hadoop没

背景

利用服务器日志做分析是很多公司进入大数据分析的第一步,也是很关键的一步。大部分情况下,这些公司在考虑进行大数据分析的时候,都会遇到以下问题:

  • 团队里面缺乏了解大数据技术栈的工程师
  • 都听过Hadoop,想要学习Hadoop,但是不知道从何入手
  • 从市面上寻找大数据人才效果不理想
  • 不愿意一下子投入过多的资金去组建一个专门的大数据团队

虽然Hadoop没有办法一下子搭起来,但是其实在刚开始进入大数据的时候完全可以用MPP数据库来快速满足需求。但是你可能会有疑问,MPP能够代替Hadoop吗?要回答这个问题,首先要理解Hadoop的出现到底解决了什么问题:

  1. 传统的单节点关系型数据库,要提升性能,只能通过scale up的方式,即增加cpu/内存/硬盘。到后面提升5%的计算能力可能是前面10倍的成本投入。Hadoop利用分布式的思想,通过shared-nothing的架构,实现了scale out的能力。在这样的架构下面,加入同样性能的机器,可以达到线性提升处理性能的效果,投入产出成正比。
  2. 关系型数据库对于非/半结构化数据不是特别友好,主要表现在关系型数据库是以行列为结构存储数据的,无法直接把json,xml这类型的数据插入进去。Hadoop的优势是可以通过编写特定的input reader,来解释这些数据格式,从而达到处理非结构数据的能力。但是不能忘记的一点是,为了提升处理性能,即使使用Hadoop,最后也是要将数据结构化的。

通过上面的描述,其实思路就很清晰了。如果可以有一个shared-nothing架构的关系型数据库,将要导入的数据预先进行结构化处理,那么我们还是可以在关系型数据库(MPP)里面做大数据分析。显然ADB就是这么一个场景下最合适的选择。

组件介绍

这一章介绍一下本方案使用到的各种组件

名称 介绍
Nginx 反向代理,一般被用来做负载均衡。作为网络流量的总入口,会沉淀所有的用户行为。利用这里的日志作为分析可以得到最全面的数据视图。
Logstash 日志采集工具,可以对采集到的数据进行一定的预处理,通过配置文件进行格式化改造。
DataHub 数据管道,提供对数据的发布和订阅。支持直接导出到一些常用的数据存储包括MaxCompute,OSS,ADB等。
ADB for MySQL 高并发低延时的PB级别数据仓库,MPP架构,完全兼容MySQL协议。

搭建步骤

安装Nginx

在CentOS下面,安装Nginx

yum install nginx

成功安装的话,会看到如下内容

已安装:
  nginx.x86_64 1:1.12.2-3.el7

作为依赖被安装:
  nginx-all-modules.noarch 1:1.12.2-3.el7              nginx-mod-http-geoip.x86_64 1:1.12.2-3.el7     nginx-mod-http-image-filter.x86_64 1:1.12.2-3.el7     nginx-mod-http-perl.x86_64 1:1.12.2-3.el7
  nginx-mod-http-xslt-filter.x86_64 1:1.12.2-3.el7     nginx-mod-mail.x86_64 1:1.12.2-3.el7           nginx-mod-stream.x86_64 1:1.12.2-3.el7

完毕!

完成安装之后,需要定义Nginx打印日志的格式。在这个例子中,因为我们想要统计网站访问的UV和每个请求的响应时长,所以我们需要把 $request_time$http_cookie 添加进去。另外,Nginx日期的默认打印方式是 07/Jul/2019:03:02:59, 对于我们后面做分析时候查询不是十分友好,所以要把它们统一改成 2019-07-11T16:32:09 的格式。

找到/etc/nginx/nginx.conf,用vi打开,将log_format更改如下:

log_format  main  '$remote_addr - [$time_iso8601] "$request" '
                  '$status $body_bytes_sent $request_time "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for" "$http_cookie"' ;

执行下面命令,重启Nginx使配置生效:

service nginx restart

这时去看一下日志(位于/var/log/nginx/access.log),会发现日志打印格式如下

119.35.6.17 - [2019-07-14T16:39:17+08:00] "GET / HTTP/1.1" 304 0 0.000 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36" "-" "-"

由于默认的Nginx主页不会记录cookie,建议后面挂一个带登陆的系统来做验证

部署DataHub

DataHub的控制台地址 https://datahub.console.aliyun.com/datahub

首先要创建一个Project,取名为log_demo

project_create.png

进入到这个log_demo 项目之后,要创建一个Topic, 我们可以取名topic_nginx_log :

topic_create.png

Topic的类型选择Tuple,这是一种带schema的组织形式,更方便我们查看和后面的处理。Schema的定义跟我们要从日志中取得的字段是强相关的,所以建立的时候需要确保没有错误,否则可能导致后面日志写入的时候出错。

字段名称 意义 类型 对应Nginx日志的字段
remote_ip 请求的来源IP STRING $remote_addr
date 请求发生的日期 BIGINT $time_iso8601 的日期部分
time 请求发生的时间,24小时制,精确到秒 STRING $time_iso8601 的时间部分
method Http请求的方法 STRING $request 的请求动作部分,例如GET
request 请求的uri和param部分 STRING $request的uri和param部分
http_version Http版本号 STRING $request的http版本号部分
status 请求的返回状态码 STRING $status
bytes 请求体的大小 BIGINT $body_bytes_sent
request_time 请求的耗时 DOUBLE $request_time
referer 发出这个请求之前,用户在哪个页面 STRING $http_referer
agent 客户端使用的操作系统和浏览器 STRING $http_user_agent
xforward 请求经过的代理 STRING $http_x_forwarded_for
cookie 用户的标识 STRING $http_cookie

成功创建之后,可以在这个Topic的Schema里面看到如下图展示

topic_schema.jpg

安装Logstash

官方的Logstash没有提供DataHub的兼容工具,所以建议到DataHub的官网上面去下载最新的兼容版本,减少中间融合操作成本。具体的介绍页面在这里

回到控制台,输入下面命令,下载和解压Logstash到你想要的目录

##注意,这里的版本号和下载链接可能因为更新缘故有区别,建议到介绍页面去获取最新链接

wget http://aliyun-datahub.oss-cn-hangzhou.aliyuncs.com/tools/logstash-with-datahub-6.4.0.tar.gz?spm=a2c4g.11186623.2.17.60f73452tHbnZQ&file=logstash-with-datahub-6.4.0.tar.gz

tar -zxvf logstash-with-datahub-6.4.0.tar.gz

安装完成之后需要配置Logstash,这里有两个工作需要完成。第一,由于我们需要将日志处理成结构化的数据,所以在抓取的过程中,还需要做一点加工。Logstash的grok可以帮我们轻松地完成这个任务。第二,我们需要告诉Logstash从哪里(Nginx的日志存放位置)抓起日志文件,最后要同步到哪里(DataHub)去。

配置grok

我们需要让grok能够理解日志文件并进行转换,需要往grok-pattern文件里面添加一个新格式。这个文件存放在刚刚下载的Logstash目录里面,具体路径如下 :

logstash/vendor/bundle/jruby/1.9/gems/logstash-patterns-core-xxx/patterns/grok-patterns

用vi打开这个文件,把下面的新pattern填到文件最末端即可

DATE_CHS %{YEAR}\-%{MONTHNUM}\-%{MONTHDAY}
NGINXACCESS %{IP:remote_ip} \- \[%{DATE_CHS:date}T%{TIME:time}\+08:00\] "%{WORD:method} %{URIPATHPARAM:request} HTTP/%{NUMBER:http_version}" %{NUMBER:status} %{NUMBER:bytes} %{NUMBER:request_time} %{QS:referer} %{QS:agent} %{QS:xforward} %{QS:cookie}
配置Logstash

在Logstash的目录里面,有一个config文件夹,里面有一个logstash-sample.conf文件。打开它,把它改成

input {
  file {
    path => "/var/log/nginx/access.log" #nginx的日志位置,默认在这里。
    start_position => "beginning" #从什么位置开始读起日志文件,beginning表示从最开始。
  }
}

filter {
  grok {
    match => {"message" => "%{NGINXACCESS}"} #当grok获取到一个消息时,怎么去转换格式
  }
  mutate {
    gsub => [ "date", "-", ""] #因为日期在后面要用作ADB表的二级分区,所以需要把非数字字符去掉
  }
}

output {
   datahub {
        access_id => "<access-key>" #从RAM用户获取access key
        access_key => "<access-secrect>" #从RAM用户获取access secret
        endpoint => "http://dh-cn-shenzhen-int-vpc.aliyuncs.com" #DataHub的endpoint,取决于把project建立在哪个区域
        project_name => "log_demo" #刚刚在DataHub上面创建的项目名称
        topic_name => "topic_nginx_log" #刚刚在DataHub上面创建的Topic名称
        dirty_data_continue => true #脏数据是否继续运行
        dirty_data_file => "/root/dirty_file" #脏数据文件名称,脏数据会被写入到这里
        dirty_data_file_max_size => 1000 #脏数据的文件大小
    }
}

完成这个配置之后,我们可以启动Logstash来验证是否有日志被写入到DataHub里面了。在Logstash的根目录里面,执行如下命令

bin/logstash -f config/logstash-sample.conf

看到这个如下日志代表启动成功

ending Logstash logs to /root/logstash-with-datahub-6.4.0/logs which is now configured via log4j2.properties
[2019-07-12T13:36:49,946][WARN ][logstash.config.source.multilocal] Ignoring the 'pipelines.yml' file because modules or command line options are specified
[2019-07-12T13:36:51,000][INFO ][logstash.runner          ] Starting Logstash {"logstash.version"=>"6.4.0"}
[2019-07-12T13:36:54,756][INFO ][logstash.pipeline        ] Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>2, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>50}
[2019-07-12T13:36:55,556][INFO ][logstash.outputs.datahub ] Init datahub success!
[2019-07-12T13:36:56,663][INFO ][logstash.inputs.file     ] No sincedb_path set, generating one based on the "path" setting {:sincedb_path=>"/root/logstash-with-datahub-6.4.0/data/plugins/inputs/file/.sincedb_d883144359d3b4f516b37dba51fab2a2", :path=>["/var/log/nginx/access.log"]}
[2019-07-12T13:36:56,753][INFO ][logstash.pipeline        ] Pipeline started successfully {:pipeline_id=>"main", :thread=>"#<Thread:0x445e23fb run>"}
[2019-07-12T13:36:56,909][INFO ][logstash.agent           ] Pipelines running {:count=>1, :running_pipelines=>[:main], :non_running_pipelines=>[]}
[2019-07-12T13:36:56,969][INFO ][filewatch.observingtail  ] START, creating Discoverer, Watch with file and sincedb collections
[2019-07-12T13:36:57,650][INFO ][logstash.agent           ] Successfully started Logstash API endpoint {:port=>9600}

这时候可以开始去刷一下Nginx代理的页面了。默认Nginx自带一个静态的网页,可以通过访问80端口打开。产生日志的话,Logstash的日志会马上打印如下信息

[2019-07-12T13:36:58,740][INFO ][logstash.outputs.datahub ] [2010]Put data to datahub success, total 10

然后在DataHub上,可以看到抽样数据如下

sample-on-datahub.jpg

配置ADB

先到ADB的控制台去创建一个新的集群,数据库的名字取nginx_logging。需要注意的是,当ADB创建好之后,在控制台那边看不到数据库的名字,转而变成了集群名称。目前看来称谓不一样,但是其实是一回事。

新的集群初始化会需要一点时间。待初始化完成之后,可以通过控制台的登陆数据库按钮跳转到DMS(数据管理)去创建用于存放日志的数据库。在创建数据库之前,需要先理解ADB的几个核心概念,这样设计出来的表性能才会更佳。

一级分区

要理解一级分区,需要先理解MPP数据库是怎么提升性能的。本文的背景中说到,MPP是可以线性扩展的,但是有一个前提,数据要均匀分布。这样在一个Query过来的时候,才能让尽量多的磁盘被利用起来。在ADB中,数据是否均匀分布,主要取决选择哪个列作为一级分区。千万不要选择数据倾斜的列作为分区列,例如日期,性别,或者存在大量空值的列。在本例中,比较适合的应该是remote_ip这一列。

二级分区

二级分区是在一级分区的基础上做二次切分,可以理解为隐性地帮用户把一个表切成了多个表,从而提升全表查询的性能。此外,二级分区还有一个优点,就是可以设置分区个数。在超过分区个数的时候,ADB会自动将历史最久的一个二级分区删除,实现历史数据自动清楚的效果。在本例中,date这个列特别时候做二级分区。假如我们想保留30天的日志数据,我们只需要将二级分区设置成30个即可。注意,二级分区的列一定要是整数类型,例如bigint或者long

下面是创建表nginx的SQL

CREATE TABLE nginx_logging.nginx(
  remote_ip varchar NOT NULL COMMENT '',
  date bigint NOT NULL COMMENT '',
  time varchar NOT NULL COMMENT '',
  method varchar NOT NULL COMMENT '',
  request varchar COMMENT '',
  http_version varchar COMMENT '',
  status varchar COMMENT '',
  bytes bigint COMMENT '',
  request_time double COMMENT '',
  referer varchar COMMENT '',
  agent varchar COMMENT '',
  xforward varchar COMMENT '',
  cookie varchar COMMENT '',
  PRIMARY KEY (remote_ip,date,time)
)
PARTITION BY HASH KEY (remote_ip) PARTITION NUM 128 -- remote_ip作为一级分区
SUBPARTITION BY LIST KEY (date) -- date作为二级分区
SUBPARTITION OPTIONS (available_partition_num = 30) -- 二级分区30个,代表保留30天的数据
TABLEGROUP logs
OPTIONS (UPDATETYPE='realtime') -- 由于要被DataHub更新,所以一定要选择是realtime的表
COMMENT ''''

成功配置创建表之后,ADB这边的准备任务就算完成了。需要提示一下,默认ADB的网络连接信息只有公有网络经典网络的连接。专有网络的连接地址需要通过配置打开。因为ADB完全兼容MySQL协议,所以我们要从本地登陆的话,可以利用公有网络的地址。而DataHub访问ADB,目前使用的是经典网络的连接。

配置DataConnector

回到刚刚创建的Topic, topic_nginx_log, 下面。右上角有一个按钮叫+DataConnector。这里需要输入几个关于ADB的信息:

Host : #ADB集群经典网络的连接地址
Port : #ADB集群经典网络的端口
Database : nginx_logging #之前建立ADB集群时候输入的名字,同时也是这个ADB集群的名字
Table : nginx #上面建立的表名
Username : <access-key> #RAM用户的access key
Password : <access-secret> #RAM用户的access secret
模式 : replace into #如果主键冲突,会覆盖掉记录

成功配置之后,在DataConnectors下面就可以看到相关的信息了。如果之前DataHub上面已经有数据,现在查询ADB里面的nginx表就可以将这些记录查出来。

sample.jpg

至此,整个数据链路就算搭建完成了。

目录
相关文章
|
2月前
|
XML JSON 监控
告别简陋:Java日志系统的最佳实践
【10月更文挑战第19天】 在Java开发中,`System.out.println()` 是最基本的输出方法,但它在实际项目中往往被认为是不专业和不足够的。本文将探讨为什么在现代Java应用中应该避免使用 `System.out.println()`,并介绍几种更先进的日志解决方案。
58 1
|
3月前
|
设计模式 SQL 安全
PHP中的设计模式:单例模式的深入探索与实践在PHP的编程实践中,设计模式是解决常见软件设计问题的最佳实践。单例模式作为设计模式中的一种,确保一个类只有一个实例,并提供全局访问点,广泛应用于配置管理、日志记录和测试框架等场景。本文将深入探讨单例模式的原理、实现方式及其在PHP中的应用,帮助开发者更好地理解和运用这一设计模式。
在PHP开发中,单例模式通过确保类仅有一个实例并提供一个全局访问点,有效管理和访问共享资源。本文详细介绍了单例模式的概念、PHP实现方式及应用场景,并通过具体代码示例展示如何在PHP中实现单例模式以及如何在实际项目中正确使用它来优化代码结构和性能。
50 2
|
3月前
|
开发者 Python
基于Python的日志管理与最佳实践
日志是开发和调试过程中的重要工具,然而,如何高效地管理和利用日志常常被忽略。本文通过Python中的logging模块,探讨如何使用日志来进行调试、分析与问题排查,并提出了一些实际应用中的优化建议和最佳实践。
|
2月前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了一种结合知识图谱与大型语言模型(LLM)的GraphRAG系统,利用PolarDB、通义千问及LangChain实现。知识图谱通过结构化信息、语义理解和推理等功能,增强了信息检索与自然语言处理效果。PolarDB具备图引擎与向量检索能力,适配知识图谱存储与查询。通义千问处理自然语言,LangChain则整合模型与应用。实战步骤包括环境准备、数据库配置与数据导入,并通过实例展示了图谱与向量联合检索的优越性,提升了问答系统的准确性和实用性。
|
4月前
|
JSON Java fastjson
Java日志通关(五) - 最佳实践
作者日常在与其他同学合作时,经常发现不合理的日志配置以及五花八门的日志记录方式,后续作者打算在团队内做一次Java日志的分享,本文是整理出的系列文章第五篇。
|
4月前
|
SQL 数据库 Java
Hibernate 日志记录竟藏着这些秘密?快来一探究竟,解锁调试与监控最佳实践
【8月更文挑战第31天】在软件开发中,日志记录对调试和监控至关重要。使用持久化框架 Hibernate 时,合理配置日志可帮助理解其内部机制并优化性能。首先,需选择合适的日志框架,如 Log4j 或 Logback,并配置日志级别;理解 Hibernate 的多级日志,如 DEBUG 和 ERROR,以适应不同开发阶段需求;利用 Hibernate 统计功能监测数据库交互情况;记录自定义日志以跟踪业务逻辑;定期审查和清理日志避免占用过多磁盘空间。综上,有效日志记录能显著提升 Hibernate 应用的性能和稳定性。
54 0
|
4月前
|
消息中间件 Prometheus 监控
Producer的监控与日志记录最佳实践
【8月更文第29天】在分布式系统中,消息队列作为关键组件之一,其稳定性和性能至关重要。生产者(Producer)负责生成并发送消息到消息队列中,因此确保生产者的健康运行是非常重要的。本文将探讨如何为生产者设置监控和日志记录,以跟踪其健康状况和性能指标。
73 0
|
5月前
|
存储 分布式计算 监控
日志数据投递到MaxCompute最佳实践
日志服务采集到日志后,有时需要将日志投递至MaxCompute的表中进行存储与分析。本文主要向用户介绍将数据投递到MaxCompute完整流程,方便用户快速实现数据投递至MaxCompute。
225 2
|
6月前
|
运维 监控 Java
系统日志规范及最佳实践
系统日志规范及最佳实践
418 1
系统日志规范及最佳实践
|
6月前
|
监控 Java API
【Spring Boot】深入解密Spring Boot日志:最佳实践与策略解析
【Spring Boot】深入解密Spring Boot日志:最佳实践与策略解析
128 1