文·黃崇遠

說起ELK,熟悉的看官可能都知道接下來要講什麼了,就算是不熟悉的,想必也多少知道一丟丟子,畢竟ELK的經典組合是具有一定年份的了。

筆者按:

遙想N年前,哪有這麼多高度封裝的工具,都是自己寫代碼屁顛屁顛去獲取數據,老老實實的調ES的Rest full API自己灌數據,等等諸如此類。

每思及此,潸然淚下!(最近在看裴松之注的《三國志》,有點抽風,莫理會)

就算如此,這裏還是花少許筆墨,簡單的描述一把,再做其他的闡述。

什麼是ELK?

首先ELK肯定不是一個東西,要不然標題也就不會叫“三劍客ELK”了,但實際上也不是三個東西,以前或許是,但現在已經不能算了。

官方說法就是,ELK的核心代表是ElasticSearch,Logstash,Kibana,這三者是核心套件,但目前已經不止如此了,已經形成了圍繞三者的整套解決方案,以應對各種不同的業務場景。

ElasticSearch是實時的全文搜索和分析引擎,起源於搜索還是依託於Lucene的草莽時代,他將Lucene進行了集成了,然後在此基礎上不但簡化了搜索引擎的搭建成本,也在性能提升上做了很多優化,目前已經算是開源搜索領域裏一家獨大的底層框架了。

當然,早期的ES最多也只能算個搜索引擎,在集成了分析體系之後,再配合Kibana的分析可視化的話,你說他也是個分析引擎,一點毛病都沒有,支持大規模的數據分析溜溜的。

他本身集成了搜索,分析,以及可擴展的存儲等功能,在查詢的支持上,不僅提供了大家喜聞樂見的Rest full訪問,還提供了很程序員化的JAVA API等,並且速度真的是公認的快。

Logstash從名字上不難發現,與log強相關,早期定義爲用來蒐集,分析和過濾日誌的工具。他的強大之處在於幾乎支持任何類型的日誌輸入,實際上是依託於其強大的日誌解析插件(這個後面會講到),並且目前對於輸入源,他已經徹底的開放了,什麼消息隊列(最常用的數據源),各種常見的數據庫,redis,甚至是直接做端口監控等等,簡直逆天。

三劍客中最後一劍是Kibana,目前他核心提供了ES的界面化查詢,ES集羣以及索引情況監控,數據的可視化分析,甚至提供了各種圖表支持等,當然他同樣也可以基於Logstash去做數據可視化的分析。

除了ELK三個,後續又補充了一個實力組件Filebeat。看名字就知道,他是與文件強關聯的一個組件。我們知道Logstash本身就支持從log文件中進行數據的獲取,而Filebeat就是大大加強數據蒐集這層的組件,甚至在Logstash中作爲一個數據源的插件做數據源的介入集成。

至於說怎麼安裝部署ELK,這裏不會過多贅述,自行百度谷歌,有很多教程,我這裏用我們目前的使用方式,以最快的方式簡單講講如何使用ELK,僅作爲一個用例的參考,幫助大家快速入門,更多資料還得依靠官網。

我司ELK使用的一個場景

在我司,或者更確切的說在我司大數據團隊裏,ELK基本框架服務的是我們的基礎搜索,而不是做日誌分析用,運維那邊使用ELK做日誌分析暫且不表。

以商品搜索爲例,業務數據庫在生產環境,我們使用canel+otter的架構來做商品業務庫的變動同步,幾百萬級的屬性變更同步肯定是支撐的住的。

然後在數據這邊的環境中,將商品對應的畫像屬性進行加掛,以及其他相關屬性的計算合併,然後以20分鐘的時間,週期性的變更到商品的索引文檔中。

所以回到ELK這邊來說就是,數據源是MySQL,對應的是週期性計算的臨時表,然後Logstash讀取MySQL對應的臨時計算變更表,寫入ES對應的索引中,通過Kibana進行ES的狀態監管,以及必要時替代舊時代的head組件進行索引查詢等。

我們來看一下Logstash對應的配置conf就清楚了大致的流程,conf總共分三個部分input是數據源獲取,filter是過濾器可以做數據中間態轉換(這個很牛,一會兒單獨講講),最後是output,我們這裏妥妥的就是ES了,所以需要做ES的一些連接配置。

以我們的XX.conf我們先來看看input輸入的配置(請原諒我將一些敏感信息給XX了)。

input {

jdbc {

id => "item_test"

jdbc_driver_library => "/data/logstash/mysql-connector-java-5.1.44.jar"

jdbc_driver_class => "com.mysql.jdbc.Driver"

jdbc_connection_string => "jdbc:mysql://host-XX:3306/XX"

jdbc_user => "XX"

jdbc_password => "XX"

connection_retry_attempts => 3

connection_retry_attempts_wait_time => 1

jdbc_default_timezone => "Asia/Shanghai"

jdbc_fetch_size => 50000

# 使用時驗證連接

jdbc_validate_connection => true

# 驗證連接的時間間隔(秒)

jdbc_validation_timeout => 600

use_column_value => true

tracking_column_type => "timestamp"

tracking_column => "update_time"

# 最後運行時間的文件路徑

last_run_metadata_path => "/data/logstash/metadata/.just_path_XX"

# 連接池最大連接數 4 默認也爲4

sequel_opts => { "max_connections" => 4 }

# 執行語句的存放路徑

statement_filepath => "/data/logstash/sql/XX.sql"

}

}

如上,就是一個典型從MySQL獲取數據的input,前面的數據庫連接相關的信息就不多說,核心注意一下last_run_metadata_path的配置,這個配置有助於你做執行進度的記錄,避免重複“消費”,第二個就是執行的SQL對應文件位置。

實際上就是SQL查詢文件,需要注意的就是,一是要提供document_id對應所需的字段,另一個就是查詢的字段跟索引對應的屬性字段名稱要一一對應。

第二個就是filter過濾器,強大的過濾器,當然我這裏沒有體現出他的強大,因爲我的數據都是規整的,不需要他強悍的轉換功能,只需要將將字段進行拆分即可。所以,針對filter過濾器,樣例講完了,還得好好說道說道,這裏就簡單略過了。

filter{

mutate {

remove_field => [ "@timestamp", "@version"]

}

mutate {

split => { "activity_id" => "," }

}

}

這裏簡單說下remove_field是字段移除,split是數組切分。

最後是output,數據的輸出,我們這裏輸出至ElasticSearch,所以進行ES連接,索引指定等配置。

output {

elasticsearch {

#配置若干個ES的hosts

hosts => ["host-XX1:9200","host-XX2:9200",...,...]

index => "index-XX"

document_type => "XX"

document_id => "%{XX_id}_%{XX_id}"

action => "update"

doc_as_upsert => true

}

}

根據字面意思,很容易理解,這裏稍微說明一下的就是,document_id的組合,我們這裏是通過兩個關鍵id進行組合生成的。

通過如下命令,將我們的conf加載到Logstash中,需要注意的就是path.data參數的配置,在遇到相同目標操作的時候,可以起到類似鎖的作用,避免數據插入干擾。

/data/logstash/logstash/bin/logstash -f /data/logstash/conf/XX.conf --path.data=/data/logstash/data/XX

至於Kibana這裏簡單的說下。

需要注意的是,Kibana如果在配置文件中指定訪問的ES的host和port就會默認取與Kibana本地的地址訪問,具體配置爲安裝目錄下config/kibana.yml,對應配置如下:

elasticsearch.url: "http://hosts-XX:9200"

如圖Management進行索引管理,主要是索引的添加操作,Discover進行索引的查詢,Vissulize是分析圖表,如果用的溜的話,可以做一些很“可視化”的圖表出來(反正我不溜),比如不是很溜的例子:

再額外說下的就是Monitoring,可以做ES集羣以及索引情況的健康狀態跟蹤,具體的就不說了,詳情請參考官網,這些信息都是比較容易拿到的。

如上,基本上就是一個簡單而又實用的例子了,基本流程是過了一遍,更多的限於篇幅就不多說了,自行擴展,更多是給大家一個入門的路子。

重點又簡單的提一下Logstash的Grok插件

Logstash對於文本的解析是非常強大的,其中Grok是Logstash是專爲文本解析而生的。Grok內置了很多正則表達式,跟我們C語言的宏定義有點像,感興趣的可以參考這裏:

https://github.com/elastic/logstash/blob/v1.4.2/patterns/grok-patterns

大概是長這樣子的:

舉個實例可能會好理解點,以需要解析的log如下爲例(這個例子是我抄來的,方便解說,哈哈):

2016-11-30 06:33:33 192.168.5.116 GET /Hotel/HotelDisplay/cncqcqb230 - 80 - 192.168.9.2 Mozilla/5.0+(Macintosh;+U;+Intel+Mac+OS+X+10.9;+en-US;+rv:1.9pre)+Gecko - 200 0 0 45

我們的過濾器配置如下:

filter {

grok {

match => [

"message" ,"s*(?<time>([0-9]{4}-[0-9]{2}-[0-9]{2}s+[0-9]{2}:[0-9]{2}:[0-9]{2}))s+%{IPORHOST:clientip}s+%{WORD:verb}s+%{URIPATHPARAM:request}s+-s+(?<port> ([0-9]{2}.*?))s+-s+%{IPORHOST:sourceip}s+(?<http_user_agent>(S+s+).*?).*"

]

}

date {

match => ["time", "yyyy-MM-dd HH:mm:ss"]

}

mutate{

remove_field =>["message"]

}

}

先來看結果(結果是直接輸出到控制檯,你可以做入庫,入ES都可以),再來分說。

{

"message" => "2016-11-30 06:33:33 192.168.5.116 GET /Hotel/HotelDisplay/cncqcqb230 - 80 - 192.168.9.2 Mozilla/5.0+(Macintosh;+U;+Intel+Mac+OS+X+10.9;+en-US; +rv:1.9pre)+Gecko - 200 0 0 45",

"@version" => "1",

"@timestamp" => "2016-11-29T22:33:33.000Z",

"host" => "dr-mysql01.zjcap.com",

"time" => "2016-11-30 06:33:33",

"clientip" => "192.168.5.116",

"verb" => "GET",

"request" => "/Hotel/HotelDisplay/cncqcqb230",

"port" => "80",

"sourceip" => "192.168.9.2",

"http_user_agent" => "Mozilla/5.0+(Macintosh;+U;+Intel+Mac+OS+X+10.9;+en-US;+rv:1.9pre)+Gecko "

}

從模板裏可以看出,他接受字對應的正則,比如<time>,也接受類似的宏定義,比如IPORHOST:clientipURIPATHPARAM:request,等等,並且支持重命名。

例如上述說到的兩個默認定義,如下:

IPORHOST (?:%{HOSTNAME}|%{IP})

URIPATHPARAM %{URIPATH}(?:%{URIPARAM})?

只要你對正則表達式很熟悉,或者說認真的看看grok-patterns,解析任何形態的log豈不是手到擒來,如果再結合其他插件諸如mutate,drop,clone,geoip等,以及Filebeat牛逼插件,可以做很多事情。

所以說ELK通過“日誌分析”的名頭奠定了日誌分析的地位,不是白搭的。

給一些官方的各種資料入口,想要進一步研究的可以看看,這裏只是給大夥兒打開一個門縫而已,如下自取(如果對ELK熟悉的略過):

Grok-patterns:

https://github.com/elastic/logstash/blob/v1.4.2/patterns/grok-patterns

Filebeat:

https://www.elastic.co/cn/products/beats/filebeat

Logstash:

https://www.elastic.co/cn/products/logstash

Kibana:

https://www.elastic.co/cn/products/kibana

ElasticSearch:

https://www.elastic.co/cn/products/elasticsearch

elasticsearch中文社區:

https://elasticsearch.cn/

打完收工,梳理的很辛苦,如果覺得有用的話,不吝打賞杯深夜咖啡錢,再實在不行,順路點點頂部或者文中的“廣了個告”也行,窮的揭不開鍋,寫文爲生了,哈哈。

--- 2018年12月7日 凌晨,癸亥月 壬申日 子時

查看原文 >>
相關文章