国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

快速搭建ELK日志收集(kafka隊列版)

妤鋒シ / 948人閱讀

摘要:快速搭建日志收集版本進行文章的第二次修改,包括了之前的簡單方案的升級過程。分割線快速搭建日志收集第一版本新項目短時間來實現日志采集。

快速搭建elk日志收集 kafka版本

進行文章的第二次修改,包括了之前的簡單方案的升級過程。

因為業務的不斷更新升級,為了保證線上業務也能正常使用elk服務,并且使得elk的服務和線業務流解耦(即避免直接寫入es的方式可能會帶來的耗時影響)所以我們采用了下面最新的方案,也是常規方案

方案
業務層 >> kafka隊列 >> logstash 消費 >> elasticsearch

業務層將日志寫入到kafka隊列,同事logstash可以開啟多個線程,啟用同一個group_id來對kafka進行消費,將讀取到的日志進行解析后,寫入到elasticsearch中,并且按照索引模板進行解析。

優點

業務層可以直接寫入到kafka隊列中,不用擔心elasticsearch的寫入效率問題。

缺點

比起之前的簡單版本,需要保證kafka隊列、logstash的高可用(雖然logstash掛掉后,可以重啟后重新讀取隊列日志)

搭建

整個搭建過程,寫入kafka是非常簡單的,這里遇到的問題是logstash和elasticsearch索引模板帶來的困擾。

logstash內置一套模板

elasticsearch 本身可以自定義一套模板

如何確定使用誰的模板呢?
網上找到的資料,建議采用將模板配置在elasticsearch側,這樣就不用每個logstash進行一個模板配置文件的維護。

Logstash 配置文件說明

官網的文檔kafka的input插件
https://www.elastic.co/guide/...

input {
    kafka {
        // 需要讀取的kafka隊列集群配置
        bootstrap_servers => "xxx.xxx.xxx.xxx:9092"
        // 配置的消費者的group名稱,因為同一個組內的消費消息不會重復
        group_id => "logstash-group"
        // 主題配置
        topics => "kibana_log"
        // 從未消費過的偏移量開始
        auto_offset_reset =>"earliest"
    }
}

// 重要,下面多帶帶講
filter {
  json {
    source => "message"
  }
}

output {
    // stdout可以省略,這個是為了命令行模式下方便調試
    stdout{ codec => rubydebug }
    elasticsearch {
        // es 集群
        hosts=>"xxx.xxx.xxx.xxx:9200"
        // 重要:取消logstash自定義模板功能,進而強制使用es的內置模板
        manage_template=>false
        // 需要匹配的模板名稱
        index=>"logstash-dev-%{+YYYY.MM.dd}"
    }
}

先解釋下filter配置,當我們從kafka讀取消息的時候,消息體是通過message字段來進行傳遞的,所以message是一個字符串,但是我們的es索引模板可能會非常復雜,所以我們需要對其進行json解析后,再交給es。否則es收到的之后一個message字段。

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

再說下模板配置,首先通過kibana的devtool向es中寫入了一個模板,我區分了兩套環境dev、prod。

Php 實現寫入

這里字段都進行了strval轉義,為什么呢?這和下面要講的動態模板有關聯的。往下看

$position = YnUtil::getPosition();

$urlData = parse_url(Wii::app()->request->url);
$path    = $urlData["path"] ?? "";

$params = [
    "category"   => strval($category),
    "appType"    => strval(YnUtil::getAppType()),
    "appVersion" => strval(YnUtil::getAppVersion()),
    "host"       => strval(Wii::app()->request->hostInfo),
    "uri"        => strval(Wii::app()->request->url),
    "uid"        => strval(Wii::app()->user->getUid()),
    "path"       => strval($path),
    "server"     => strval(gethostname()),
    "geoip"      => [
        "ip"       => strval(Yii::$app->request->userIP),
        "location" => [
            "lat" => floatval($position["latitude"]),
            "lon" => floatval($position["longitude"]),
        ],
    ],
    "userAgent"  => strval(Wii::app()->request->userAgent),
    "message"    => is_array($message) ? Json::encode($message) : strval($message),
    // "@timestamp" => intval(microtime(true) * 1000),
];
索引模板

下面的模板是寫入到es里面的自定義模板,為了防止索引規則名稱沖突,這里將order置為1。

我們先來看下第一個模板(這個是不推薦的,因為很繁瑣,但是類型很強制有效)

PUT _template/logstash-dev
{
    "index_patterns": "logstash-dev*",
    "aliases": {},
    "order":1,
    "mappings": {
      // 這里使用logs是因為logstash默認的type類型
      "logs": {
        // 動態模板
        "dynamic_templates": [
          {
            "string_fields": {
              "match": "*",
              "match_mapping_type": "string",
              "mapping": {
                "fields": {
                  "keyword": {
                    "ignore_above": 256,
                    "type": "keyword"
                  }
                },
                "norms": false,
                "type": "text"
              }
            }
          }
        ],
        // 這里對屬性進行了類型設置
        "properties": {
          "@timestamp": {
            "type": "date"
          },
          "@version": {
            "type": "keyword"
          },
          "appType": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "appVersion": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "category": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "geoip": {
            "dynamic": "true",
            "properties": {
              "ip": {
                "type": "ip"
              },
              "latitude": {
                "type": "half_float"
              },
              "location": {
                "type": "geo_point"
              },
              "longitude": {
                "type": "half_float"
              }
            }
          },
          "host": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "message": {
            "type": "text",
            "norms": false
          },
          "server": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "uid": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "uri": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "path": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          },
          "userAgent": {
            "type": "text",
            "norms": false,
            "fields": {
              "keyword": {
                "type": "keyword",
                "ignore_above": 256
              }
            }
          }
        }
      }
    },
    "settings": {
      "index": {
        "number_of_shards": "1"
      }
    }
}
動態模板概念

上面的模板不是最優的,但是卻是一種嘗試,模板里面針對每個屬性做了設置,這樣客戶端只需要寫入對應的屬性就好了。但是如何動態配置呢?如果想加入一個字段,難道還要修改模板么? 這里引入了動態模板的概念

Only the following datatypes can be automatically detected: boolean, date, double, long, object, string. It also accepts * to match all datatypes.

動態映射
https://www.elastic.co/guide/...

動態模板(注意看match和match_mapping_type)
https://www.elastic.co/guide/...

映射屬性
https://www.elastic.co/guide/...

然后我們給出了一個全新的模板

全新索引模板

這個模板里面只針對特殊的屬性進行了設置,其他的都是通過動態模板擴展的,下面看下效果。

PUT _template/logstash-dev
{
    "index_patterns": "logstash-dev*",
    "aliases": {},
    "order":1,
    "mappings": {
      "logs": {
        "dynamic_templates": [
          {
            "string_fields": {
              "match": "*",
              "match_mapping_type": "string",
              "mapping": {
                "fields": {
                  "keyword": {
                    "ignore_above": 256,
                    "type": "keyword"
                  }
                },
                "norms": false,
                "type": "text"
              }
            }
          }
        ],
        "properties": {
          "@timestamp": {
            "type": "date"
          },
          "@version": {
            "type": "keyword"
          },
          "geoip": {
            "dynamic": "true",
            "properties": {
              "ip": {
                "type": "ip"
              },
              "latitude": {
                "type": "half_float"
              },
              "location": {
                "type": "geo_point"
              },
              "longitude": {
                "type": "half_float"
              }
            }
          }
        }
      }
    },
    "settings": {
      "index": {
        "number_of_shards": "1"
      }
    }
}

我們上面說了,全都進行了strval轉義,為什么呢?因為動態模板里面,匹配的是string類型,如果我們寫入的是一個int類型,那么就不會進行自動擴展了。試驗后表明,會生成一個int類型的message字段,這樣是不合理的。最終生成的效果是如下圖的。

分割線 =============================

快速搭建elk日志收集 第一版本

新項目短時間來實現日志采集。

資源

一臺8G 4核 500G硬盤 服務器

部署方案

項目部署在4臺服務器,每臺服務器通過phpsdk直接寫入一臺es服務器中。
(在本次部署中,沒有使用logstash的功能)

缺點

沒有使用異步隊列,導致直接寫入es可能會影響業務邏輯,但是目前只會在開發和測試環境使用。

組件

主要利用elasticsearch 和 kibana
要使用x-pack做安全校驗,包括給kibana加入登錄授權功能

Elasticsearch
https://www.elastic.co/cn/pro...

Elasticsearch-clients
這里包含的多種語言的sdk包
https://www.elastic.co/guide/...

Kibana
https://www.elastic.co/cn/pro...

Logstash
https://www.elastic.co/cn/pro...

X-pack
安裝流程說明很詳細,秘鑰生成后記得保存下,并且加入x-pack后,kibana和elasticsearch的通訊,需要修改配置文件。另外phpsdk也需要加入秘鑰,后面說明。
https://www.elastic.co/cn/pro...

配置 創建索引

es的模板超級復雜的,所以我們要利用標準的現有的模板,需要從logstash中提取一個。
解壓下載的logstash-6.1.2.tar,執行搜索命令

$ find ./  -name "elasticsearch-template*"
./vendor/bundle/jruby/2.3.0/gems/logstash-output-elasticsearch-9.0.2-java/lib/logstash/outputs/elasticsearch/elasticsearch-template-es2x.json
./vendor/bundle/jruby/2.3.0/gems/logstash-output-elasticsearch-9.0.2-java/lib/logstash/outputs/elasticsearch/elasticsearch-template-es5x.json
./vendor/bundle/jruby/2.3.0/gems/logstash-output-elasticsearch-9.0.2-java/lib/logstash/outputs/elasticsearch/elasticsearch-template-es6x.json

會發現有2x 5x 6x三個模板,這里我們選擇6x,要根據你的es版本來選擇。
然后創建索引,索引要在數據寫入之前創建,因為要給每個字段設置類型。

創建索引模板

https://www.elastic.co/guide/...

按照文檔的方式,將獲取到的6x通過curl的方式寫入到es

Es開啟外網訪問

因為默認的es配置是開啟了localhost:9200端口,用于執行RESTFUL,但是本次我們采用php-sdk的方式,直接寫入es,就要求每臺業務服務器,都能訪問到es。

# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
# 修改此處的host配置為0.0.0.0,這樣所有的請求都可以接入進來
network.host: 0.0.0.0
#
# Set a custom port for HTTP:
#
#http.port: 9200
使用client sdk

下載地址
https://www.elastic.co/guide/...

try {
    $hosts = [
        // 這個地方要填寫x-pack分配的密碼和用戶名
        "http://{用戶名}:{密碼}@192.168.1.11:9200",       // HTTP Basic Authentication
        // "http://user2:pass2@other-host.com:9200" // Different credentials on different host
    ];

    $client = ClientBuilder::create()->setHosts($hosts)->build();

    $position = YnUtil::getPosition();

    $params = [
        "index" => "logstash-yn-" . date("Ymd"),
        // elastic6版本有個bug,每個索引只能有一個type類型
        "type"  => "xxxx",
        "id"    => md5(rand(0, 999999999)) . (microtime(true) * 1000),
        "body"  => [
            // 索引創建好后,寫入數據一定要注意類型,不然會報錯,我這里都會進行格式化一遍
            // 類別作為一個主要字段用于區分日志
            "category"   => strval($category),
            "appType"    => strval(YnUtil::getAppType()),
            "appVersion" => strval(YnUtil::getAppVersion()),
            "host"       => strval($hostInfo),
            "uri"        => strval($url),
            "uid"        => strval($user->getUid()),
            "server"     => strval(gethostname()),
            "geoip"      => [
                "ip"       => strval($ip),
                // 這個很重要,可以實現geo可視化圖形
                "location" => [
                    "lat" => floatval($position["latitude"]),
                    "lon" => floatval($position["longitude"]),
                ],
            ],
            "userAgent"  => strval($userAgent),
            "message"    => Json::encode($message),
            // 這里一定要寫入毫秒時間戳
            "@timestamp" => intval(microtime(true) * 1000),
        ],
    ];

    $client->index($params);

} catch (Exception $e) {

}

安裝好x-pack后,sdk也要配置用戶名和密碼

日志的索引,按照日期來構建名稱

elastic6版本,每個索引只能有一個type類型,這是一個bug

geoip是logstash的模板中定義的字段,可以實現geo可視化(稍后解釋模板)

@timestamp 這里一定要毫秒時間戳

要捕獲報錯日志,不要影響業務邏輯

模板說明

官方說明
https://www.elastic.co/guide/...

我們這里以6x作為模板

{
    // 將這個模板應用于所有以 logstash- 為起始的索引。
    "template": "logstash-*",
    "version": 60001,
    "settings": {
        "index.refresh_interval": "5s"
    },
    "mappings": {
        "_default_": {
            //  動態模板說明,很重要,配置了動態模板后,我們可以添加任意字段
            // https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-templates.html
            "dynamic_templates": [{
                // 信息字段 官方說這里可以自定義 The template name can be any string value.
                "message_field": {
                    "path_match": "message",
                    "match_mapping_type": "string",
                    "mapping": {
                        "type": "text",
                        "norms": false
                    }
                }
            }, {
                // 字符串字段說明
                "string_fields": {
                    // 匹配所有
                    "match": "*",
                    // 并且字段類型是string的
                    "match_mapping_type": "string",
                    // 
                    "mapping": {
                        "type": "text",
                        // 這里應該是和受歡迎程度評分相關
                        "norms": false,
                        "fields": {
                            "keyword": {
                                "type": "keyword",
                                "ignore_above": 256
                            }
                        }
                    }
                }
            }],
            // 定義好的屬性說明
            "properties": {
                // 時間字段,這個很重要,不然kibana不會出現時間相關的查詢控件
                "@timestamp": {
                    "type": "date"
                },
                "@version": {
                    "type": "keyword"
                },
                // 這個可以只寫入properies里面的任意一個字段
                "geoip": {
                    "dynamic": true,
                    "properties": {
                        "ip": {
                            "type": "ip"
                        },
                        // 我只是用了這個location
                        "location": {
                            "type": "geo_point"
                        },
                        "latitude": {
                            "type": "half_float"
                        },
                        "longitude": {
                            "type": "half_float"
                        }
                    }
                }
            }
        }
    }
}
遇到的問題 索引創建太復雜怎么辦?

使用logstash內置的模板

添加了時間字段后,創建數據不顯示?

檢查是否是毫秒時間戳

安裝x-pack后,clientsdk向es寫入數據報錯,提示校驗失敗?

需要在鏈接中添加用戶名和密碼

類型和模板不匹配導致錯誤?

寫入類型,一定要和索引模板中定義的一致,不然肯定報錯!

同一個索引,添加多個type報錯?

elasticsearch6的 bug,官方承諾在7進行修復

kibana加入登錄驗證?

安裝x-pack吧

如何保證高可用,無人值守?

使用supervisor

如何清理elasticsearch老數據?

我的方案是:定時腳本來清理7天之前的索引DELETE logstash-xxxx

如何快速執行curl查詢?

在kibana中有一個Dev Tools 可以執行curl,并且看到結果

如何格式化kibana的日期格式?

在kibana菜單的Management->Index Patterns中可以管理

結束

不詳細的地方,可以留言

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28196.html

相關文章

  • ELK結合logback搭建日志中心

    摘要:日志監控和分析在保障業務穩定運行時,起到了很重要的作用。本文搭建的的是一個分布式的日志收集和分析系統。對于隊列上的這些未處理的日志,有不同的幾臺進行接收和分析。再由統一的進行日志界面的展示。如等配置文件可以配置,等日志報表可視化熟練 ELK簡介ELKStack即Elasticsearch + Logstash + Kibana。日志監控和分析在保障業務穩定運行時,起到了很重要的作用。比...

    tracy 評論0 收藏0

發表評論

0條評論

妤鋒シ

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<