微服務日志知識點匯總


使用 Spring Boot 日志框架

為什么使用日志框架?

  1. 日志可以輸出到文件中,而不是輸出到應用程序的控制台中,這樣更容易收集和分析
  2. 可以通過異步多線程的方式,將日志輸出到文件中,這樣不會影響主線程,可以提高程序的吞吐量,節約性能。

通常使用的日志框架有 Log4J 等。

如何在 Spring Boot 中添加日志框架呢?Spring Boot 自帶了一款名為 Spring Boot Logging 的插件,它已經為我們提供了日志實現。

使用 Spring Boot Logging 插件

Spring Boot 使用 Commons Logging 作為內部的日志框架,而它是一個日志接口,在實際應用中,我們需要為該接口提供相應的日志實現。Spring 的默認日志實現是 Java.Util.Logging,它是 JDK 自帶的日志包,一般場景下很少被用到。Spring Boot 也提供了 Log4J, Logback 這類流行的日志實現,我們只要添加簡單的配置,就能開啟對這些日志的實現。

在 Java 應用程序中,日志一般分為 5 個級別: ERROR,WARN,INFO,DEBUG,TRACE。

Spring Boot Logging 默認輸出到 INFO 級別,如果希望日志可以輸出到 DEBUG 級別,需要在 application.yml 中添加如下配置

logging:
  level:
    root: DEBUG

在 java 文件中添加

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

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

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

就可以在運行代碼時看到 debug 級別的日志了。

如果不想關注 Spring Boot 框架的日志,則可將日志級別統一設置成 ERROR ,此時只會輸出 ERROR 級別的日志。隨后,將 Spring Boot 應用程序指定的包設置成 DEBUG 級別的日志,就能看到只有指定包的日志了。

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: 合並多行文本


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM