微服務日誌知識點彙總

使用 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: 合併多行文本
相關文章
相關標籤/搜索