Flume + Solr + log4j搭建web日志采集系统

简介: 首先我们有多个web 应用,每个web应用每天都有不断的日志产生,这些日志文件现在以文件的形式存储在服务器当中,我们需要收集这些日志,并对日志进行查询。 所以整个流程就是,Flume agent 收集日志 -> Morphline 进行过滤 -> 对结果进行索引然后在Solr中进行搜索。

前言

很多web应用会选择ELK来做日志采集系统,这里选用Flume,一方面是因为熟悉整个Hadoop框架,另一方面,Flume也有很多的优点。

关于Apache Hadoop Ecosystem 请点击这里。

Cloudera 官方的教程也是基于这个例子开始的,get-started-with-hadoop-tutorial

并且假设我们已经了解Flume(agent, Source, Channel, Sink) , Morphline (ETL), Solr (全文检索),如果都没有了解,请自行百度。

Scenario (需求)

首先我们有多个web 应用,每个web应用每天都有不断的日志产生,这些日志文件现在以文件的形式存储在服务器当中,我们需要收集这些日志,并对日志进行查询

所以整个流程就是,Flume agent 收集日志 -> Morphline 进行过滤 -> 对结果进行索引然后在Solr中进行搜索。

Flume 收集日志

    1、使用 Spooling Directory Source
         就是监视指定目录是否有新文件移入,如果有,就会读取这些Event, 但是文件一旦被移到该目录之后,就不应该被写入,目录               下的文件名也不可重复,这样的情况就是需要定期将文件移动到指定的目录,不能实现实时的读取。
  
    2、使用 Exec Source
         就是通过下面的命令行产生的结果作为源,在agent 死亡或或者机器重启的过程可能会存在数据丢失
agent.sources.execSrc.type = exec
agent.sources.execSrc.shell=/bin/bash -c
agent.sources.execSrc.command= tail -F /var/log/flume/flume.log | grep "error: "
     1、使用消息中间件JMS或者KAFKA
          请参考: 基于Flume+Log4j+Kafka的日志采集架构方案
          客户端直接发送至kafaka queue , 用 log4j KafkaAppender

      2、使用Flume Appender
            对于Java web 应用,我们就最简单直接采取这种方式。 Flume Appender 我们这里就直接采用log4j2 , 关于日志框架的这些说                 明,请看另一片博客 spring boot use log4j log4j 关于flume Appender 的配置

The Flume Appender supports three modes of operation.

    1、It can act as a remote Flume client which sends Flume events via Avro to a Flume Agent configured with an Avro Source.(同                 步,Avro协议)

     2、It can act as an embedded Flume Agent where Flume events pass directly into Flume for processing.(异步,需要维护客户端                  flume)

      3、It can persist events to a local BerkeleyDB data store and then asynchronously send the events to Flume, similar to the    embedded Flume Agent but without most of the Flume dependencies.(先写数据库,再异步发送)

Usage as an embedded agent will cause the messages to be directly passed to the Flume Channel and then control will be immediately returned to the application. All interaction with remote agents will occur asynchronously. Setting the "type" attribute to "Embedded" will force the use of the embedded agent. In addition, configuring agent properties in the appender configuration will also cause the embedded agent to be used.

我们下面就简单的用第一种方式

客户端配置

log4j.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn" name="MyApp" packages="">
  <Appenders>
    <Flume name="eventLogger" compress="true">
      <Agent host="192.168.10.101" port="8800"/>
      <Agent host="192.168.10.102" port="8800"/>
      <RFC5424Layout enterpriseNumber="18060" includeMDC="true" appName="MyApp"/>
    </Flume>
  </Appenders>
  <Loggers>
    <Root level="error">
      <AppenderRef ref="eventLogger"/>
    </Root>
  </Loggers>
</Configuration>

服务端配置

参考:flume log4j appender config

下载 flume, 在conf 目录下,配置example.conf :

# example.conf: A single-node Flume configuration

# Name the components on this agent
a1.sources = r1
a1.sinks = k1
a1.channels = c1

# Describe/configure the source
a1.sources.r1.type = org.apache.flume.clients.log4jappender.Log4jAppender
a1.sources.r1.bind = localhost
a1.sources.r1.port = 44444

# Describe the sink
a1.sinks.k1.type = logger

# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 100

# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

启动 flume

bin/flume-ng agent --conf conf --conf-file example.conf --name a1 -Dflume.root.logger=INFO,console

查看日志,是否成功。

Solr 配置

关于solr的介绍

这里 solr的数据也是需要存储到 hdfs中的,另外solr 是通过zookeeper 来管理的

以下配置,这里用的cloudera manager 安装,所以自动配好了,但是需要检验,如果是手动安装也有对应的文档可以直接查看, 另外这里省略Solr Authentication。

配置 zookeeper service

$ cat /etc/solr/conf/solr-env.sh
export SOLR_ZK_ENSEMBLE=zk01.example.com:2181,zk02.example.com:2181,zk03.example.com:2181/solr

配置 solr use hdfs

$ cat /etc/default/solr
//地址nn01.example.com:8020 是hdfs name node的地址
SOLR_HDFS_HOME=hdfs://nn01.example.com:8020/solr

//To create the /solr directory in HDFS,需要创建/solr hdfs目录:
$ sudo -u hdfs hdfs dfs -mkdir /solr
$ sudo -u hdfs hdfs dfs -chown solr /solr

initializing the ZooKeeper Namespace

$ sudo service solr-server restart

启动solr

$ sudo service solr-server restart

solr collection 配置

solr 通过 collection 来组织逻辑数据,所以你需要创建collection,每个collection有自己的配置,文档上已经讲的比较清楚了,而且也不多,这里不再赘述

Generating Collection Configuration

下面是的collection是用来存储上面收集到的日志:

// 使用默认模版创建instancedir
$ solrctl instancedir --generate $HOME/weblogs_config

// upload instancedir to zookeeper,上传配置
$ solrctl instancedir --create weblogs_config $HOME/weblogs_config

//verify instance  
$ solrctl instancedir --list

// create collection  -s shard_count, collection 和config 关联
$ solrctl collection --create weblogs_collection -s 2 -c weblogs_config

A SolrCloud collection is the top-level object for indexing documents and providing a query interface. Each collection must be associated with an instance directory. Different collections can use the same instance directory. Each collection is typically replicated among several SolrCloud instances. Each replica is called a core and is assigned to an individual Solr service. The assignment process is managed automatically, although you can apply fine-grained control over each individual core using the solrctl core command . 这是 collection 和instance之间关系的介绍

成功创建之后如何修改和扩展,请参考这里solectl usage

Morphline (ETL)

创建好 collection 之后,我们就需要将日志解析存储到solr里,方便检索。Morphline 就是这个中间过程的ETL工具(extracting, transforming and loading data), Flume 提供了Morphlion Solr Sink, 从 log flume的source中读取event,经过ETL导入到solr中。

配置flume

继续上面的flume,中 example.conf 的配置

a1.sources = r1
a1.sinks = k1
a1.channels = c1

# Describe/configure the source
a1.sources.r1.type = avro
a1.sources.r1.bind = 0.0.0.0
a1.sources.r1.port = 4444

# Describe the sink
a1.sinks.k1.type = org.apache.flume.sink.solr.morphline.MorphlineSolrSink
a1.sinks.k1.morphlineFile=morphlines.conf
a1.sinks.k1.morphlineId = morphline_log4j2

# Use a channel which buffers events in memory
a1.channels.c1.type = memory
a1.channels.c1.capacity = 1000
a1.channels.c1.transactionCapacity = 1000

# Bind the source and sink to the channel
a1.sources.r1.channels = c1
a1.sinks.k1.channel = c1

配置Morphline

我们的日志格式文件如下:

[INFO ] 2017-07-14 11:40:51.556 [main] RequestMappingHandlerAdapter - Detected ResponseBodyAdvice bean in apiResponseAdvice

需要解析成:

level: INFO
create_time: 2017-07-14 11:40:51.556
thread: main
class:  RequestMappingHandlerAdapter
 -    //这里有个短横线
message: Detected ResponseBodyAdvice bean in apiResponseAdvice

所以我们使用grok
在线调试工具online tools

 # grok get data from unstructured line 
     { 
        grok {
          dictionaryFiles : [grok-dictionary.conf]
          expressions : {
            message : """\[%{LOGLEVEL:level} \] %{SC_LOGDATETIME:create_time} \[%{DATA:thread}\] %{WORD:class} [-] %{GREEDYDATA:message}"""
          }
        }

      }

      # Consume the output record of the previous command and pipe another
      # record downstream.
      #
      # convert timestamp field to native Solr timestamp format 
      # e.g.  2017-07-14 11:40:52.512 to 2012-09-06T07:14:34.000Z
      {
        convertTimestamp {
          field : create_time
          inputFormats : ["yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd"]
          inputTimezone : America/Los_Angeles
          outputFormat : "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
          outputTimezone : UTC
        }
      }

配置 schema.xml

在上一节,配置solr的时候,我们生成了默认的模版,我们需要根据实际的需求修改schema.xml,在$HOME/weblogs/conf 下

The schema.xml file contains all of the details about which fields your documents can contain, and how those fields should be dealt with when adding documents to the index, or when querying those fields.

schema.xml
solrconfig.xml

   <field name="level" type="text_general" indexed="true" stored="true" multiValued="true"/>
   <field name="create_time" type="date" indexed="true" stored="true"/>
   <field name="thread" type="text_general" indexed="true" stored="true"/>
   <field name="class" type="text_general" indexed="true" stored="true"/>
   <field name="message" type="text_general" indexed="true" stored="true"/>

重新上传配置到zookeeper

$ solrctl instancedir --update weblogs_config $HOME/weblogs_config
$ solrctl collection --reload weblogs_collection

总结

到此为止,我们完成了日志的收集,解析,索引,你可以通过 Hue来进行搜索和查询了,或者自己定义UI。这个教程比较基础也相对简单,但是可以完成基本的需求,也把日志处理流程走了一遍,剩下的大家自定义即可。

文章来源:https://my.oschina.net/tigerlene/blog/1475239

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
5085 32
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
9月前
|
数据采集 缓存 大数据
【赵渝强老师】大数据日志采集引擎Flume
Apache Flume 是一个分布式、可靠的数据采集系统,支持从多种数据源收集日志信息,并传输至指定目的地。其核心架构由Source、Channel、Sink三组件构成,通过Event封装数据,保障高效与可靠传输。
483 1
|
12月前
|
JSON JavaScript 前端开发
实现ROS系统的Websocket传输,向Web应用推送sensor_msgs::Image数据
WebSocket协议具有低延迟和高实时性的特性,适用于实时数据推送。但是,它也依赖于网络条件,因此,在通过WebSocket发送数据时,保证网络稳定性也是重要的。以上步骤为建立基本的WebSocket传输提供了框架,并可以根据实际需求进行调整和优化。
731 0
|
存储 缓存 关系型数据库
图解MySQL【日志】——Redo Log
Redo Log(重做日志)是数据库中用于记录数据页修改的物理日志,确保事务的持久性和一致性。其主要作用包括崩溃恢复、提高性能和保证事务一致性。Redo Log 通过先写日志的方式,在内存中缓存修改操作,并在适当时候刷入磁盘,减少随机写入带来的性能损耗。WAL(Write-Ahead Logging)技术的核心思想是先将修改操作记录到日志文件中,再择机写入磁盘,从而实现高效且安全的数据持久化。Redo Log 的持久化过程涉及 Redo Log Buffer 和不同刷盘时机的控制参数(如 `innodb_flush_log_at_trx_commit`),以平衡性能与数据安全性。
957 5
图解MySQL【日志】——Redo Log
|
监控 Java 应用服务中间件
Tomcat log日志解析
理解和解析Tomcat日志文件对于诊断和解决Web应用中的问题至关重要。通过分析 `catalina.out`、`localhost.log`、`localhost_access_log.*.txt`、`manager.log`和 `host-manager.log`等日志文件,可以快速定位和解决问题,确保Tomcat服务器的稳定运行。掌握这些日志解析技巧,可以显著提高运维和开发效率。
1777 13
|
SQL 关系型数据库 MySQL
MySQL事务日志-Undo Log工作原理分析
事务的持久性是交由Redo Log来保证,原子性则是交由Undo Log来保证。如果事务中的SQL执行到一半出现错误,需要把前面已经执行过的SQL撤销以达到原子性的目的,这个过程也叫做"回滚",所以Undo Log也叫回滚日志。
992 7
MySQL事务日志-Undo Log工作原理分析
|
SQL 存储 关系型数据库
简单聊聊MySQL的三大日志(Redo Log、Binlog和Undo Log)各有什么区别
在MySQL数据库管理中,理解Redo Log(重做日志)、Binlog(二进制日志)和Undo Log(回滚日志)至关重要。Redo Log确保数据持久性和崩溃恢复;Binlog用于主从复制和数据恢复,记录逻辑操作;Undo Log支持事务的原子性和隔离性,实现回滚与MVCC。三者协同工作,保障事务ACID特性。文章还详细解析了日志写入流程及可能的异常情况,帮助深入理解数据库日志机制。
2014 0
|
存储 关系型数据库 MySQL
图解MySQL【日志】——Undo Log
Undo Log(回滚日志)是 MySQL 中用于实现事务原子性和一致性的关键机制。在默认的自动提交模式下,MySQL 隐式开启事务,每条增删改语句都会记录到 Undo Log 中。其主要作用包括:
852 0
|
监控 关系型数据库 MySQL
【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
【01】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-硬件设备实时监控系统运营版发布-本产品基于企业级开源项目Zabbix深度二开-分步骤实现预计10篇合集-自营版
639 0