對頗具規模的Web服務進行日誌收集、存儲、分析、處理等;html
ELK:ElasticSearch、Logstash、Kibanajava
ElasticSearch:是一個基於Lucene實現的開源的、分佈式、RestFul的全文本搜索引擎;此外,它仍是一個分佈式實時文檔存儲,其中每一個文檔的每一個field均是被索引的數據,且可被搜索;也是一個帶實時分析功能的分佈式搜索引擎,可以擴展至數以百計的節點,實時處理PB級的數據;node
架構:redis
對於大規模的日誌收集,都會專門的服務器用來將日誌數據集中到一塊兒進行整合。通常會在各個生產日誌的節點上安裝日誌收集agent,而後經過agent向服務端發送日誌數據。可是若是全部agent同時將日誌發送給服務端,就算先不看服務端的性能,僅看網絡帶寬就是一個大問題,因此通常會在agent和服務端之間在放置一個消息隊列(能夠是redis、AMQP、kafka等)緩衝一下,而後服務端再一條一條的到隊列中獲取日誌數據;數據庫
名詞解釋:apache
官網信息:https://www.elastic.co/guide/en/elasticsearch/reference/7.3/glossary.html#glossary-termjson
在Elasticsearch中存儲數據的行爲就叫作索引(indexing)vim
索引(index)這個詞在Elasticsearch中有着不一樣的含義,因此有必要在此作一下區分:api
索引(名詞):如上文所述,一個索引(index)就像是傳統關係數據庫中的數據庫,它是相關文檔存儲的地方,index的複數是indices 或indexes。瀏覽器
索引(動詞):「索引一個文檔」表示把一個文檔存儲到索引(名詞)裏,以便它能夠被檢索或者查詢。這很像SQL中的INSERT關鍵字,差異是,若是文檔已經存在,新的文檔將覆蓋舊的文檔。
倒排索引:傳統數據庫爲特定列增長一個索引,例如B-Tree索引來加速檢索。Elasticsearch和Lucene使用一種叫作倒排索引(inverted index)的數據結構來達到相同目的。也能夠理解爲根據某個詞找某個或某些文檔;
文檔(document):文檔是Lucene索引和搜索的原子單位,它包含一個或多個域,是域的容器,基於JSON格式表示;
映射(mapping):原始內容存儲爲文檔以前須要事先進行分析,例如切詞、過濾某些詞等;映射就是用於定義此分析機制應該如何實現;
示例:顯示特定字段的類型;
~]# curl 'http://192.168.80.136:9200/students/_mapping/?pretty'
{
"students" : {
"mappings" : {
"properties" : {
"age" : {
"type" : "long"
},
"courses" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"first_name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"gender" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"last_name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
域由其名稱和一個或多個值組成;
Note:ES對每一個文檔,會取得其全部域的全部值,生成一個名爲_all的域。若是在query_string未指定查詢的域,則在_all域上執行查詢操做;
在Elasticsearch中,文檔歸屬於一種類型(type),而這些類型存在於索引(index)中,且一個索引中能夠有多種類型,咱們能夠畫一些簡單的對比圖來類比傳統關係型數據庫:
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields
切詞:對一段文字進行切割,能夠詞一句話也能夠是一個詞,而後以切割出來的詞或句來進行搜索;或者是搜索相應的詞或句時對其進行匹配;
域:
索引選項:用於經過倒排索引來控制文本是否可被索引;
Index.ANALYZED:分析(切詞)並單獨做爲索引項;
Index.Not_ANALYZED:不分析(不切詞),把整個內容當作一個索引項;
Index.ANALYZED_NORMS:相似於Index.ANALYZED,但不存儲切詞的Norms(加權基準)信息;
Index.Not_ANALYZED_NORMS:相似於Index.Not_ANALYZED,但不存儲切詞的Norms信息;
Index.NO:不對此域的值進行索引,所以不能被搜索;
存儲選項:是否須要存儲域的真實值;
store.YES:存儲真實值(原值,切詞之後原詞的形式(好比大小寫));
store.NO:不存儲真實值;
文檔和域的加權操做:
權重大的會在搜索結果中被優先顯示;默認都是同樣的;
搜索引擎進行搜索的流程:
獲取原始內容 --> 構建文檔 --> 文檔分析 --> 建立索引 --> 用戶查詢 --> 構建查詢 --> 運行查詢(與建立索引密切相關) --> 返回結果 --> 展現給用戶
咱們可使用Lucene建立索引可是它不獲取且不提供供用戶使用的搜索頁面,因此咱們能夠將它當作一個庫,能夠經過調用它的API接口來實現索引建立相關的功能;對於搜索界面咱們可使用ElasticSearch來實現;
查詢Lucene索引時,它返回的是一個有序的scoreDOC對象;查詢時,Lucene會對每一個文檔計算出其score;
Lucene的查詢:
IndexSearcher中的search方法:
TermQuery:對索引中的特定項進行搜索;Term是索引中的最小索引片斷,每一個Term包含了一個域名和一個文本值;
例子:
title: This is a pen;
owner:Tom;
des:It is blue;
title:This is a book;
owner:Jack
des:It has 400 pages;
當咱們進行搜索時就能夠指定在title或者owner範圍內搜索指定內容;
TermRangeQuery:在索引中的多個特定項中進行搜索,能搜索指定的多個域;
NumericRangeQuery:對數值範圍進行搜索;
PrefixQuery:用於搜索以指定字符串開頭的項;
BooleanQuery:用於實現組合搜索;AND、OR、NOT;
WildcardQuery:使用通配符進行查詢;
FuzzyQuery:模糊查詢,好比查詢與指定內容類似的內容;
Elasticsearch致力於隱藏分佈式系統的複雜性。如下這些操做都是在底層自動完成的:
將你的文檔分區到不一樣的容器或者分片(shards)中,它們能夠存在於一個或多個節點中。
將分片均勻的分配到各個節點,對索引和搜索作負載均衡。
冗餘每個分片,防止硬件故障形成的數據丟失。
將集羣中任意一個節點上的請求路由到相應數據所在的節點。
不管是增長節點,仍是移除節點,分片均可以作到無縫的擴展和遷移。
ES的集羣組件:
Cluster:ES的集羣名稱。節點就是靠此名稱來決定加入到哪一個集羣中,且一個節點只能加入到一個集羣中;
Node:運行了單個ES實例的主機即爲節點。用於存儲數據、參與集羣索引及搜索操做;經過節點名標識此節點;
Shard:將索引分割成多個shard,存儲在多個節點中;從而減小單個節點的磁盤IO的壓力;默認狀況下ES會將一個索引分割成5個shard,固然,用戶也能夠自定義,可是肯定以後不能夠再修改shard的數量;
shard有兩種類型:primary shard和replica
primary shard用於文檔存儲,默認切割成5個primary shard;且ES還會爲每一個primary shard提供副本,當primary shard不可用是,其副本就會提高爲primary shard,這個副本就是replica;其replica也可用於查詢時的負載均衡;每一個primary shard的replica數量也能夠自定義;
ES集羣狀態:
green:正常狀態
red:故障狀態
yellow:修復狀態
ES Cluster的工做過程:
啓動時,ES的各個節點會經過組播(默認)或單播在TCP協議的9300端口查找同一集羣中的其餘節點,並與之創建通訊;而且選舉出一個主節點,負責管理集羣狀態,以及在集羣範圍內決定各shard的分佈方式,這對用戶是透明的,也就是說每一個節點均可以接收和相應用戶的請求;
ES經過http協議,使用9200接受客戶的查詢請求;
ES的安裝:
1.準備環境:
安裝ES須要安裝JDK,使用OpenJDK或者OracleJDK都是能夠的;
~]# yum install java-1.8.0-openjdk.x86_64 -y
~]# yum install java-1.8.0-openjdk-devel.x86_64 -y
~]# yum install java-1.8.0-openjdk-headless.x86_64 -y
配置JAVA的環境變量;
2.下載ES軟件包:
官網下載地址:https://www.elastic.co/cn/downloads/elasticsearch/elasticsearch-7.3.0-x86_64.rpm
~]# yum install ./elasticsearch-7.3.0-x86_64.rpm 我下載的是rpm包
~]# sudo systemctl daemon-reload
~]# sudo systemctl enable elasticsearch.service
3.編輯配置文件:
~]# vim /etc/elasticsearch/elasticsearch.yml
cluster.name: myes 集羣名稱
node.name: node3 節點名稱
http.port: 9200 監聽端口
network.host: 192.168.80.129 綁定的主機地址
discovery.seed_hosts: ["192.168.80.129", "192.168.80.136"] 初始主機列表
cluster.initial_master_nodes: ["node3 ", "node2 "] 使用一組符合主節點條件的初始節點引導集羣
更多參數請參考官網:https://www.elastic.co/guide/en/elasticsearch/reference/current/settings.html
4.啓動ES:
~]# sudo systemctl start elasticsearch.service
Note:多個節點重複以上步驟便可;
ES的RestFul API:
1.檢查集羣、節點、索引等健康與否,以及獲取及相應狀態;
2.管理集羣、節點、索引、及元數據;
查詢數據:
查詢方式:
1.經過RestFul request API查詢,也成爲query string;
2.經過發送REST request body進行;
分爲兩類:
query DSL:執行full-text查詢時,基於相關度來評判其查詢結果;
執行過程相對複雜,且不會被緩存;
filter DSL:執行exact查詢時,基於其結果爲「yes」或「no」進行評判;
速度快,且結果能夠緩存;
示例:
~]# curl -XGET 'http://192.168.80.136:9200/students/_search/?pretty'
{
"took" : 24,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "students",
"_type" : "class1",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"first_name" : "Jing",
"last_name" : "Guo",
"gender" : "Male",
"age" : 25,
"courses" : "Xainglong shiba zhang"
}
}
]
}
}
~]# curl -H "Content-Type: application/json" -XGET 'http://192.168.80.136:9200/students/_search/?pretty' -d '
{
"query": { "match_all":{} }
}' 結果同上;
多索引、多類型查詢:
/_search:查詢全部索引
/INDEX_NAME/_search:單索引查詢
/INDEX_NAME1,INDEX_NAME2/_search:多索引查詢
/g*,w*/_search:通配索引查詢
/INSEX_NAME/TYPE1,TYPE2/_search:多類型查詢
3.執行CRUD(增刪查改)操做;
示例:
建立文檔:
~]# curl -H "Content-Type: application/json" -XPUT 'http://192.168.80.136:9200/students/class1/1?pretty' -d '
{
"first_name":"Jing",
"last_name":"Guo",
"gender":"Male",
"age":25,
"courses":"Xainglong shiba zhang"
}'
查看:
~]# curl -XGET 'http://192.168.80.136:9200/students/class1/1?pretty'
{
"_index" : "students",
"_type" : "class1",
"_id" : "1",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"first_name" : "Jing",
"last_name" : "Guo",
"gender" : "Male",
"age" : 25,
"courses" : "Xainglong shiba zhang"
}
}
更新:
PUT方法會直接覆蓋文檔內容,若是隻是更新部份內容,須要使用_update API;
~]# curl -H "Content-Type:application/json" -XPOST 'http://192.168.80.136:9200/students/class1/1/_update?pretty' -d '
> {
> "doc":{"age":28}
> }'
{
"_index" : "students",
"_type" : "class1",
"_id" : "1",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
}
刪除:
~]# curl -XDELETE 'http://192.168.80.136:9200/students/class1/2'
{"_index":"students","_type":"class1","_id":"2","_version":2,"result":"deleted","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":3,"_primary_term":1}
4.執行各類高級操做;好比paging、filtering等
ES的請求格式:
向Elasticsearch發出的請求的組成部分與其它普通的HTTP請求是同樣的:
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
VERB HTTP方法:GET, POST, PUT, HEAD, DELETE
PROTOCOL http或者https協議(只有在Elasticsearch前面有https代理的時候可用)
HOST Elasticsearch集羣中的任何一個節點的主機名,若是是在本地的節點,那麼就叫localhost
PORT Elasticsearch HTTP服務所在的端口,默認爲9200
PATH API路徑(例如_count將返回集羣中文檔的數量),PATH能夠包含多個組件,例如_cluster/stats或者_nodes/stats/jvm
QUERY_STRING 一些可選的查詢請求參數,例如?pretty參數將使請求返回更加美觀易讀的JSON數據
BODY 一個JSON格式的請求主體(若是請求須要的話)
舉例說明,爲了計算集羣中的文檔數量,咱們能夠這樣作:
curl -H "Content-Type: application/json" -XGET 'http://192.168.80.136:9200/_search?pretty' -d '
{
"query": {
"match_all": {}
}
}
'
Elasticsearch返回一個相似200 OK的HTTP狀態碼和JSON格式的響應主體(除了HEAD請求)。上面的請求會獲得以下的JSON格式的響應主體:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 0,
"successful" : 0,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"
},
"max_score" : 0.0,
"hits" : [ ]
}
}
咱們看不到HTTP頭是由於咱們沒有讓curl顯示它們,若是要顯示,使用curl命令後跟-i參數:
curl -i -XGET 'localhost:9200/'
示例:
~]# curl -XGET 'http://192.168.80.136:9200/_cat/nodes?v' 顯示字段名
~]# curl -XGET 'http://192.168.80.129:9200/_cat/nodes?help' 顯示幫助信息
Note:ES有不少的API,具體參見官網:https://www.elastic.co/guide/en/elasticsearch/reference/current/rest-apis.html
ES的Plugins:
插件擴展的功能:添加自定義的映射類型、自定義分析器、本地腳本、自定義發現方式等;
安裝插件的方式:
1.直接將插件放置到plugins目錄(/usr/share/elasticsearch/plugins)中;
2.使用plugin(/usr/share/elasticsearch/bin/elasticsearch-plugin)命令進行添加插件;
有關插件的文檔:https://www.elastic.co/guide/en/elasticsearch/plugins/7.3/index.html https://www.elastic.co/guide/en/kibana/current/kibana-plugins.html
Logstash:負責數據的收集
官網簡介:https://www.elastic.co/guide/en/logstash/current/introduction.html
能夠經過Agent在各個產生日誌的服務器上收集數據,而後再經過Agent將數據統一發送到Logstash服務器中進行統一處理,再存儲到ElasticSearch上;
支持多種數據獲取機制,經過TCP/UDP協議、文件、syslog、Windows EventLogs及STDIN等;獲取到數據後,它還支持對數據進行過濾修改等操做;
使用JRuby語言開發,所以安裝環境須要JVM;
Logstash的許多功能都是使用插件完成的,因此Logstash必須加載各類插件從而完成其各類功能;
插件類型:輸入插件、編碼插件、過濾插件、輸出插件
工做流程:input|filter|output
各類插件:https://www.elastic.co/guide/en/logstash-versioned-plugins/current/index.html
安裝Logstash:
1.環境搭建:
安裝JDK(前面已經介紹了,就不贅述了!)
2.下載軟件包並安裝:
下載地址:https://www.elastic.co/cn/downloads/logstash
~]# yum install ./logstash-7.3.0.rpm
3.測試
~]# /usr/share/logstash/bin/logstash -e 'input { stdin { } } output { stdout {} }'
Ctrl+D退出;
更多參數:https://www.elastic.co/guide/en/logstash/current/running-logstash-command-line.html
4.配置文件:/etc/logstash/以及/etc/logstash/conf.d/(自定義的配置信息建議放在這裏且以".conf"結尾)
配置文件的框架:
input {
……
}
filter {
……
}
output {
……
}
Logstash的插件:
input插件:
file:從指定的文件中讀取事件流;使用FileWatch(Ruby Gem庫)監視文件是否變化且能夠同時監視多個文件,還能夠保存文件的讀取位置,以方便之後接着讀取(存儲在.sincedb,其記錄了每一個被監視的文件的inode、major、minor、number、pos等);
默認以單行數據爲一個事件做爲一次讀取,可是能夠經過編碼器將文本中的多行合併成一行進行一次讀取;
示例:
~]# cat /etc/logstash/conf.d/file.conf
input {
file {
path => ["/var/log/messages"]
type => "system"
start_position => "beginning"
}
}
output {
stdout {
codec => rubydebug
}
}
~]# /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/file.conf
運行此命令就會將/var/log/messages中全部的信息都輸出到STDOUT;
udp:經過udp協議從網絡鏈接讀取Message,其必備的參數爲port(本身監聽的端口號)和host(本身監聽的地址);
若是使用udp做爲輸入插件,則在被收集端還應該有一個與其對應的軟件來完成將其數據主動發送到收集端(Logstash端)中,可使用nc或者collectd(位於epel源中)中的network插件(經過Server配置段指定Logstash的地址便可)完成相應的功能;固然還有不少其餘的軟件可使用;
Note:Logstash端input{}要使用collectd專用的編碼器(codec => collectd {});
redis插件:
從redis讀取數據,支持redis channel和lists兩種方式;
filter插件:
用於在將event(事件)經過output發出以前對其進行某些處理操做;
grok插件:
用於分析並結構化文本數據的插件;是Logstash中將非結構日誌數據轉化爲結構化可查詢數據的不二之選;
結構化方式:
經過將數據的各個字段進行從新命名來實現數據的結構化,好比apache的日誌,其中字段依次是客戶端的IP地址、用戶、組、訪問時間、方法、URL、版本、狀態碼、大小、referer以及客戶端代理;grok就是經過將各個字段定義爲某個名稱,而後在輸出時用各個鍵值對錶示其數據結構形式;
ip => 192.168.80.123
user => liubocheng
……
文件/usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-patterns-core-4.1.2/patterns/grok-patterns中就包含了其支持的各類形式,而且也支持自定義格式;
output插件:
redis插件:
示例:
1.配置redis.conf
vim /etc/redis.conf
port 6379
bind 0.0.0.0
2.配置被收集端的Logstash
~]# cat /etc/logstash/conf.d/redis.conf
input {
file {
path => ["/var/log/messages"]
type => "system"
start_position => "beginning"
}
}
output {
redis {
port => "6379"
host => ["127.0.0.1"]
data_type => "list"
key => "logstash-%{type}"
}
}
3.配置收集端的Logstash
~]# cat /etc/logstash/conf.d/redis.conf
input {
redis {
port => "6379"
host => "192.168.80.129"
data_type => "list"
key => "logstash-system"
}
}
output {
stdout {
codec => rubydebug
}
}
4.在收集端執行命令進行測試
~]# /usr/share/logstash/bin/logstash -f /etc/logstash/conf.d/redis.conf
5.將收集的數據存儲到ES中
~]# cat /etc/logstash/conf.d/redis.conf
input {
redis {
port => "6379"
host => "192.168.80.129"
data_type => "list"
key => "logstash-system"
}
}
filter {
mutate {
rename => { "[host][name]" => "host" }
}
}
output {
elasticsearch {
hosts => ["192.168.80.129:9200"]
id => "redis"
index => "logstash-%{+YYYY.MM.dd}"
}
}
Note:lumberjack能夠代替客戶端的Logstash做爲發送數據的Agent,由於Logstash做爲客戶端Agent過重量級了;
安裝Kibana:
1.下載並安裝軟件包:
https://www.elastic.co/cn/downloads/kibana
~]# yum install ./kibana-7.3.0-x86_64.rpm -y
2.配置文件:
~]# vim /etc/kibana/kibana.yml
server.port: 5601
server.host: "node2.guowei.com"
指定Kibana服務器將綁定到的地址。IP地址和主機名都是有效值。要容許來自遠程用戶的鏈接
server.name: "node2.guowei.com"
指定節點名稱,能夠是任意字符
elasticsearch.hosts: ["http://node2.guowei.com:9200"]
指定ES的監聽地址
kibana.index: ".mykibana"
Kibana在Elasticsearch中使用索引來存儲保存的搜索、可視化和儀表盤。若是索引不存在,Kibana將建立一個新索引。
xpack.security.enabled: false
配置kibana的安全機制,測試時能夠關閉。
3.啓動Kibana
systemctl start kibana.service
4.在瀏覽器中鍵入http://192.168.80.129:5601便可鏈接至Kibana
借鑑文章:https://es.xiaoleilu.com/index.html
根據馬哥視頻作的學習筆記,若有錯誤,歡迎指正;侵刪