微服务日志知识点汇总

使用 Spring Boot 日志框架

为何使用日志框架?

  1. 日志能够输出到文件中,而不是输出到应用程序的控制台中,这样更容易收集和分析
  2. 能够经过异步多线程的方式,将日志输出到文件中,这样不会影响主线程,能够提升程序的吞吐量,节约性能。

一般使用的日志框架有 Log4J 等。java

如何在 Spring Boot 中添加日志框架呢?Spring Boot 自带了一款名为 Spring Boot Logging 的插件,它已经为咱们提供了日志实现。linux

使用 Spring Boot Logging 插件

Spring Boot 使用 Commons Logging 做为内部的日志框架,而它是一个日志接口,在实际应用中,咱们须要为该接口提供相应的日志实现。Spring 的默认日志实现是 Java.Util.Logging,它是 JDK 自带的日志包,通常场景下不多被用到。Spring Boot 也提供了 Log4J, Logback 这类流行的日志实现,咱们只要添加简单的配置,就能开启对这些日志的实现。nginx

在 Java 应用程序中,日志通常分为 5 个级别: ERROR,WARN,INFO,DEBUG,TRACE。redis

Spring Boot Logging 默认输出到 INFO 级别,若是但愿日志能够输出到 DEBUG 级别,须要在 application.yml 中添加以下配置spring

logging:
  level:
    root: DEBUG

在 java 文件中添加docker

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

...
 
private static Logger logger = LoggerFactory.getLogger(HelloController.class);

...
logger.debug("log ...");

就能够在运行代码时看到 debug 级别的日志了。shell

若是不想关注 Spring Boot 框架的日志,则可将日志级别统一设置成 ERROR ,此时只会输出 ERROR 级别的日志。随后,将 Spring Boot 应用程序指定的包设置成 DEBUG 级别的日志,就能看到只有指定包的日志了。json

logging:
  level:
    root: ERROR
    demo:
      msa: DEBUG

默认状况下日志框架会将日志输出到控制台中,须要在 application.yml 文件中加入下面配置,才能将日志输出到文件中。浏览器

logging:
  level:
    root: ERROR
    demo:
      msa: DEBUG
  file: hello.log

集成 Log4J日志框架

首先须要在 pom.xml 中添加以下 Maven 配置,就能在 Spring Boot 中集成 Log4J。

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-log4j2</artifactId>
    </dependency>

在第一段中,先排除掉默认的 Logback 日志功能。在第二段的 dependency 配置中,咱们自行添加 spring-boot-starter-log4j2 依赖,它是 Spring Boot 提供的 Log4J 插件。

配置完成 Maven 依赖配置后,下面须要在 resources 目录下添加 log4j2.xml 文件,具体内容以下

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appenders>
        <File name="file" fileName="${sys:user.home}/logs/hello.log">
            <PatternLayout pattern="%d{HH:mm:ss:SSS} %p %c (%L) - %m%n"/>
        </File>
    </appenders>

    <loggers>
        <root level="ERROR">
            <appender-ref ref="file"/>
        </root>
        <logger name="demo.msa" level="DEBUG" />
    </loggers>
</configuration>

这个配置文件分红两部分, appendersloggers 。经过以上配置,就将 Log4j 集成到 Spring Boot 应用中。虽然日志已经成功输出到了文件中,但咱们的微服务是以 Docker 容器的方式来运行的,此时输出的日志文件仍然和应用程序在一个 Docker 容器中,咱们得想办法将日志文件输出到 Docker 容器外。也就是将数据和程序分离,以便后续更方便的获取并分析日志内容。

将日志输出到 Docker 容器外

最经常使用的方法就是,经过 Docker 数据卷的方式,将文件路径挂载到 Docker 容器上,这样日志文件天然与 Docker 文件分离了。启动命令以下

[tomcat@ ~]$ docker run -v ~/logs:/root/logs -d -p 18080:8081 demo.msa/mesa-hello:0.0.1-SNAPSHOT

这样就能够随时在宿主机上查看 Docker 容器内部的日志了。但咱们还须要到文件中去查看,使用 docker logs 的方式获取日志内容则不会有此限制,一块儿来看下。

使用 Docker 容器日志

使用 docker logs 命令能够随时查看 Docker 容器内部应用程序运行时产生的日志,这样就能够避免首先进入 Docker 容器,在打开应用程序的过程了。

Docker logs 的执行过程以下: 它会监控容器中操做系统的标准输出设备 (STDOUT), 一旦 STDOUT 有产生,就会将这些数据传输到另外一个设备中,该设备在 Docker 的世界中被称为日志驱动(Logging Driver)。

Docker 日志驱动

以 nginx 为例,经过下面 Docker 命令启动 Nginx 容器

docker run -d -p 80:80 --name nginx nginx

打开浏览器,在地址栏输入 http://localhost:80,就能够看到 nginx 的首页。这时就可使用 docker logs 命令,查看 Nginx 容器的日志。

docker logs -f nginx

其中 -f 是指监控日志尾部的意思。

由此看出,只要 Docker 容器内部的应用程序在控制台中有日志输出,就能经过 docker logs 命令来查看响应的日志。那么 Docker 是如何作到的呢?

首先来执行下 命令

docker info |grep "Logging Driver"

能够获得 Docker 当前设置的日志驱动类型,就是 json-file

json-file 表示 JSON 文件,就是说 Docker 容器内部的应用程序输出的日志,将自动写入一个 JSON 文件中,并存放在 /var/lib/docker/containers/<container_id>目录中 <container_id>-json.log ,它就是要找的日志文件。

json-file 只是 Docker 日志驱动的一个默认选项,除了这个选项,咱们还能够显式的指定其余的类型:

  • none 不输出任何日志
  • syslog 容器输出的日志写入宿主机的 Syslog
  • ...

咱们能够在 docker run 命令中经过 --log-driver 参数来设置具体的 Docker 日志驱动。而且能够经过 --log-opt 参数来指定对应日志驱动的相关选项。就拿默认的 json-file 来讲,能够这样来启动 Docker 容器。

docker run -d -p 80:80 --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 --name nginx nginx:1.14

--log-opt 参数有两个选项:

  • max-file 表示 JSON 文件最多为 3 个
  • max-size 表示 JSON 文件最大为 10M,超过 10M 会自动生成新文件

在上面这些日志驱动类型,最为经常使用的是 Syslog, 它是 Linux 的日志系统,不少日志分析工具均可以从 Syslog 获取日志。好比流行的 ELK 日志中心,它包括下面 3 个部分

  • 日志存储 Elasticsearch
  • 日志收集 Logstash
  • 日志查询 Kibana 负责

在这 3 个组件中, Logstash 用于收集日志, Syslog 写入的日志可转发到 Logstash 中,随后会存储到 Elasticsearch 中。

使用 Docker 容器日志

Linux 日志系统:Syslog

默认状况下,Linux 操做系统已经安装了 syslog 软件包,叫作 Rsyslog。Rsyslog 是 syslog 标准的一种实现。

能够经过下面命令能够查看 Rsyslog 是否已经安装。

rsyslogd -v

若是要开启 Rsyslog 服务,必须对 Rsyslog进行配置,打开配置文件

vi /etc/rsyslog.conf

手工开启(去掉配置前面的注释),启动 TCP 连接的 Rsyslog 的 514 端口。

# Provides TCP syslog reception
$ModLoad imtcp
$InputTCPServerRun 514

配置文件修改完毕后,手工重启 Rsyslog 服务。

service rsyslog restart
or
systemctl restart rsyslog

检查下本地是否对外开启了 514 端口。

[root@ ~]# netstat -anpt |grep 514
tcp        0      0 0.0.0.0:514                 0.0.0.0:*                   LISTEN      63516/rsyslogd
tcp        0      0 :::514                      :::*                        LISTEN      63516/rsyslogd

下面就启动 Nginx 容器,并选择 Syslog 做为日志驱动。

docker run -d -p 80:80 --log-driver syslog --log-opt syslog-address=tcp://localhost:514 --name nginx nginx

其中

  • --log-driver 表示指定 Syslog 为日志驱动
  • --log-opt 指定了 Docker 环境能够经过 TCP 协议链接本地的 514 端口

可使用下面命令来查看 linux 系统日志文件,该文件的内容就是 Syslog 所生成的日志

tail -f /var/log/messages

一般会在一台宿主机上同时运行多个 Docker 容器,若是每一个容器都经过 Syslog 来聚合日志,那么在系统日志文件经过 Docker 容器的 ID 是很难识别出是哪一个容器的。如何能区分某条日志是来自哪一个容器呢?

Docker 日志驱动已经为咱们提供了支持,只须要在 --log-opt 参数中添加一个 tag 选项,并在这个选项上给出恰当的命名,就能更好的识别出相应的日志。

docker run -d -p 80:80 --log-driver syslog --log-opt syslog-address=tcp://localhost:514 --log-opt tag="nginx" nginx:1.14

将 tag 选项设置成 nginx (容器名称),就能在日志中看到带有 nginx 的标识,这样咱们能够更加容易的识别这条日志来自 Nginx 容器。

若是不指定 tag 选项,则默认的 tag 为容器 ID 的前 12 个字符。也能够在 tag 选项中使用 Docker 已经提供的模板标签,可将这些标签理解为 tag 选项中的占位符。

  • {{.ID}} : 容器 ID 的前 12 个字符
  • {{.FullID}} 容器 ID 的完整名称
  • {{.Name}} 容器名称
  • {{.ImageID}} 容器镜像 ID 的前 12 个字符
  • {{.ImageName}} 容器镜像名称

下面将这些 tag 标签来个大融合

docker run -d -p 80:80 -v /etc/localtime:/etc/localtime --log-driver syslog --log-opt syslog-address=tcp://localhost:514 --log-opt tag="{{.ImageName}}/{{.Name}}/{{.ID}}" nginx:1.14

docker 时区问题

docker run -d -p 80:80 -v /etc/localtime:/etc/localtime --log-driver syslog --log-opt syslog-address=tcp://localhost:514 --log-opt tag="{{.ImageName}}/{{.Name}}/{{.ID}}" nginx:1.14

重点是 -v /etc/localtime:/etc/localtime 固然还有其余方法,可参考这篇连接 http://www.cnblogs.com/zengming/p/10190317.html

Docker 日志架构

Docker 容器中的应用程序 Application 将日志吸入到标准输出设备 STDOUT, Docker Daemon 负责从 STDOUT 中获取日志,并将日志写入对应的日志驱动中。

Docker日志架构

当应用程序的日志从 Docker 容器内部写入宿主机的 Syslog 中后,后面咱们要作的就是将 Syslog 中的日志转发到 ELK 平台的 Logstash 中,从而创建咱们须要的日志中心

搭建应用日志中心

开源日志中心: ELK

Elastic 官方推出了 6 款开源产品

  • Kibana: 用于数据可视化
  • Elasticsearch: 用于数据搜索,分析与存储
  • Logstash: 用于数据收集,将数据存入 Elasticsearch 中
  • Beats: 用于数据传输,将数据从磁盘传输到 Logstash 中
  • X-Pack: 提供了一些扩展功能,包括安全,预警,监控,报表和图形化等
  • Elasticsearch Cloud: 提供 Elastic 栈的云服务,提供公有云与私有云的解决方案

日志收集系统

Logstash 是一款开源的数据收集引擎,它既提供了实时管道数据能力,也提供了灵活的插件机制。咱们能够自由选择已有的插件,也能自行开发所需的插件。咱们使用 Logstash 更多的时候都在作参数配置,以实现咱们所需的功能。

从系统架构的角度来看,它提供了 3 个内部组件,分别是输入组件,过滤组件,输出组件,并且每一个组件都提供了插件机制。能够将这些组件及其插件想象成一个管道(pipeline),数据从数据源(Data Source)流向 INPUTS,FILTERS,OUTPUT,最终到达 Elasticsearch 中存储。

上面 3 个组件包含的经常使用插件以下:

  1. 输入插件
    1. file: 读取文本文件
    2. syslog: 读取 syslog,包含 Rsyslog
    3. redis: 读取 Redis 消息队列
    4. beats: 处理 Filebeat 事件
  2. 过滤插件
    1. grok: 解析日志文本
    2. mutate: 修改事件字段
    3. drop: 删除事件
    4. clone: 复制事件
    5. geoip: 添加 IP 地理位置
  3. 输出插件
    1. elasticsearch: 写入 elasticsearch
    2. file: 写入文本文件
    3. graphite: 一种开源工具,用于存储与图形化指标
    4. statsd: 写入 statsd 统计服务,监听 UDP 端口
  4. 编解码插件
    1. json:编解码为 json 格式
    2. multiline: 合并多行文本
相关文章
相关标签/搜索