一、前言

分布式日志框架服务的实现思路基本是一致的,如下:

  • 日志收集器:微服务中引入日志客户端,将记录的日志发送到日志服务端的收集器,然后以某种方式存储
  • 数据存储:一般使用ElasticSearch分布式存储,把收集器收集到的日志格式化,然后存储到分布式存储中
  • web服务:利用ElasticSearch的统计搜索功能,实现日志查询和报表输出

比较知名的分布式日志服务包括:

  • ELK:elasticsearch、Logstash、Kibana
  • GrayLog

二、GrayLog的优势

业界比较知名的分布式日志服务解决方案是ELK,而我们今天要学习的是GrayLog。为什么呢?
E
LK解决方案的问题:

  1. 不能处理多行日志,比如Mysql慢查询,Tomcat/Jetty应用的Java异常打印
  2. 不能保留原始日志,只能把原始日志分字段保存,这样搜索日志结果是一堆Json格式文本,无法阅读。
  3. 不符合正则表达式匹配的日志行,被全部丢弃。

GrayLog方案的优势:

  1. 一体化方案,安装方便,不像ELK有3个独立系统间的集成问题。
  2. 采集原始日志,并可以事后再添加字段,比如http_status_code,response_time等等。
  3. 自己开发采集日志的脚本,并用curl/nc发送到Graylog Server,发送格式是自定义的GELF,Flunted和Logstash都有相应的输出GELF消息的插件。自己开发带来很大的自由度。实际上只需要用inotifywait监控日志的modify事件,并把日志的新增行用curl/netcat发送到Graylog Server就可。
  4. 搜索结果高亮显示,就像google一样。
  5. 搜索语法简单,比如: source:mongo AND reponse_time_ms:>5000,避免直接输入elasticsearch搜索json语法
  6. 搜索条件可以导出为elasticsearch的搜索json文本,方便直接开发调用elasticsearch rest api的搜索脚本。

三、GrayLog简介

GrayLog是一个轻量型的分布式日志管理平台,一个开源的日志聚合、分析、审计、展示和预警工具。在功能上来说,和 ELK类似,但又比 ELK要简单轻量许多。依靠着更加简洁,高效,部署使用简单的优势很快受到许多公司的青睐。

官网:https://www.graylog.org/
其基本框架如图:

1-GrayLog.png

流程如下:

  • 微服务中的GrayLog客户端发送日志到GrayLog服务端
  • GrayLog把日志信息格式化,存储到Elasticsearch
  • 客户端通过浏览器访问GrayLog,GrayLog访问Elasticsearch
    这里MongoDB是用来存储GrayLog的配置信息的,这样搭建集群时,GrayLog的各节点可以共享配置。

四、部署安装

选择使用Docker来安装。需要安装的包括:

  • MongoDB:用来存储GrayLog的配置信息
  • Elasticsearch:用来存储日志信息
  • GrayLog:GrayLog服务端
    下面将通过docker的方式部署,部署脚本如下:
#部署Elasticsearch
docker run -d \
    --name elasticsearch \
    -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
    -e "discovery.type=single-node" \
    -v es-data:/usr/share/elasticsearch/data \
    -v es-plugins:/usr/share/elasticsearch/plugins \
    --privileged \
    -p 9200:9200 \
    -p 9300:9300 \
elasticsearch:7.17.5

#部署MongoDB(使用之前部署的服务即可)
docker run -d \
--name mongodb \
-p 27017:27017 \
--restart=always \
-v mongodb:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=sl \
-e MONGO_INITDB_ROOT_PASSWORD=123321 \
mongo:4.4

#部署
docker run \
--name graylog \
-p 9000:9000 \
-p 12201:12201/udp \
-e GRAYLOG_HTTP_EXTERNAL_URI=http://192.168.150.101:9000/ \
-e GRAYLOG_ELASTICSEARCH_HOSTS=http://192.168.150.101:9200/ \
-e GRAYLOG_ROOT_TIMEZONE="Asia/Shanghai"  \
-e GRAYLOG_WEB_ENDPOINT_URI="http://192.168.150.101:9000/:9000/api" \
-e GRAYLOG_PASSWORD_SECRET="somepasswordpepper" \
-e GRAYLOG_ROOT_PASSWORD_SHA2=8c6976e5b5410415bde908bd4dee15dfb167a9c873fc4bb8a81f6f2ab448a918 \
-e GRAYLOG_MONGODB_URI=mongodb://sl:123321@192.168.150.101:27017/admin \
-d \
graylog/graylog:4.3

命令解读:

  • 端口信息:
    • -p 9000:9000:GrayLog的http服务端口,9000
    • -p 12201:12201/udp:GrayLog的GELF UDP协议端口,用于接收从微服务发来的日志信息
  • 环境变量
    • -e GRAYLOG_HTTP_EXTERNAL_URI:对外开放的ip和端口信息,这里用9000端口
    • -e GRAYLOG_ELASTICSEARCH_HOSTS:GrayLog依赖于ES,这里指定ES的地址
    • -e GRAYLOG_WEB_ENDPOINT_URI:对外开放的API地址
    • -e GRAYLOG_PASSWORD_SECRET:密码加密的秘钥
    • -e GRAYLOG_ROOT_PASSWORD_SHA2:密码加密后的密文。明文是admin,账户也是admin
    • -e GRAYLOG_ROOT_TIMEZONE="Asia/Shanghai":GrayLog容器内时区
    • -e GRAYLOG_MONGODB_URI:指定MongoDB的链接信息
  • graylog/graylog:4.3:使用的镜像名称,版本为4.3
    访问地址 http://ip:9000/ , 如果可以看到如下界面说明启动成功。

2-启动.png

通过 admin/admin登录,即可看到欢迎页面,目前还没有数据:

3-登录.png

五、收集日志

1、配置Inputs

部署完成GrayLog后,需要配置Inputs才能接收微服务发来的日志数据。

  • 第一步,在System菜单中选择Inputs:

4-GrayLog.png

  • 第二步,在页面的下拉选框中,选择GELF UDP:

5-GrayLog.png

  • 然后点击Launch new input按钮:

6-GrayLog.png

  • 点击save保存:

7-GrayLog.png

可以看到,GELF UDP Inputs 保存成功。

2、集成微服务

现在,GrayLog的服务端日志收集器已经准备好,我们还需要在项目中添加GrayLog的客户端,将项目日志发送到GrayLog服务中,保存到ElasticSearch。
基本步骤如下:

  • 引入GrayLog客户端依赖
  • 配置Logback,集成GrayLog的Appender
  • 启动并测试
    这里,我们以work微服务为例,其他的类似。
  • 导入依赖
<dependency>
    <groupId>biz.paluch.logging</groupId>
    <artifactId>logstash-gelf</artifactId>
    <version>1.15.0</version>
</dependency>
  • 配置Logback,在配置文件中增加 GELF的appender:
<?xml version="1.0" encoding="UTF-8"?>
<!--scan: 当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true。-->
<!--scanPeriod: 设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。-->
<!--debug: 当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。-->
<configuration debug="false" scan="false" scanPeriod="60 seconds">
    <springProperty scope="context" name="appName" source="spring.application.name"/>
    <!--文件名-->
    <property name="logback.appname" value="${appName}"/>
    <!--文件位置-->
    <property name="logback.logdir" value="/data/logs"/>

    <!-- 定义控制台输出 -->
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} - [%thread] - %-5level - %logger{50} - %msg%n</pattern>
        </layout>
    </appender>


    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
        <File>${logback.logdir}/${logback.appname}/${logback.appname}.log</File>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>${logback.logdir}/${logback.appname}/${logback.appname}.%d{yyyy-MM-dd}.log.zip</FileNamePattern>
            <maxHistory>90</maxHistory>
        </rollingPolicy>
        <encoder>
            <charset>UTF-8</charset>
            <pattern>%d [%thread] %-5level %logger{36} %line - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="GELF" class="biz.paluch.logging.gelf.logback.GelfLogbackAppender">
        <!--GrayLog服务地址-->
        <host>udp:192.168.150.101</host>
        <!--GrayLog服务端口-->
        <port>12201</port>
        <version>1.1</version>
        <!--当前服务名称-->
        <facility>${appName}</facility>
        <extractStackTrace>true</extractStackTrace>
        <filterStackTrace>true</filterStackTrace>
        <mdcProfiling>true</mdcProfiling>
        <timestampPattern>yyyy-MM-dd HH:mm:ss,SSS</timestampPattern>
        <maximumMessageSize>8192</maximumMessageSize>
    </appender>

    <!--evel:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,-->
    <!--不能设置为INHERITED或者同义词NULL。默认是DEBUG。-->
    <root level="INFO">
        <appender-ref ref="stdout"/>
        <appender-ref ref="GELF"/>
    </root>
</configuration>
  • 点击search按钮即可看到日志数据:

8-GrayLog.png

六、日志回收策略

到此graylog的基础配置就算完成了,已经可以收到日志数据。
但是在实际工作中,服务日志会非常多,这么多的日志,如果不进行存储限制,那么不久就会占满磁盘,查询变慢等等,而且过久的历史日志对于实际工作中的有效性也会很低。

  • Graylog则自身集成了日志数据限制的配置,可以通过如下进行设置:

9-GrayLog.png

  • 选择Default index set的Edit按钮:

10-GrayLog.png

  • GrayLog有3种日志回收限制,触发以后就会开始回收空间,删除索引:

11-GrayLog.png

分别是:

  • Index Message Count:按照日志数量统计,默认超过20000000条日志开始清理
    • 我们测试时,设置100000即可
  • Index Size:按照日志大小统计,默认超过1GB开始清理
  • Index Message Count:按照日志日期清理,默认日志存储1天

七、搜索语法

在search页面,可以完成基本的日志搜索功能:

12-GrayLog.png

1、搜索语法

搜索语法非常简单,输入关键字或指定字段进行搜索:

#不指定字段,默认从message字段查询
输入:undo

#输入两个关键字,关系为or
undo 统计

#加引号是需要完整匹配
"undo 统计"

#指定字段查询,level表示日志级别,ERROR(3)、WARNING(4)、NOTICE(5)、INFO(6)、DEBUG(7)
level: 6

#或条件
level:(6 OR 7)

更多查询官网文档:https://docs.graylog.org/docs/query-language

2、自定义展示字段

13-GrayLog.png

效果如下:

14-GrayLog.png

八、日志统计仪表盘

GrayLog支持把日志按照自己需要的方式形成统计报表,并把许多报表组合一起,形成DashBoard(仪表盘),方便对日志统计分析。

1、创建仪表盘

15-GrayLog.png

16-GrayLog.png

可以设置各种指标:

1-仪表盘.png

2-仪表盘.png

3-仪表盘.png

4-仪表盘.png

  • 最终效果:

5-仪表盘.png

  • 官方给出的效果:

6-仪表盘.png