ELK原理

 爲何要使用Elasticsearch?
​   由於在咱們中的數據,會隨着時間變的很是多,若採用以往的模糊查詢,模糊查詢前置通配符,如:"%aa%",會放棄索引,致使數據表查詢將變成全表掃描,在百萬級別的數據庫中,效率很是低下,而咱們使用ES作一個全文索引,咱們就能夠將常常查詢的數據字段,好比說商品名,描述、價格還有id等,這些字段放入咱們索引庫裏,這樣就能夠大大提升查詢速度。html

Elasticsearch
  PV: 頁面瀏覽量:一個頁面中可能有多個頁框,假如:一個頁面有100個頁框,那麼打開一個頁面,就會
          產生100個請求頁面,但統計PV時,這個100個頁面就是一個PV.
  UV:用戶訪問量
  UV < PV

對於大型Web站點,每秒產生的日誌量都是很是驚人的,假如併發1W,每一個頁面產生100條日誌事件,
1秒就是1百萬條日誌事件.將這些日誌寫入存儲系統,對日誌存儲系統的壓力是很是大的,並且日誌存儲
下來後還須要能實時對日誌作分析的,這就對存儲日誌的系統有更加高的要求。

搜索引擎:必須包含如下兩個組件
索引鏈:將數據收集,存儲,並創建索引的系統,就稱爲索引鏈。
搜索組件:即面對用戶的數據搜索組件,它是咱們開發的程序工具。

搜索引擎的索引稱爲:倒序索引
所謂倒序,是由於搜索引擎首先對詞條,作切詞,而後存儲在一個表中,這個表只有兩列,一列詞,一列文檔編號,
這樣就將詞和文檔作了關聯,在搜索時,搜索引擎會根據詞來匹配出符合條件的文檔,好比: Linux 培訓,那麼搜索引擎
會先找Linux,再找培訓,最後作並集,同時包含Linux和培訓兩個關鍵字的,排列越靠前,這是比較理想的,Google
的搜索引擎算法更加複雜,它能夠根據互聯網上引用該網頁文檔,以及網頁文檔的點擊量,等綜合來定權重,權重越大的
排列會越靠前。

Lucene和Elasticsearch工做流程圖:java

  

Lucene:
文檔:Document
    它是包含了一個或多個域的容器,在Lucene將文檔中每一個詞組都稱爲域
       field: value

域:一個域它包含不少選項
    索引選項,存儲選項,每一項的域向量使用選項。可單個或組合使用。

    索引選項:用於經過倒排索引來控制文本是否可被搜索。
        Index:ANYLYZED: 分析(切詞)並單獨做爲索引項.
        Index:Not_ANYLYZED: 不分析(不切詞),把整個內容當一個索引項
        Index.ANYLYZED_NORMS: 相似於Index:ANALYZED,但不存儲token的Norms(加權基準)信息。
        Index.Not_ANYLYZED_NORMS:相似於Index:Not_ANALYZED,但不存儲值的Norms(加權基準)信息。
        Index.NO: 不對此域的值進行索引:所以不能被搜索。

    存儲選項:是否須要存儲域的真實值
        例如: 一個網頁的title: This is a Notebook。
            對於上面這個句子,在切詞後就是 This 和 Notebook.

        store.YES: 存儲真實值, 此選項則會將This和Notebook統一轉換爲小寫或大寫用於索引,
                            同時還會存儲This 和 Notebook這兩個原始值。
        store.NO:不存儲真實值. 而它則是表示不存儲This和Notebook的原始值,以便節省空間。

    域向量選項用於在搜索期間該文檔全部的惟一項都能徹底從文檔中檢索時使用。

    文檔和域的加權操做:
        加權計算標準:

            搜索:
                查詢Lucene索引時,它返回的是一個有序的scoreDOC對象,查詢時,Lucene會爲每一個文檔計算
                出其score,並根據分值進行排序。

            API:
                IndexSearcher: 搜索索引入口
                Query及其子類:
                QueryParser: 查詢分析器
                TopDocs: 將排名前十的文檔保存在其中,它是一個數組。
                ScoreDoc:查詢的結果文檔。

    Lucene的多樣化查詢:
     IndexSearcher中的search方法:
       TermQuery: 對索引中特定項進行搜索,Term是索引中的最小索引片斷,每一個Term包含了一個域名和一個文本值。
         示例:
            文檔1:
            title: This is a Desk.
            owner: Tom Blair.
            description: this is a desk, it's belong to Tom.
            文檔2:
            title: This is a table.
            owner: Clinton
            description: this is a desk, it's belong to Clinton.

            對於以上兩個文檔,對它們作索引:
            如今對這個兩個文檔作索引以下:
                this: 1, 2        #這表示this這個詞在,1號和2號文檔中都包含.
                desk: 1, 2
                Tom: 1
                Blair: 1
                belong: 1, 2
                table: 2
                Clinton: 2
                ....

            如今TermQuery查詢,指定僅查詢title域,中包含desk的文檔,那麼搜索的結果就只有
            1號文檔。

    TermRangeQuery: 在索引中的多個特定項中進行搜索,能搜索指定的多個域。
    NumericRangeQuery:作數值範圍搜索.
        如: 如今有如下文本:
            30
            34abc
            abc093
            44a
            90
            若使用NumericRangeQuery去搜索20-100的值的話,就會搜索出30,90,由於他們是數值.

    PrefixQuery: 用於搜索以指定字符串開頭的項。這就相似與SQL中"abc%"查詢以abc開頭的內容.
    BooleanQuery:它不是搜索布爾型,而是用於實現組合查詢的;組合邏輯有: AND,OR,NOT.
    PhraseQuery:它根據搜索關鍵字在文檔中的位置信息來肯定那個更加匹配。
        如: 我喜歡吃蘋果; 平安夜蘋果是平安果; 蘋果又大又紅很好吃。
            若使用PhraseQuery搜索蘋果,則第三個文檔中蘋果是在首位的,那它就最匹配,其次
            是第二個文檔,最後是第一個文檔。 
    WildcardQuery: 進行通配符查詢.
    FuzzyQuery:模糊查詢,根據與關鍵字的類似度來查詢,即類似99%,類似80%,60%...,
            越類似就排的越靠前。它是根據Levenshtein算法(距離算法)來作計算的。

    

       Lucene的索引文件,就是它的數據物理文件,在Lucene中稱爲索引,此索引文件有N多文檔組成,每個文檔都稱爲一行,這些行一般會歸類存放,但這並非必須的,Lucene中文檔能夠是任意的內容,如一個是關於動物種類的文檔,而另外一個多是描述房子建築的,這些能夠爲相鄰行,可是咱們一般不會這麼作,一般會歸類存儲,如:關於動物的文檔,關於人類的,關於飛禽類等放一個索引中等。

Elasticsearch:
      它藉助於Lucene的搜索功能,但它並不只僅是簡單使用,它還在Lucene的基礎上,對其功能作了更強大的實現,讓Lucene能夠支持分佈式存儲,Elasticsearch經過將Lucene的索引物理文件切分紅片,每個片稱爲 一個 Sharding ,對每一個分片,作全部節點上作冗餘備份,而且這些冗餘分片,是主從結構的(即:主:能讀能寫,從:僅讀),經過對索引文件分片,能夠分擔寫壓力,由於多數狀況下,寫僅會針對一個分片進行,而讀則可能會由於數據量很大,而從每一個節點都讀。
 對於Elasticsearch來講,它能夠:
  1.能自動對索引物理文件進行分片,並隨機分佈與Elasticsearch集羣中的每臺主機上。
  2.它能夠自動管理每一個分片的冗餘數量,一旦發現一個分片的冗餘數量不足,就會自動爲其建立分片,並隨機存儲在一個節點上.
  3.它會自動管理分片的讀寫,併爲用戶請求作代理。即:Elasticsearch中每一個節點都知道全局的分片存儲信息,用戶發來一個請求,  
    如: 一個讀請求,它會先看本地是否有要讀的這個分片,沒有就幫用戶將這個讀請求轉發給有該分片的節點,由該節點負責查詢,
    該節點查詢完成後,會將結果返回給接收用戶請求的節點,而後接收用戶請求的節點在將結果返回給用戶。對於寫請求也是同樣,
    先查本地,如有則看其是主仍是從,若沒有則轉發給有該主分片的節點上,執行寫入操做,完成後,再告訴接收用戶請求的節點,
    寫入完成了,接收用戶請求的節點在返回用戶寫入完成。
  4.對於Elasticsearch,它首先是一個分佈式存儲系統,若要對分佈式系統進行訪問,一則經過其API接口,寫程序訪問,二則經過其專用客戶端接口來訪問。
node

因此宗上所述,Elasticsearch它更像一個分佈式的集羣實時搜索管理引擎。

Elasticsearch的定義:
       ES是一個基於Lucene實現的開源,分佈式、基於Restful風格的全文本搜索引擎,此外,它仍是一個分佈式實時文檔存儲,其中每一個文檔的每一個field均是被索引的數據,且可被搜索,它也是一個帶實時分析功能的分佈式搜索引擎,可以擴展至數以百計的節點,實時處理PB級數據的搜索引擎。

基本組件:
       索引(index): 它其實就是一個文檔容器,或者說是相似屬性的文檔的集合,它相似於表.
          注: 索引名必須使用全小寫字母,並且ES中能夠建立N多個索引,根據須要建立.
  類型(type):類型是索引內部的邏輯分區,其意義徹底取決於用戶需求,一個索引內部可定義一個或多個類型.通常來講,
      類型就是擁有相同的域的文檔的預約義,不過每種類型之間無任何約束,如:一個索引中能夠有日誌類型,
      評論類型,文章類型等,不過建議一個索引中儘可能只有一個類型。
  文檔(document):文檔是Lucene索引和搜索的原子單位,它包含了一個或多個域(即:字段),它是域的容器。但文檔要基於
      JSON格式進行表示。每一個域的組成部分,一是名字,二是值,值能夠是一個或多個.甚至是一個文檔。
      一般將擁有多個值的域,稱爲多值域。
  映射(mapping):原始內容存儲爲文檔以前須要事先進行分析,如:切詞、過濾掉某詞等,而映射就是用於定義這種分析機制
      該如何實現的,除此以外,ES還爲映射提供了諸如將域中的內容排序等功能。能夠這樣理解: 在ES中,映射實際
      是索引外部的一個文件,它定義了一個文檔要怎麼分析,好比:
        This is a disk. 
      對於這個文檔,映射中規定,This,is,a,這些都是助詞,能夠忽略,只有disk是關鍵詞,須要將其切出來,這就是映射的做用。

Elasticsearch的集羣組件:
  Cluster:ES的集羣是根據集羣標識來組建的,默認標識爲'elasticsearch',若須要定義多個集羣,就必須手動修改集羣標識了,
      注: 節點是根據集羣標識來決定加入到那個集羣,並且一個節點只能屬於一個集羣。
  Node:即運行ES實例的主機,它用於存儲索引分片數據,參與集羣索引及搜索操做。節點的標識靠節點名,此節點名非主機名,
     它僅是此節點在集羣中的標識,默認會生成隨機字符串作爲其名字,建議手動定義可容易識別的節點名稱。
  Shard: 即分片,它就是將索引切割成物理存儲組件,但每個shard都是一個獨立且完整的索引,但在ES層面來看,它們是一個
     大索引的分片。建立索引時,ES默認會將其分割爲5個shard,但可根據集羣數量自定義分片個數。

shard有兩種類型:
  Primary shard: 即主分片,一個大索引物理文件,默認ES將其分紅5個主shard.須要注意,大索引被分紅幾個主shard只能在分割前設定,
        分割後,就不能修改了,若你想將其分紅6個,那就只能將5個分片組合成一個大索引後,在從新分紅6個主shard.
  replica shared: 即副本分片,它主要用於數據冗餘及查詢時的負載均衡,它是主分片的副本,它能夠隨時動態調整數量。

ES Cluster的工做過程:
  啓動時,ES集羣經過多播(默認) 或 單播方式在TCP的9300端口上,查找同一集羣中的其它節點,並與之創建通訊。集羣中的全部節點會選舉出一個主節點負責管理整個集羣狀態,以及在集羣範圍內決定各shards的分佈方式,因此站在用戶角度看,ES集羣中的每一個節點都可接收並響應用戶的各種請求。當一個節點宕機了,主節點會協調各節點進入維護模式,此時主節點會先查詢全部現存節點上,主分片是否缺失,副本分片是否夠數,來報告集羣目前的狀態,ES集羣有三種狀態:
  green: 正常狀態.
  red: 不可用狀態.
  yellow:修復狀態.此狀態下,全部副本shard都將進入維護模式,並都將不可用,僅主shard可用,所以此時讀將沒法負載均衡,
    吞吐能力將降低。ES在這種狀態下,主節點會檢查全部主分片是否都在,如有一個丟失,則從現存的副本shard中找一個,
    並將其提高爲主shard,接着在檢查副本shard是否均達到配額,如有副本數量缺乏的,則ES從新複製一個副本shard到
    一個節點上,並讓全部副本shard都達到配額副本shard後,再將集羣從yellow狀態轉爲green狀態。

ES集羣在運行過程當中,主節點會週期性檢查集羣中各節點是否宕機,是否可提供服務等,一旦發現有節點不可用,就會將集羣轉爲yellow狀態,並從新進入集羣的從新均衡。nginx

Elasticsearch是如何實現Master選舉的?
  Elasticsearch的選主是ZenDiscovery模塊負責的,主要包含Ping(節點之間經過這個RPC來發現彼此)和Unicast(單播模塊包含一個主機列表以控制哪些節點須要ping通)這兩部分;對全部能夠成爲master的節點(node.master: true)根據nodeId字典排序,每次選舉每一個節點都把本身所知道節點排一次序,而後選出第一個(第0位)節點,暫且認爲它是master節點。若是對某個節點的投票數達到必定的值(能夠成爲master節點數n/2+1)而且該節點本身也選舉本身,那這個節點就是master。不然從新選舉一直到知足上述條件。
補充:master節點的職責主要包括集羣、節點和索引的管理,不負責文檔級別的管理;data節點能夠關閉http功能。正則表達式

安裝ES2.0.0:
    任何集羣在配置前,必定要肯定時間同步。

node1:
1.準備Java環境
  查看當前系統是否安裝了 JDK1.7以上版本,以及其JDK1.7的 devel包。
  接着導出JAVA_HOME環境變量。
      vim  /etc/profile.d/java.sh
          export JAVA_HOME=/usr    #默認rpm包安裝會在/usr/bin/下建立一個java軟鏈接.
                                  此java軟鏈接時鏈接到/etc/下面的,而etc下面仍是一個軟鏈接.
                                  它是鏈接到正在的java,這樣作是爲了方便升級。

2.安裝ES
      yum install elasticsearch

    編輯配置文件:
    vim  /etc/elasticsearch/elasticsearch.yml
        cluster.name: myes
        node.name: "node1"
        node.master: true   #true:表示此節點參與主節點選舉.
        node.data: true     #true:表示此節點可用於存儲數據.
        index.number_of_shards:5     #每一個索引默認切成5個shard.
        index.number_of_replicas:1   #每一個shard默認保存1個副本。

        transport.tcp.port: 9300    #默認其集羣選舉的端口爲9300
        http.port: 9200                #默認接收並響應用戶請求的端口爲9200

        discovery.zen.minimum_master_nodes: 1   #最少主節點的數量,1個.
            注: 發現協議使用的是 ES的zen協議.
        discovery.zen.ping.timeout: 3s            #心跳檢查超時時間.
        discovery.zen.ping.multicast.enabled: false   #false:表示使用單播作心跳檢查.

    啓動ES:
        systemctl daemon-reload
        systemctl start elasticsearch.service
        systemctl status elasticsearch.service
           -Xms256m: 表示堆內存最小256M
           -Xmx1g: 表示最大堆內存1G


node2:
    1. 安裝JDK1.7 和 JDK1.7 devel
    2. 建立JAVA_HOME
        echo 'export JAVA_HOME=/usr' > /etc/profile.d/java.sh
    3. 安裝Elasticsearch
        yum install elasticsearch
    4. 編輯配置文件:
        vim  /etc/elasticsearch/elasticsearch.yml
            cluster.name: myes
            node.name: "node2"
    5. 啓動ES:
        systemctl daemon-reload
        systemctl start elasticsearch.service

    6. 此時就能夠抓包查看ES集羣傳遞的信息。

node3:
    1. 安裝JDK1.7 和 JDK1.7 devel
    2. 建立JAVA_HOME
        echo 'export JAVA_HOME=/usr' > /etc/profile.d/java.sh
    3. 安裝Elasticsearch
        yum install elasticsearch
    4. 編輯配置文件:
        vim  /etc/elasticsearch/elasticsearch.yml
            cluster.name: myes
            node.name: "node3"
    5. 啓動ES:
        systemctl daemon-reload
        systemctl start elasticsearch.service


ES的Restful API,共四類API:
    1. 檢查集羣、節點、索引等健康與否,以及獲取其相應狀態。
    2. 管理集羣、節點、索引及元數據
    3. 執行CRUB操做(即:增刪查改)
    4. 執行高級操做,如:paging,filtering等。

    ES API的訪問接口: TCP:9200,而且ES是基於HTTP協議工做的.

    curl -X <Verb> '<Protocol>://Host:Port/<Path>?<Query_String>' -d '<Body>'

        注:
            Verb: 即HTTP的操做,GET, PUT, DELETE等.
            Protocol: http,https
            Path: 訪問路徑.
            Query_String:查詢參數,如: '?pretty':表示使用容易讀的JSON格式顯示輸出.
            Body:請求的主體。

    如查看node1的狀態:
        curl -X GET 'http://1.1.1.1:9200/?pretty'


ES的API接口:

  _cat API:
    查看ES集羣的狀態:
        curl -X GET 'http://1.1.1.1:9200/_cat/nodes?v'
            注:
                _cat:     這是ES的API接口名,通常ES的API接口名使用下劃線開頭.
                          此接口的功能是輸出顯示的。
                ?v:      問號v,是修飾符,v:是verbose,顯示詳情。
                ?help:     可顯示幫助信息。
                ?h=name,ip,port,uptime,heap.current :可定義顯示那些列.

  _cluster APIs:
    查看ES集羣健康狀態詳情:
        curl -X GET 'http://1.1.1.1:9200/_cluster/health?pretty'

    查看索引的健康狀態:
    health
        curl -X GET 'http://1.1.1.1:9200/_cluster/health/索引名1,索引名2,...'
        curl -X GET 'http://1.1.1.1:9200/_cluster/health/索引名1?level=Level'
            注:
                cluster:顯示到集羣級別
                indices:顯示到索引級別
                shards:分片級別

    查看集羣的狀態信息:
    state:
        curl -X GET 'http://1.1.1.1:9200/_cluster/state/version'

        curl -X GET 'http://1.1.1.1:9200/_cluster/state/master_node?pretty'
        curl -X GET 'http://1.1.1.1:9200/_cluster/state/nodes?pretty'

    查看集羣的統計數據:
    stats:
        curl -X GET 'http://1.1.1.1:9200/_cluster/stats?pretty'

ES Plugins:
  插件可擴展ES的功能:
    可添加自定義的映射類型、自定義的詞幹分析器、本地腳本、自定義發現方式

  安裝插件:
    1. 直接將插件放到插件目錄中。
    2. 使用/usr/share/elasticsearch/bin/plugin命令來安裝插件。
        此命令的參數說明:
            -u  插件URL      #若能聯網,可直接提供互聯網插件URL便可安裝.
                            如果下載到本地,則可: file:///path/插件.zip
            -i  插件名        #安裝插件。

        插件安裝完,訪問方式:
            http://1.1.1.1:9200/_plugin/插件名/

            經常使用監控和管理插件:
                bigdesk
                marvel
                kopf
                head  #在ES6.x以上不少插件已經不在更新了,head插件在ES6.8.1中測試工做正常.

索引管理:
建立索引:[ES自動建立]
    注:
        若引用的索引不存在,則會自動建立。
        若引用的類型(type)不存在時,也是自動建立。
        id 是自定義的文檔標識,可以使用全局ID生成器來生成.若id衝突,則PUT時,默認是覆蓋。
    curl -X PUT 'http://1.1.1.1:9200/students/class1/1'  -H   "content-type: application/json"  -d '
                {
                    "first_name":"Guo",
                    'last_name':'Yang',
                    'gender':"Male",
                    'age':'26',
                    'courses':'GuMu ShenGong'
                }'
    
    curl -XPUT 'http://1.1.1.1:9200/students/class1/2'  -H   "content-type: application/json"  -d '
            {
                "first_name":"LongNv",
                "last_name":'Xiao',
                'gender':"Female",
                'age':'25',
                'courses':'GuMu LiYing'
            }'

查看建立的索引:
    curl -XGET 'http://1.1.1.1:9200/students/class1/1?pretty'

更新建立的文檔:
    curl -XPOST 'http://1.1.1.1:9200/students/class1/2/_update?pretty' -d '
        {
            "doc":{ "age": 23 }
        }'

刪除文檔:
    curl -XDELETE 'http://1.1.1.1:9200/students/class1/2'

刪除索引:
    curl -XDELETE 'http://1.1.1.1:9200/students'

    curl -XGET 'http://1.1.1.1:9200/_cat/indices?v'

查詢數據;
Query API:

    查詢使用的DSL(Domain Search Language):基於JSON的語言去構建複雜查詢。
        它用於實現諸多類型的查詢操做,如:簡單查詢,phrase,range,boolean,
        fuzzy(模糊查詢)等查詢。

    ES的查詢操做執行分爲兩個階段:
        1.分散階段:將用戶請求轉發到擁有該shared的節點上,執行操做。
        2.合併階段:執行操做的節點返回執行結果給,接收用戶請求的節點,由該節點合併結果返回用戶。

    查詢方式:
        向ES發起查詢請求的方式有兩種:
            1.經過Restful request API查詢,也稱爲query string.
            2.經過發送REST request body進行.

        查詢一個索引下的全部文檔:
            1.簡單的查詢字符串(Query String):
                curl -XGET 'localhost:9200/students/_search?pretty'
                    注:
                        took: 表示請求響應時間.
                        hits:使用了一個數組來記錄搜索到的文檔.
                        hits下面的_id: 文檔ID.
                                  _score: 這是文檔成績,如有加權,就由它記錄。
            2.REST Request Body
                curl -XGET 'localhost:9200/students/_search?pretty' -d '
                    { "query": { "match_all":{} }}'

    多索引,多類型查詢:
        curl -XGET 'http://1ocalhost:9200/_search/'  #全部索引
        curl -XGET 'http:/.../IndexName/_search/'      #單索引
        curl -XGET 'http://../Index1,Index2,../_search'      #多索引
        curl -XGET 'http://../t*,sh*/_search'                #通配符索引.
        curl -XGET 'http://.../tests/class1/_search'        #單類型搜索
        curl -XGET 'http://.../tests/class1,class2/_search' #多類型搜索。

        

Mapping和Analysis:
ES對每個文檔,取得其全部域的全部值,並生成一個名爲"_all"的域,執行查詢時,若在Query_String時,未指定查詢的域,則在_all域上執行查詢操做:

    #指定了查詢域,則表示在courses域中作精確查詢:
    #模糊:
        curl -XGET 'URL/_search?q=courses:"GuMu"'
    #精確:
        curl -XGET 'URL/_search?q=courses:"GuMu%20ShenGong"' #%20是空格的轉義

    #下面是沒有指定查詢域,則在_all域上執行查詢:
    curl -XGET 'http://localhost:9200/students/_search?q="Yang"&pretty'
    curl -XGET 'http://localhost:9200/students/_search?q="Yang%20Guo"&pretty'
    
    #建立age:25 和 desc:"total 25"兩個文檔,當不指定域,在_all域中搜索時,作如下測試:
    curl -XGET 'http://localhost:9200/students/_search?q=25'    

ES中的數據類型:
    string, numbers, boolean, dates

查看指定類型(type)的mapping:
    curl 'URL/students/_mapping/class1?pretty'  #查看class1這個type的mapping.
    
ES中搜索的數據廣義可被理解爲兩類:
    types:    exact        #精確搜索
              full-text    #全文搜索

    精確值:指未經加工的原始值,在搜索時進行精確匹配.
            如:Apple, 則Apple不能被轉換爲apple再去查詢,必須是查詢Apple
    full-text:用於引用文本中數據,判斷文檔在多大程度上匹配查詢請求,即評估文檔與用戶
            請求查詢的相關度. 爲了完成full-text搜索,ES必須首先分析文本,並建立出
            倒排索引,在倒排索引中的數據還須要進行「正規化」爲標準格式:
            即:先分詞,後正規化,這個過程叫「分析」,由analyzer完成。

    分析須要由分析器進行: analyzer

        一個分析器由三個部分組成: 字符過濾器,分詞器,分詞過濾器

        ES內置的分析器:
            Standard Analyzer: 它比較通用,ES默認使用它作分析,它使用Unicode標準作分詞.
            Simple analyzer:它是根據非字母字符作單詞邊界,來分詞分析。
            Whitespace analyzer:它是根據空白字符做爲單詞邊界,來分詞分析。
            Language analyzer:使用於不一樣語言的專用語言單詞分析器

            分析器不只在建立索引時用,在構建查詢時也須要用到.
            簡單理解: 構建索引時使用了Standard analyzer,但在構建查詢時使用了
                simple analyzer,則兩者的構建的結構可能存在差別,於是查詢結果
                也會帶來很大影響。因此不建議這樣使用。

Query DSL:
請求主體部分分紅兩類查詢:
Query DSL: 執行full-text查詢時,基於相關度來評判其匹配結果:
        所以其查詢執行過程複雜,且不會被緩存。但使用基於倒排索引的機制,也能夠實現
        接近於實時的查詢。
Filter DSL:執行exact(精確)查詢時,基於其結果爲「yes"或「no」進行評判:
        所以其查詢執行簡單,速度快,且結果容易被緩存。

    查詢語句的結構:
        {
            QUERY_NAME:{
                ARGUMENT:VALUE,
                ARGUMENT:VALUE,...
            }
        }

        {
            QUERY_NAME:{
                FIELD_NAME:{
                    ARGUMENT:VALUE,..
                }
            }
        }
filter DSL:
term filter:精確匹配指定項(term)的文檔。
        如: "Guo", "Jing" , "Guo%20Jing" 這三個都是一個term.
        示例:
            { "term": {"name":"Guo"}} #判斷name中是否包含Guo這個字符串的term filter。
        查詢格式:
            curl -XGET 'URL/students/_search?pretty' -d '{
                "query": {
                    "term": {           #單值匹配
                        "name":"Guo"
                    }
                }
            }'

terms filter: 用於多值精確匹配:
    查詢格式:
        curl -XGET 'URL/students/_search?pretty' -d '{
                "query": {
                    "terms": {          #多值匹配
                        "age":[20,22,18,30,27]
                    }
                }
            }'

range filters: 用於在指定的範圍內查找數值或時間.【僅能查詢數值和時間】
    查詢格式:
        curl -XGET 'URL/students/_search?pretty'  -H "content-type: application/json"  -d '{
                "range": {
                    "age": {       #測試失敗,"Unknown key for a START_OBJECT in [range]." 沒有找到緣由
                        "gte":15,
                        "lte":25
                    }
                }
            }'
            注: gt:大於,lt:小於, gte:大於等於,lte:小於等於

exists 和 missing filters: 用於判斷指定查詢內容是存在 或 不存在.
    查詢格式:
        curl -XGET 'URL/students/_search?pretty' -d '{
                "exists": {
                    "age": 28
                }
            }'

boolean filter:基於boolean的邏輯來合併多個filter子句:
    must: 其內部全部的子句條件必須同時匹配,即and:
        格式:
            must: {
                "term":{ "age": 25 }
                "term":{ "gender": "Female"}
            }     #查詢年齡在25歲的女人

    must_not: 其全部子句必須不匹配,即not
        格式:
            must_not: {
                "term":{ "age": 25 }
            }

    should: 至少有一個子句匹配,即:or
        格式:
            should: {
                "term":{ "age": 25 }
                "term":{ "gender": "Female"}
            }     #查詢年齡是25歲的 或 是女人的

Query DSL:
match_all Query:
    用於匹配全部文檔,若沒有指定任何query,默認即爲 match_all查詢.
        如: { "match_all": {} }

match Query:
    在幾乎全部域上執行full-text 或 exact-value查詢:
    full-text:會先作語句分析再查詢。
        如:
            { "match": {"students":"Guo"}}  
             #這是在students索引中查詢全部包含"Guo"的內容
    exact-value:精確值匹配時,不須要分析.但它不會緩存,因此此時建議使用過濾,而非查詢.
        如:
            { "match":{"name":"Guo"}}

multi_match Query:
    用於在多個域上執行相同查詢:
        格式:
            {
                "multi_match":
                    "query":{ '索引 | 類型 ': "QueryString"}
                    "field":{ 'field1', 'field2'}
            }
        如:
            {
                "multi_match":
                    "query":{
                        "students":"Yang"
                    }
                    "field":{
                            "name",
                            "description"
                        }
            }        #這就是在students索引內部的name和description域上查詢包含"Yang"的內容

bool query:
    基於boolean邏輯合併多個查詢語句,與bool filter不一樣的是,查詢子句不返回
    yes/no, 而是計算出匹配度分值,所以,boolean Query會爲各子句合併其score值:
        使用格式:
            must:
            must_not:
            should:

合併filter和Query:
    一般會將filter嵌套在query中組合使用,但不多將query嵌套在filter中過濾。
        {
            "filterd":{
                query:{
                    "match":{"gender":"Female"}
                }
                filter:{
                    "term":{"age":25}
                }
            }
        }

查詢語句的語法檢查:
    curl -XGET 'URL/INDEX_NAME/_validate/query?pretty'  -H "content-type: application/json"  -d '{ ... }'

    示例:
        curl -XGET 'localhost:9200/students/_validate/query?pretty'  -H "content-type: application/json"  -d '{
            "query":{"term":{ "name": "Guo" }}    
        }'    #注:前面提到索引構建的分析器有,存儲原值和不存原值的選項,若建立索引時,
               分析器使用的是不存儲原值,則分析器會自動會將全部數據都轉換爲小寫索引
               並存儲,因此這裏作精確值匹配時,是沒有'Guo'這樣的字符串的。也就是說
               索引存儲的分析器和查詢分析器不同致使的問題。


    分析語法時顯示錯誤信息:
        curl -XGET 'URL/INDEX_NAME/_validate/query?explain&pretty' -d '{ ... }'

 

ELK Stack的兩個組件:
  L: Logstash
  K: Kibian

Logstash:
  支持多種數據獲取機制,經過TCP/UDP協議、文件、syslog、Windows EventLogs及STDIN等,獲取到數據後,它支持對數據執行過濾、修改等操做。另外Logstash它自己不只有日誌收集功能,它還支持索引構建,不過它的索引和ES的索引構建不是一個量級的。
  它使用JRuby語言研發,須要運行在JVM上,而且爲Agent/Server模型。

工做原理:
  WebNode1【L_Agent】--->【Broker:掮客(如:Redis)】<--->【L_Server】--->【ES集羣】
  Logstash如上圖所示,它須要在每一個日誌收集端安裝Agent,由Agent來收集目標節點上指定的日誌信息,並將這些日誌信息先發送給Broker(消息隊列),接着Logstash再從
Broker中取出數據,在本地執行分析,再過濾,最後輸出給ES集羣。

Logstash Server:
  它是一個嚴重插件式服務器,它除了核心功能外,主要部件都使用插件來完成工做,首先是INPUT Plugin,如有消息隊列,則根據消息隊列可選擇對應的INPUT Plugin,若
直接從Agent接收數據,由Agent相關的插件; 接着是Codec Plugin,這是logstash的分析插件,能夠根據數據來定義如何分析,此類插件也有十多種;再接着是filter plugin
這是它的過濾插件,主要完成數據過濾,僅將須要的數據過濾出來,並最終發給OUTPUT plugin,由它將最終數據發送給ES集羣。   redis

安裝logstash
  1.先準備JAVA運行環境,導出JAVA_HOME
  2.安裝logstash
    logstash能夠在ELK的官網直接下載。
  3.安裝好logstash後,默認RPM是安裝在/opt/logstash/bin下面的。
   vim /etc/profile.d/logstash.sh
    export PATH=/opt/logstash/bin:$PATH
  4.建立一個簡單的從標準輸入接收數據,從標準輸出來輸出數據的配置文件:
   vim /etc/logstash/conf.d/smiple.conf
    input {
      stdin {}
     }

    output {
      stdout {
        codec => rubydebug
        }
      }

檢測配置文件語法:
  logstash -f /etc/logstash/conf.d/smiple.conf --configtest

直接運行:
 logstash -f /etc/logstash/conf.d/smiple.conf
  #當出現Logstash startup,則啓動成功。
  #這時就能夠輸入日誌,作測試:
  Hello Logstash

 Logstash的配置文件框架格式:
  input { .... }
  filter { .... }
  codec { .... }
  output { .... }

 它支持如下數據類型:
  Array: [item1, item2,...]
  Boolean: true, false
  Bytes: 字節值
  Codec: 編碼器類型
  Hash:key => value, key => value, ...
  Number: 數值型,浮點型
  Password:不記錄或記錄爲星號的密碼串
  Path:文件系統路徑
  String:字符串

  字段引用: []

  條件判斷:
    ==, !=, <, <=, >, >=
    =~, !~ : 匹配和不匹配
    in, not in: 包含 或 不包含
    and, or
    ()算法

 

Logstash的工做流程:
    input | filter | output  #能夠將Logstash當作一個管道,filter是可選的。

Logstash的插件:
  input插件:
    File: 從指定的文件中讀取事件流,它從文件中獲取日誌最新變化的方式相似於tail -f,
        叫作FileWatch,雖然FileWatch是文件系統的一個功能,但此插件是使用Ruby Gem
        庫實現了此功能,File插件每次讀取完最新日誌後,會記錄讀取信息,如讀到哪一行:pos,
        該日誌文件的inode,以及該日誌文件所在磁盤設備的major number,minor number等信息。
        固然這些信息是存儲在一個叫「.sincedb」中的,默認在運行logstash Agent的用戶家目錄中,
        另外,File插件可自動識別日誌滾動後的文件。

  示例:
    vim /etc/logstash/conf.d/fromfile.conf
        input {
            file {
                path => ["/var/log/messages"]   #定義爲數組類型.
                type => "system"                #類型是用來定義,在其它地方引用時的
                                                的字符串標識,可爲任意字符.例如:
                                                可在過濾時,指定對哪些類型的信息作過濾.
                start_position => "beginning"    #定義從哪裏開始讀取日誌文件
            }
        }

        output {
            stdout {
                codec => rubydebug
            }
        }

    udp插件:在logstash server端啓動一個進程監聽在指定端口上,接收遠端主機發來的日誌信息。
            它主要須要定義:port 和 host,監聽端口和地址。

            示例:
                collectd: 這是一個用C語言開發的,服務性能監控程序,它能夠將收集到的
                        服務器上的性能數據收集起來,經過不一樣的插件存儲到不一樣的位置,它
                        有一個network插件,這次udp示例,就須要使用它的network插件,
                        來將收集到的服務器性能數據發送給logstash。

        在collectd服務器端配置:
            1. 安裝collectd ,在epel源中有
            2. 修改collectd的配置文件:
                vim /etc/collectd.conf
                Hostname 'node1.a.com'
                Loadplugin  network   #啓用監控主機的哪些數據,如:CPU,內存,磁盤,接口等.但,在這裏要找到network插件,並啓用它。
                                
                <Plugin network>    #這是對network插件的功能定義.不一樣插件有不一樣的
                                    #功能定義,也有的插件沒有。
                    <Server "1.1.1.1" "25826">    #定義接收數據的服務器是誰,及其端口.
                       ..若須要認證,可定義認證選項..
                       ResolveInterval 2000       #設置收集數據的時間間隔,此設置爲每隔2秒發送一次
                    </Server>
                </Plugin>

                systemctl start collectd.service

        在Logstash服務器端配置:
            配置logstash來接收collectd發來的服務器性能數據
                input {
                    udp {
                        port => 25826
                        codec => collectd   {}            #這是logstash專門對collectd提供的解析器
                        type => "collectd"
                    }
                }

                output {
                    stdout {
                        codec => rubydebug
                    }
                }

    redis插件:
        從redis讀取數據,支持redis channel 和 list的兩種方式。


filter插件:
用於將收到的event經過output發出以前對其實現某些處理功能的.

grok: 它是在處理Web服務日誌時,必須使用的插件; grok是用於分析並結構化
    文本數據,它是目前,logstash中將非結構化日誌數據轉化爲結構化的可查詢
    數據的不二之選。

    它的模式定義位置:
        rpm -ql logstash |grep 'patterns'
        其中有一個叫 'grok-patterns'的文件,它就是模式匹配文件.
        #在ubuntu上位置:
            /usr/share/logstash/vendor/bundle/jruby/2.5.0/gems/logstash-patterns-core-4.1.2/patterns/
                    #說明: 在這個目錄下有不少模式匹配文件,其中的關鍵字均可以直接使用.

    grok模式定義的語法格式:
        %{SYNTAX:SEMANTIC}
            SYNTAX:預約義模式名稱,它可自定義,若沒有相關預約義的配置,其語法就是:
                SYNTAX_NAME 正則表達式
            SEMANTIC:匹配到的文本的自定義標識符
        如:
            1.1.1.1 GET /index.html 30 0.23
            匹配此段日誌信息的模式爲:
            %{IP:clientip} \ #IP: 是grok.patterns文件中定義的SYNTAX,
                              clientip:是IP這個預約義模式匹配到的值,存放的變量名。
            %{WORD:method} \
            %{URIPATHPARAM:request} \
            %{NUMBER:bytes} \
            %{NUMBER:duration}

    使用示例:
        vim /etc/logstash/conf.d/grok.conf
            input {
                stdin {}
            }

            filter {
                grok {
                    match => {
                        "message" => "%{IP:clientip} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}"
                    }
                }
            }

            output {
                stdout {
                    codec => rubydebug
                }
            }

    啓動測試:
        1. 檢查配置文件語法
            logstansh -f /etc/logstash/conf.d/grok.conf --configtest

        2. 啓動logstash
            logstansh -f /etc/logstash/conf.d/grok.conf

        3. 測試輸入:
            1.1.1.1 GET /index.html 30 0.23

    示例2:
        測試讀取httpd的access_log文件

        vim /etc/logstash/conf.d/apachelog_grok.conf
            input {
                file {
                    path => ["/var/log/httpd/access_log"]
                    type => "ApacheLog"
                    start_position => 'beginning'
                }
            }

            filter {
                grok {
                    match => { "message" => "%{COMBINEDAPACHELOG}"}
                }
            }

            output {
                stdout { codec => rubydebug }
            }

        1. 檢查配置文件語法
            logstansh -f /etc/logstash/conf.d/apachelog_grok.conf --configtest

        2. 啓動logstash
            logstansh -f /etc/logstash/conf.d/apachelog_grok.conf

        3. 啓動apached 並 嘗試訪問一次默認首頁。







output插件:
  redis插件的使用示例:
    1. 在epel源中安裝redis
    2. 配置redis
        vim /etc/redis.conf
            port 6396
            host 0.0.0.0
    3.啓動redis
        systemctl start redis

    4.編寫配置文件
        vim /etc/logstash/conf.d/redis_form_nginxlog.conf
            input {
                file {
                    path => ["/var/log/nginx/access.log"]
                    type => "NginxLog"
                    start_position => "beginning"
                }
            }

            filter {
                grok {
                    match => { "message" => "%{NGINXACCESS}"}
                }
            }
            output {
                redis {
                    batch => false     #若爲true:則表示如有多個數據要發佈時,redis可一次
                                        性打包發佈,使用RPUSH方式。
                    port => "6379"
                    host => ["127.0.0.1"]    #redis若安裝在本機,可默認不寫
                    data_type => "list"
                    key => "logstash-%{type}"  #type:是引用input中的type值。
                }
            }

    檢測logstash的配置文件
    啓動logstash

    嘗試訪問nginx頁面

    登陸redis查看
        redis-cli
        127.0.0.1:6379> LLEN logstash-nginxlog    #logstash-nginxlog:是output中定義key的值
        127.0.0.1:6379>LINDEX logstash-nginxlog 0  #查看key中索引號爲0的值



配置從redis中讀數據,並存儲到後端的ES集羣中:
 node3:
    做爲Logstash Agent節點配置:
    1. 在epel源中安裝redis
        配置redis
            vim /etc/redis.conf
                port 6396
                host 0.0.0.0
        啓動redis
            systemctl start redis

    2. 安裝nginx,使用默認配置,直接啓動nginx
    3. 嘗試訪問nginx頁面
    
    4.安裝java-openjdk-8.0以上,並配置JAVA_HOME
    5.安裝logstash
    6.配置logstash
       vim /etc/logstash/conf.d/redis_form_nginxlog.conf
            input {
                file {
                    path => ["/var/log/nginx/access.log"]
                    type => "NginxLog"
                    start_position => "beginning"
                }
            }

            filter {
                grok {
                    match => { "message" => "%{NGINXACCESS}"}
                }
            }
            output {
                redis {
                    port => "6379"
                    host => ["127.0.0.1"]    #redis若安裝在本機,可默認不寫
                    data_type => "list"
                    key => "logstash-%{type}"  #type:是引用input中的type值。
                }
            }

    7. 啓動logstash
        logstash -f /etc/logstash/conf.d/redis_from_nginxlog.conf

    8. 登陸redis查看
        redis-cli
        127.0.0.1:6379> LLEN logstash-nginxlog    #logstash-nginxlog:是output中定義key的值
        127.0.0.1:6379>LINDEX logstash-nginxlog 0  #查看key中索引號爲0的值


node2:
    做爲Logstash server節點配置:
    1.安裝java-openjdk-8.0以上,並配置JAVA_HOME
    2.安裝logstash
    3.配置logstash
      vim /etc/logstash/conf.d/server.conf
        input {
            redis {
                #這裏須要注意: logstash從Redis中讀取logstash寫進去的日誌後,它會將其自動刪除,此可經過Windows版的RedisClient工具查看最爲清晰。
                port => "6379"
                host => "1.1.1.3"
                data_type => "list"
                key => "logstash-nginxlog"
            }
        }

        output {
            elasticsearch {
                #cluster => "loges"
                hosts  =>  ["http://1.1.1.1:9200"]
                index => "logstash-%{+YYYY.MM.dd}"  #這裏要注意:寫到Elasticsearch中的index鍵必須是小寫!!不然再向ES中寫時會報錯
            }
        }
    4.檢查配置文件語法
    5.啓動logstash

node1:
    配置爲ES集羣的節點,這次測試作單節點
    1. 安裝openjdk1.7以上的, 完成後配置JAVA_HOME
    2. 安裝ES
        yum install elasticsearch
    3. 編輯ES的配置文件
        vim /etc/elasticsearch/elasticsearch.conf
            cluster.name loges
            node.name: "node1.a.com"
    4.啓動ES
        systemctl daemon-reload
        systemctl start elasticsearch.service
    5.安裝ES的插件
        /usr/share/elasticsearch/bin/plugin -i bigdesk -u file:///path/bigdesk.zip
    6.安裝kibana
        從ES官網下載kibana後
        tar xf kibana.tar.gz -C /usr/local/
        cd /usr/local/kibana/config/
        vim kibana.yml
            修改ES的訪問URL爲ES集羣中的任意一個節點IP便可。
        啓動kibana
            /usr/local/kibana/bin/kibana &
        訪問kibana
            http://kibana_IP:5601/

    7. 先訪問node3上的nginx,讓其產生新日誌信息
    
    8. 嘗試在ES集羣上使用查詢看看可否收到這些新日誌信息
        curl -XGET 'http://1.1.1.1:9200/_cat/indices'  #查看ES集羣中全部的索引信息
        curl -XGET 'http://1.1.1.1:9200/logstash-2018xxx/_search?pretty'
相關文章
相關標籤/搜索