一、ELK應用場景
在復雜的企業應用服務群中,記錄日志方式多種多樣,並且不易歸檔以及提供日志監控的機制。無論是開發人員還是運維人員都無法准確的定位服務、服務器上面出現的種種問題,也沒有高效搜索日志內容從而快速定位問題的方式。因此需要一個集中式、獨立的、搜集管理各個服務和服務器上的日志信息,集中管理,並提供良好的UI界面進行數據展示,處理分析。
得此:ELK提供一套開源的解決方案,能高效、簡便的滿足以上場景。
二、ELK日志系統介紹
1、ELK分別是Elasticsearch、Logstash、Kibana三個開源框架縮寫。
框架 | 簡介 | 作用 |
Elasticsearch | 開源分布式搜索引擎,提供存儲、分析、搜索功能。特點:分布式、基於reasful風格、支持海量高並發的准實時搜索場景、穩定、可靠、快速、使用方便等。 | 接收搜集的海量結構化日志數據,並提供給kibana查詢分析 |
Logstash | 開源日志搜集、分析、過濾框架,支持多種數據輸入輸出方式。 | 用於收集日志,對日志進行過濾形成結構化數據,並轉發到elasticsearch中 |
Kibana | 開源日志報表系統,對elasticsearch以及logstash有良好的web頁面支持。 | 對elasticsearch提供的數據進行分析展示 |
2、與Logstash的直接集成有兩種方式:
2.1、Logstash與微服務應用安裝在一起,監聽日志文件
2.2、Logstash獨立部署,微服務節點通過網絡向Logstash發送日志信息。
3、間接集成(兩種方式)
1、每個應用節點部署一個輕量級日志采集框架Beats,再由Beats對接統一的Logstash
由於Logstash消耗資源大,而服務器資源相當寶貴,所以引進另一個輕量級日志采集框架Beats,其中包含以下6種
Packetbeat | 用於搜集網絡流量數據 |
Heartbeat |
用於運行時間監控 |
Filebeat | 用於搜集文件數據 |
Winlogbeat | 用於搜集winodws事件數據 |
Metricbeat | 用於指標 |
Auditbeat | 用於審計數據 |
2、微服務將日志發送給Redis或者MQ,再由他們去對接Logstash(高並發場景)
由於logstash消耗性能,所以高並發場景容易遇到流量上的瓶頸,及時使用logstash集群也是如此,所以可以添加中間件進行日志緩存處理。由於logstash數據源具有多種方式,所有中間件也可以很多選擇,常見的有kafka,redis。
三、ELK搭建(非集群)
1、下載ELK(保持版本一致)
Elasticsearch | 官網elasticsearch-6.3.1.tar | elasticsearch官方文檔 |
Kibana | 官網kibana-6.3.1下載 linux64位 | kibana官方文檔 |
Logstash | 官網logstash-6.3.1.tar | logstash官方文檔 |
Filebeat | 官網filebeat-6.3.0 linux64位 | beats官方文檔 |
下面只介紹,方案2:Logstash獨立部署,微服務節點通過網絡向Logstash發送日志信息。
2、環境准備
1、jdk1.8
2、Elasticsearch安裝參考:ES系列一、CentOS7安裝ES 6.3.1
3、啟動 Elasticsearch
3、安裝Kibana
1、解壓到安裝目錄即可
/home/kibana-6.3.1-linux-x86_64
2、修改配置文件
vi /home/kibana-6.3.1-linux-x86_64/config/kibana.yml
server.port: 5601 ##服務端口 server.host: "0.0.0.0" ##服務器ip 本機 elasticsearch.url: "http://localhost:9200" ##elasticsearch服務地址 與elasticsearch對應
3、啟動kibana
/home/kibana-6.3.0-linux-x86_64/bin/kibana #命令窗啟動
4、關閉kibana
ps -ef | grep kibana #后台線程關閉 kill -9 4525 ##pid 4525 為查處線程的pid
5、驗證kibana啟動
4、安裝logstash
1、下載
wget https://artifacts.elastic.co/downloads/logstash/logstash-6.3.1.tar.gz
tar -zxvf logstash-6.3.1.tar.gz
2、創建配置文件logstash-es.conf
vim /home/logstash-6.3.1/conf.d/logstash-es.conf
復制一下內容:
input { tcp { port => 10514 codec => "json" } } output { elasticsearch { action => "index" hosts => ["localhost:9200"] index => "%{[appname]}" } }
10514:接受日志端口
hosts => ["localhost:9200"] :es的ip和端口
"%{[appname]}" :取值日志中appname值為索引
3、檢測配置文件是否有錯:
/home/logstash-6.3.1/bin/logstash --path.settings /home/logstash-6.3.1/config/ -f /home/logstash-6.3.1/config/conf.d/logstash-es.conf--config.test_and_exit Sending Logstash's logs to /var/log/logstash which is now configured via log4j2.properties Configuration OK # 為ok則代表配置文件沒有問題 [root@data-node1 /usr/share/logstash/bin]#
命令說明:
- --path.settings 用於指定logstash的配置文件所在的目錄
- -f 指定需要被檢測的配置文件的路徑
- --config.test_and_exit 指定檢測完之后就退出,不然就會直接啟動了
4、指定配置文件,啟動logstash:
/home/logstash-6.3.1/bin/logstash --path.settings /home/logstash-6.3.1/config/ -f /home/logstash-6.3.1/config/conf.d/logstash-es.confSending Logstash's logs to /var/log/logstash which is now configured via log4j2.properties # 這時終端會停留在這里,因為我們在配置文件中定義的是將信息輸出到當前終端
5、驗證
打開新終端檢查一下10514端口是否已被監聽:
[root@data-node1 ~]# netstat -lntp |grep 10514 tcp6 0 0 :::10514 :::* LISTEN 4312/java [root@data-node1 ~]#
5、配置lockback
1、maven
<!--logback日志-->
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>4.8</version>
</dependency>
2、logback.xml添加logstash配置
<appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <param name="Encoding" value="UTF-8"/> <remoteHost>192.168.1.102</remoteHost> <port>10514</port> <!-- <filter class="com.program.interceptor.ELKFilter"/>-->//引入過濾類 <!-- encoder is required --> <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder" > <customFields>{"appname":"${appName}"}</customFields> // 索引名 </encoder> </appender>
logback.xml如下:
<?xml version="1.0" encoding="UTF-8"?> <configuration scan="true"> <contextName>MovieBooking</contextName> <timestamp key="TIMESTAMP" datePattern="yyyy-MM-dd" /> <property name="LOGPATH" value="log" /> <springProperty scope="context" name="appName" source="server.Name" defaultValue="localhost.log"/> <!-- 輸出到控制台 --> <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern> %d{HH:mm:ss.SSS} [%thread] %-5level %logger{40} - %msg%n </pattern> </layout> </appender> <!-- 輸出到文件 --> <appender name="fileLog" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOGPATH}${file.separator}${TIMESTAMP}.log</file> <append>true</append> <encoder> <pattern> %d{HH:mm:ss.SSS} [%thread] %-5level %logger{40} - %msg%n </pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOGPATH}${file.separator}all${file.separator}%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <MaxFileSize>10MB</MaxFileSize> </triggeringPolicy> </appender> <appender name="logstash" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <param name="Encoding" value="UTF-8"/> <remoteHost>192.168.1.102</remoteHost> <port>10514</port> <!-- <filter class="com.program.interceptor.ELKFilter"/>-->//引入過濾類 <!-- encoder is required --> <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder" > <customFields>{"appname":"${appName}"}</customFields> </encoder> </appender> <root level="INFO"> <appender-ref ref="fileLog" /> <appender-ref ref="stdout" /> <appender-ref ref="logstash" /> </root> </configuration>
3、測試
添加單元測試類:
package com.example.demo; import com.example.service.StudentService; import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.context.web.WebAppConfiguration; @RunWith(SpringRunner.class) @SpringBootTest @Slf4j @WebAppConfiguration public class DemoApplicationTests { @Autowired private StudentService studentService; @Test public void Test() { log.info("測試日志{}","台風山竹,威力很大!"); log.info(studentService.findAllStudent().get(0).toString()); } }
執行:
4、驗證