Logstash读取Kafka数据写入HDFS详解
强大的功能,丰富的插件,让logstash在数据处理的行列中出类拔萃
通常日志数据除了要入ES提供实时展示和简单统计外,还需要写入大数据集群来提供更为深入的逻辑处理,前边几篇ELK的文章介绍过利用logstash将kafka的数据写入到elasticsearch集群,这篇文章将会介绍如何通过logstash将数据写入HDFS
本文所有演示均基于logstash 6.6.2版本
数据收集
logstash默认不支持数据直接写入HDFS,官方推荐的output插件是webhdfs
,webhdfs使用HDFS提供的API将数据写入HDFS集群
插件安装
插件安装比较简单,直接使用内置命令即可
# cd /home/opt/tools/logstash-6.6.2
# ./bin/logstash-plugin install logstash-output-webhdfs
配置hosts
HDFS集群内通过主机名进行通信所以logstash所在的主机需要配置hadoop集群的hosts信息
# cat /etc/hosts
192.168.107.154 master01
192.168.107.155 slave01
192.168.107.156 slave02
192.168.107.157 slave03
如果不配置host信息,可能会报下边的错
[WARN ][logstash.outputs.webhdfs ] Failed to flush outgoing items
logstash配置
kafka里边的源日志格式可以参考这片文章:ELK日志系统之使用Rsyslog快速方便的收集Nginx日志
logstash的配置如下:
# cat config/indexer_rsyslog_nginx.conf
input {
kafka {
bootstrap_servers => "10.82.9.202:9092,10.82.9.203:9092,10.82.9.204:9092"
topics => ["rsyslog_nginx"]
codec => "json"
}
}
filter {
date {
match => ["time_local","dd/MMM/yyyy:HH:mm:ss Z"]
target => "time_local"
}
ruby {
code => "event.set('index.date', event.get('time_local').time.localtime.strftime('%Y%m%d'))"
}
ruby {
code => "event.set('index.hour', event.get('time_local').time.localtime.strftime('%H'))"
}
}
output {
webhdfs {
host => "master01"
port => 50070
user => "hadmin"
path => "/logs/nginx/%{index.date}/%{index.hour}.log"
codec => "json"
}
stdout { codec => rubydebug }
}
logstash配置文件分为三部分:input、filter、output
input指定源在哪里,我们是从kafka取数据,这里就写kafka集群的配置信息,配置解释:
- bootstrap_servers:指定kafka集群的地址
- topics:需要读取的topic名字
- codec:指定下数据的格式,我们写入的时候直接是json格式的,这里也配置json方便后续处理
filter可以对input输入的内容进行过滤或处理,例如格式化,添加字段,删除字段等等
- 这里我们主要是为了解决生成HDFS文件时因时区不对差8小时导致的文件名不对的问题,后边有详细解释
output指定处理过的日志输出到哪里,可以是ES或者是HDFS等等,可以同时配置多个,webhdfs主要配置解释:
- host:为hadoop集群namenode节点名称
- user:为启动hdfs的用户名,不然没有权限写入数据
- path:指定存储到HDFS上的文件路径,这里我们每日创建目录,并按小时存放文件
- stdout:打开主要是方便调试,启动logstash时会在控制台打印详细的日志信息并格式化方便查找问题,正式环境建议关闭
webhdfs还有一些其他的参数例如compression
,flush_size
,standby_host
,standby_port
等可查看官方文档了解详细用法
启动logstash
# bin/logstash -f config/indexer_rsyslog_nginx.conf
因为logstash配置中开了stdout
输出,所以能在控制台看到格式化的数据,如下:
{
"server_addr" => "172.18.90.17",
"http_user_agent" => "Mozilla/5.0 (iPhone; CPU iPhone OS 10_2 like Mac OS X) AppleWebKit/602.3.12 (KHTML, like Gecko) Mobile/14C92 Safari/601.1 wechatdevtools/1.02.1902010 MicroMessenger/6.7.3 Language/zh_CN webview/ token/e7b92168159736c30401a55589317d8c",
"remote_addr" => "172.18.101.0",
"status" => 200,
"http_referer" => "https://ops-coffee.cn/wx02935bb29080a7b4/devtools/page-frame.html",
"upstream_response_time" => "0.056",
"host" => "ops-coffee.cn",
"request_uri" => "/api/community/v2/news/list",
"request_time" => 0.059,
"upstream_status" => "200",
"@version" => "1",
"http_x_forwarded_for" => "192.168.106.100",
"time_local" => 2019-03-18T11:03:45.000Z,
"body_bytes_sent" => 12431,
"@timestamp" => 2019-03-18T11:03:45.984Z,
"index.date" => "20190318",
"index.hour" => "19",
"request_method" => "POST",
"upstream_addr" => "127.0.0.1:8181"
}
查看hdfs发现数据已经按照定义好的路径正常写入
$ hadoop fs -ls /logs/nginx/20190318/19.log
-rw-r--r-- 3 hadmin supergroup 7776 2019-03-18 19:07 /logs/nginx/20190318/19.log
至此kafka到hdfs数据转储完成
遇到的坑
HDFS按小时生成文件名不对
logstash在处理数据时会自动生成一个字段@timestamp
,默认情况下这个字段存储的是logstash收到消息的时间,使用的是UTC时区,会跟国内的时间差8小时
我们output到ES或者HDFS时通常会使用类似于rsyslog-nginx-%{+YYYY.MM.dd}
这样的变量来动态的设置index或者文件名,方便后续的检索,这里的变量YYYY
使用的就是@timestamp
中的时间,因为时区的问题生成的index或者文件名就差8小时不是很准确,这个问题在ELK架构中因为全部都是用的UTC时间且最终kibana展示时会自动转换我们无需关心,但这里要生成文件就需要认真对待下了
这里采用的方案是解析日志中的时间字段time_local
,然后根据日志中的时间字段添加两个新字段index.date
和index.hour
来分别标识日期和小时,在output的时候使用这两个新加的字段做变量来生成文件
logstash filter配置如下:
filter {
# 匹配原始日志中的time_local字段并设置为时间字段
# time_local字段为本地时间字段,没有8小时的时间差
date {
match => ["time_local","dd/MMM/yyyy:HH:mm:ss Z"]
target => "time_local"
}
# 添加一个index.date字段,值设置为time_local的日期
ruby {
code => "event.set('index.date', event.get('time_local').time.localtime.strftime('%Y%m%d'))"
}
# 添加一个index.hour字段,值设置为time_local的小时
ruby {
code => "event.set('index.hour', event.get('time_local').time.localtime.strftime('%H'))"
}
}
output的path中配置如下
path => "/logs/nginx/%{index.date}/%{index.hour}.log"
HDFS记录多了时间和host字段
在没有指定codec的情况下,logstash会给每一条日志添加时间和host字段,例如:
源日志格式为
ops-coffee.cn | 192.168.105.91 | 19/Mar/2019:14:28:07 +0800 | GET / HTTP/1.1 | 304 | 0 | - | 0.000
经过logstash处理后多了时间和host字段
2019-03-19T06:28:07.510Z %{host} ops-coffee.cn | 192.168.105.91 | 19/Mar/2019:14:28:07 +0800 | GET / HTTP/1.1 | 304 | 0 | - | 0.000
如果不需要我们可以指定最终的format只取message,解决方法为在output中添加如下配置:
codec => line {
format => "%{message}"
}
同时output到ES和HDFS
在实际应用中我们需要同时将日志数据写入ES和HDFS,那么可以直接用下边的配置来处理
文章未完,全部内容请关注公众号【运维咖啡吧】或个人网站https://ops-coffee.cn查看,运维咖啡吧专注于原创精品内容分享,感谢您的支持
Logstash读取Kafka数据写入HDFS详解的更多相关文章
- Java+大数据开发——HDFS详解
1. HDFS 介绍 • 什么是HDFS 首先,它是一个文件系统,用于存储文件,通过统一的命名空间--目录树来定位文件. 其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角 ...
- flink---实时项目--day02-----1. 解析参数工具类 2. Flink工具类封装 3. 日志采集架构图 4. 测流输出 5. 将kafka中数据写入HDFS 6 KafkaProducer的使用 7 练习
1. 解析参数工具类(ParameterTool) 该类提供了从不同数据源读取和解析程序参数的简单实用方法,其解析args时,只能支持单只参数. 用来解析main方法传入参数的工具类 public c ...
- HDFS详解
HDFS详解大纲 Hadoop HDFS 分布式文件系统DFS简介 HDFS的系统组成介绍 HDFS的组成部分详解 副本存放策略及路由规则 命令行接口 Java接口 客户端与HDFS的数据流讲解 目标 ...
- Python API 操作Hadoop hdfs详解
1:安装 由于是windows环境(linux其实也一样),只要有pip或者setup_install安装起来都是很方便的 >pip install hdfs 2:Client——创建集群连接 ...
- spark读取kafka数据 createStream和createDirectStream的区别
1.KafkaUtils.createDstream 构造函数为KafkaUtils.createDstream(ssc, [zk], [consumer group id], [per-topic, ...
- php中读取大文件实现方法详解
php中读取大文件实现方法详解 来源: 时间:2013-09-05 19:27:01 阅读数:6186 分享到:0 [导读] 本文章来给各位同学介绍php中读取大文件实现方法详解吧,有需要了解 ...
- 10.Spark Streaming源码分析:Receiver数据接收全过程详解
原创文章,转载请注明:转载自 听风居士博客(http://www.cnblogs.com/zhouyf/) 在上一篇中介绍了Receiver的整体架构和设计原理,本篇内容主要介绍Receiver在 ...
- flume 读取kafka 数据
本文介绍flume读取kafka数据的方法 代码: /************************************************************************* ...
- SparkStreaming直连方式读取kafka数据,使用MySQL保存偏移量
SparkStreaming直连方式读取kafka数据,使用MySQL保存偏移量 1. ScalikeJDBC 2.配置文件 3.导入依赖的jar包 4.源码测试 通过MySQL保存kafka的偏移量 ...
随机推荐
- ORACLE环境变量定义
export在linux的bash中可以理解为设置环境变量.设置后能够被当前的shell及子shell使用. 这些变量的含义有一些有意义,可以查看相应的文档,我给你解释一些我知道的: ORACLE_H ...
- 移动端的dl
https://blog.csdn.net/u013139259/article/details/52143240
- 动手动脑——JAVA语法基础
EnumTest.java public class EnumTest { public static void main(String[] args) { Size s=Size.SMALL; Si ...
- go包之logrus显示日志文件与行号
前言: logrus是go中比较好的一个log模块.github上的很多开源项目都在使用这个模块, 我在写这个博文时, github上的logrus的stars数已经有8214了.最近在用这个模块时, ...
- 集腋成裘-03-css基础-02
1.1 三种写法 内嵌式:样式只作用于当前文件,没有真正实现结构表现分离 外链式:作用范围是当前站点,真正实现了内容与表现分离 行内样式:仅限于当前标签,结构混在一起 1.2 标签分类 1.2.1 块 ...
- tomcat和server安装和操作
servers的创建 最后一步:ctrl+s
- jQuery常见案例
jQuery常见案例 通过jQuery实现全选,反选取消: 选择 地址 端口 1.1.1.1 80 1.1.1.1 80 1.1.1.1 80 1.1.1.1 80 代码实现 <body> ...
- Redis cluster集群模式的原理
redis cluster redis cluster是Redis的分布式解决方案,在3.0版本推出后有效地解决了redis分布式方面的需求 自动将数据进行分片,每个master上放一部分数据 提供内 ...
- 一脸懵逼学习HBase---基于HDFS实现的。(Hadoop的数据库,分布式的,大数据量的,随机的,实时的,非关系型数据库)
1:HBase官网网址:http://hbase.apache.org/ 2:HBase表结构:建表时,不需要指定表中的字段,只需要指定若干个列族,插入数据时,列族中可以存储任意多个列(即KEY-VA ...
- CentOS6— Redis安装(转和延续)
Part I. Redis安装(转载部分) 一.安装(官网地址 http://redis.io/download) wget http://download.redis.io/redis-stable ...