Spring Cloud集成ELK完成日誌收集實戰(elasticsearch、logstash、kibana)

簡介

對於日誌來說,最常見的需求就是收集、存儲、查詢、展示,開源社區正好有相對應的開源項目:logstash(收集)、elasticsearch(存儲+搜索)、kibana(展示),我們將這三個組合起來的技術稱之爲ELK,所以說ELK指的是Elasticsearch、Logstash、Kibana技術棧的結合。ELK對外作爲一個日誌管理系統的開源方案,能夠可靠和安全地從任何格式的任何來源獲取數據,並實時搜索、分析和可視化。

1 Elasticsearch

elasticsearch是一個高可擴展的、開源的、全文本搜索和分析的引擎。它能夠近乎實時地存儲,檢索和分析大量數據,通常用作底層引擎/技術,爲具有複雜搜索特性和需求的應用程序提供動力。

elasticsearch的底層是開源庫 Lucene。但是,你沒法直接用 Lucene,必須自己寫代碼去調用它的接口。Elastic 是 Lucene 的封裝,提供了 REST API 的操作接口,開箱即用。

1.1節點和集羣

elasticsearch 本質上是一個分佈式數據庫,允許多臺服務器協同工作,每臺服務器可以運行多個 elasticsearch 實例。單個 elasticsearch 實例稱爲一個節點(node)。一組節點構成一個集羣(cluster)

1.2索引(Index)

elasticsearch 會索引所有字段,經過處理後寫入一個反向索引(Inverted Index)。查找數據的時候,直接查找該索引。所以,elasticsearch 數據管理的頂層單位就叫做 Index(索引)。它是單個數據庫的同義詞。每個 Index (即數據庫)的名字必須是小寫。

下面的命令可以查看當前節點的所有 Index。

curl -X GET ‘http://localhost:9200/_cat/indices?v’

1.3文檔(Document)

索引裏面的單條記錄稱爲文檔(Document),多個文檔就組成了一個索引。文檔是用JSON格式表示。同一個索引的文檔不要求有相同的結構(scheme),但是最好保持相同,這樣有利於提高搜索效率。一個簡單的文檔示例:
{
“user”: “張三”,
“profession”: “java工程師”,
}

1.4 碎片和副本

索引可能存儲大量數據,超出單個節點的硬件限制。例如,一個包含10億個文檔的索引佔用了1TB的磁盤空間,它可能不適合於單個節點的磁盤,或者可能太慢,無法單獨爲單個節點提供搜索請求。爲了解決這個問題,Elasticsearch提供了將索引細分爲多個碎片的功能。當你創建索引時,可以簡單地定義你想要的碎片的數量。每個碎片本身都是一個功能齊全、獨立的“索引”,可以駐留在集羣中的任何節點上。

總而言之,每個索引可以分成多個碎片。一個索引也可以被複制零次(意思是沒有副本)或多次。一但複製,每個索引將具有主碎片(原始碎片)和複製碎片(主碎片的副本)。在創建索引時,每個索引可以定義碎片和副本的數量。默認情況下,Elasticsearch中的每個索引分配5個主碎片和1個副本。

關於elasticsearch的深入瞭解請參考elastic官方網站:https://www.elastic.co/cn/

2 Logstash

Logstash是一個開源數據收集引擎,具有實時管道功能。Logstash可以動態地將來自不同數據源的數據統一起來,並將數據標準化到你所選擇的目的地。

2.1管道

logstash的事件處理管道通常具有一個或多個的輸入插件、過濾器、輸出插件。logstash的事件處理通常分爲三個階段:輸入→過濾器→輸出。

2.2輸入

數據往往以各種各樣的形式,或分散或集中地存在於很多系統中。Logstash 支持各種輸入選擇 ,可以在同一時間從衆多常用來源捕捉事件。能夠以連續的流式傳輸方式,輕鬆地從您的日誌、指標、Web 應用、數據存儲以及各種 AWS 服務採集數據。

logstash使用輸入插件實現數據導入。常用的輸入插件如下:

插件 說明
tcp 從TCP套接字讀取事件
http 從http請求中讀取事件
file 從文件中讀取
beats 從Elastic Beats框架接收事件
kafka 從kafka中讀取
rabbitmq 從rabbitmq中讀取
redis 從Redis實例讀取事件
log4j 從Log4j SocketAppender對象通過TCP讀取事件
elasticsearch 從Elasticsearch集羣讀取
jdbc 從jdbc數據中讀取
websocket 從網絡套接字讀取事件

Filebeat客戶端是一個輕量級的、資源友好的工具,它從服務器上的文件中收集日誌,並將這些日誌轉發到你的Logstash實例以進行處理。Filebeat設計就是爲了可靠性和低延遲。Filebeat在主機上佔用的資源很少,而且Beats input插件將對Logstash實例的資源需求降到最低。

關於更多輸入插件參照:
https://www.elastic.co/guide/en/logstash/current/input-plugins.html

2.3 過濾器

數據從源傳輸到存儲庫的過程中,Logstash 過濾器能夠解析各個事件,識別已命名的字段以構建結構,並將它們轉換成通用格式,以便更輕鬆、更快速地分析和實現商業價值。

Logstash 能夠動態地轉換和解析數據,不受格式或複雜度的影響。常用的過濾器如下:

1.grok插件:解析並構造任意文本。Grok是目前Logstash中將非結構化日誌數據解析爲結構化和可查詢內容的最佳方式。有了內置於Logstash的120種模式,很可能會找到滿足需求的模式!

2.ruby插件: 官方對ruby插件的介紹是無所不能。ruby插件可以使用任何的ruby語法,無論是邏輯判斷,條件語句,循環語句,還是對字符串的操作,對EVENT對象的操作,都是極其得心應手的。

3.mutate插件: mutate插件是用來處理數據的格式的。

4.json插件:這個插件也是極其好用的一個插件,現在我們的日誌信息,基本都是由固定的樣式組成的,我們可以使用json插件對其進行解析,並且得到每個字段對應的值。

更多過濾器插件請參考:
https://www.elastic.co/guide/en/logstash/current/filter-plugins.html

2.4 輸出

輸出是Logstash管道的最後階段。事件可以通過多個輸出,但是一旦所有輸出處理完成,事件就完成了它的執行。 Logstash有很多輸出選擇,最常用的是輸出到elasticsearch。常見的輸出還有:

1.elasticsearch
2.File
3.Emial
4.http
5.Kafka
6.Redis
7.MongoDB
8.Rabbitmq
9.Syslog
10.Tcp
11.Websocket
12.Zabbix
13.Stdout
14.Csv

更多輸出插件請參照:
https://www.elastic.co/guide/en/logstash/current/output-plugins.html

3 Kibana

Kibana 是一款開源的數據分析和可視化平臺,它是 Elastic Stack 成員之一,設計用於和 Elasticsearch 協作。您可以使用 Kibana 對 Elasticsearch 索引中的數據進行搜索、查看、交互操作。您可以很方便的利用圖表、表格及地圖對數據進行多元化的分析和呈現。

Kibana 可以使大數據通俗易懂。它很簡單,基於瀏覽器的界面便於您快速創建和分享動態數據儀表板來追蹤 Elasticsearch 的實時數據變化。
更多資料請參考:
https://www.elastic.co/guide/cn/kibana/current/index.html

4 ELK實戰

此方案大致思路如下:
1.應用將日誌傳入kafka。
2.logstash在kafka上消費(讀取)日誌內容,寫入elasticsearch。
3.kibana讀elasticsearch,做對應的展示。

這樣的好處是:
1)幾乎不用做特別大的修改,只需做一定的配置工作即可完成日誌收集;
2)日誌內容輸入kafka幾乎沒有什麼瓶頸,可以做到解耦,另外kafka的擴展性能很好,也很簡單;
3)收集的日誌幾乎是實時的;
4)整體的擴展性很好,很容易消除瓶頸,例如elasticsearch分片、擴展都很容易。

方案架構圖如下:

在這裏插入圖片描述

4.1 使用docker-compose安裝ELK組件

本示例依賴於:

  • jdk8
  • docker 18.06.1
  • docker-compose 1.24.1
  1. 編寫docker-compose.yml 文件

安裝兩個elasticsearch集羣,kibana,logstash

vim docker-compose.yml

文件內容如下:

version: '3'
services:
  elasticsearch:
    image: elasticsearch:7.5.2
    container_name: jdyp-elasticsearch
    environment:
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - node.name=elasticsearch
      - cluster.name=docker-elasticsearch-cluster
      - xpack.security.enabled=false
      - discovery.zen.minimum_master_nodes=1
      - discovery.zen.ping.unicast.hosts=ip:9300, ip:9301
      - http.cors.enabled=true
      - http.cors.allow-origin="*"

    volumes:
      - esdata:/usr/share/elasticsearch/data
    hostname: elasticsearch
    network_mode: host
    restart: always
    ports:
      - 9200:9200
      - 9300:9300
  es-slave:
    image: elasticsearch:7.5.2
    container_name: jdyp-es-slave
    environment:
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - node.name=es-slave
      - cluster.name=docker-elasticsearch-cluster
      - xpack.security.enabled=false
      - discovery.zen.minimum_master_nodes=1
      - discovery.zen.ping.unicast.hosts=ip:9300, ip:9301
      - http.cors.enabled=true
      - http.cors.allow-origin="*" 
    volumes:
      - esdata2:/usr/share/elasticsearch/data
    hostname: es-slave
    network_mode: host
    restart: always
    ports:
      - 9201:9200
      - 9301:9300

  kibana:
    image: kibana:7.5.2
    container_name: jdyp-kibana
    hostname: kibana
    network_mode: host
    environment:
      - ELASTICSEARCH_URL=http://ip:9200
      - ELASTICSEARCH_HOSTS=http://ip:9200
    depends_on:
      - elasticsearch
      - es-slave
    restart: always
    ports:
      - "5601:5601"
  logstash:
    image: logstash:7.5.2
    container_name: jdyp-logstash
    command: logstash -f /etc/logstash/conf.d/logstash.conf
    volumes:
      - ./logstash:/etc/logstash/conf.d
      - /opt/logs/:/opt/build/
    environment:
      - elasticsearch.hosts=http://ip:9200
      # 解決logstash監控連接報錯
      - xpack.monitoring.elasticsearch.hosts=http://ip:9200
    hostname: logstash
    network_mode: host
    restart: always
    depends_on:
      - elasticsearch
      - es-slave
    ports:
      - 9600:9600
      - 5044:5044
volumes:
  esdata:
    driver: local
  esdata2:
    driver: local

2.編寫logstash配置文件

本方案將日誌從kafka輸入,存儲到elasticsearch。
在docker-compose.yml文件目錄下的logstash文件下編寫logstash.conf文件。
vim ./logstash/logstash.conf

文件內容如下:

input {
 
    tcp {
    port => 5044
    codec => "json"
  }
 
    kafka {
      bootstrap_servers => "http://ip:9092" #kafka地址
      topics=>["applog"]
    }
}

filter {
    json {
             source => "message"
         }
}

output{
  elasticsearch {
    hosts => ["ip:9200"]     #elastic地址
    action => "index"
    index => "keyway-log-%{+YYYY.MM.dd}"
    }
  stdout {
    codec => rubydebug
    }
}

3.啓動

在docker-compose.yml同級目錄下使用命令:docker-compose up -d

如果系統中沒有鏡像會先去拉取鏡像,耗時較長需要等待,另外可以配置國內鏡像加速器加快鏡像的拉取速度,這裏選擇阿里雲的鏡像加速器。
阿里雲:https://dev.aliyun.com/search.html
注意阿里雲需要登錄,每個人對應一個地址。登錄之後在鏡像那搜索docker:

在這裏插入圖片描述
然後選擇鏡像加速器:
在這裏插入圖片描述

獲取加速地址後,輸入命令:vim /etc/docker/daemon.json

複製獲取的地址:

{
  "registry-mirrors": ["https://你的地址"]
}

保存退出,然後重啓docker:

sudo systemctl daemon-reload

sudo systemctl restart docker

等待完成後輸入 docker ps 查看部署的容器,如果存在則說明部署成功了。然後輸入 curl:http://localhost://127.0.0.1:9200,如果出現如下界面則說明elasticsearch部署成功:

在這裏插入圖片描述

接下來在瀏覽器輸入 ip:5601,如果出現以下界面則說明kibana安裝成功:
在這裏插入圖片描述

另外。由於日誌採用kafka輸入,因此還需要安裝kafka

  1. 部署kafka

編寫docker-compose.yml文件

cd /opt/docker/kafka (可以是任意你想要的目錄)

vim docker-compose.yml

文件內容如下:

version: '3'
services:
  zookeeper:
    image: wurstmeister/zookeeper
    container_name: jdyp-zoo1
    ports:
      - "2181:2181"
    network_mode: host
  kafka:
    image: wurstmeister/kafka
    container_name: jdyp-kafka
    depends_on:
      - zookeeper
    network_mode: host
    ports:
      - "9092:9092"
    environment:
      KAFKA_BROKER_ID: 5
      KAFKA_ZOOKEEPER_CONNECT: 192.168.7.211:2181
      KAFKA_LISTENERS: PLAINTEXT://0.0.0.0:9092
      KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://192.168.7.211:9092  #宿主機監聽端口
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

在docker-compose.yml同級目錄下執行命令:docker-compose up -d

執行完後,可以通過命令 docker ps查看容器是否啓動成功,啓動成功後可以進入容器測試kafka功能是否正常。

進入容器指令:docker exec -it kafka的容器id /bin/bash

此次,Spring Cloud整合ELK的準備工作就完成了。

4.2 Spring Cloud集成 ELK

Spring Cloud版本:Spring cloud Finchley.SR2

4.2.1 pom文件引入依賴

 <!--引入logback日誌輸出配置,這時由於kafka綁定的是日誌事件-->
<dependency>
    <groupId>net.logstash.logback</groupId>
    <artifactId>logstash-logback-encoder</artifactId>
    <version>5.2</version>
</dependency>
<dependency>
    <groupId>com.github.danielwegener</groupId>
    <artifactId>logback-kafka-appender</artifactId>
    <version>0.1.0</version>
</dependency>

4.2.2 配置文件

添加logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true">
    <appender name="KafkaAppender" class="com.github.danielwegener.logback.kafka.KafkaAppender">
        <encoder class="com.github.danielwegener.logback.kafka.encoding.LayoutKafkaMessageEncoder">
            <layout class="net.logstash.logback.layout.LogstashLayout" >
                <includeContext>true</includeContext>
                <includeCallerData>true</includeCallerData>
                <customFields>{"system":"service-1"}</customFields>
<!--                <fieldNames class="net.logstash.logback.fieldnames.ShortenedFieldNames"/>-->
            </layout>
            <charset>UTF-8</charset>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter"><!-- 只打印info及其以上的日誌 -->
            <level>INFO</level>
            <!--<onMatch>ACCEPT</onMatch>-->
            <!--<onMismatch>DENY</onMismatch>-->
        </filter>
        <!--kafka topic -->
        <topic>applog</topic>
        <keyingStrategy class="com.github.danielwegener.logback.kafka.keying.HostNameKeyingStrategy" />
        <deliveryStrategy class="com.github.danielwegener.logback.kafka.delivery.AsynchronousDeliveryStrategy" />
        <producerConfig>bootstrap.servers=ip:9092</producerConfig>
    </appender>
       <root level="info">
        <appender-ref ref="KafkaAppender"/>
    </root>

</configuration>

注意: bootstrap.servers=ip:9092填寫你自己的kafka所在服務器的ip地址

application指定日誌文件
logging:
config: classpath:logback.xml

至此,Spring Cloud整合ELK已經弄好了。調用微服務接口,然後就可以在kibana上看到日誌信息,如圖所示:
在這裏插入圖片描述

發佈了94 篇原創文章 · 獲贊 94 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章