0%

ELK日志管理解决方案浅探(Elasticsearch、Logstash、Kibana)

Elasticsearch是一个基于Lucene库的搜索引擎。它提供了一个分布式、支持多租户的全文搜索引擎,具有HTTP Web接口和无模式JSON文档。

ELK(Elasticsearch、Logstash、Kibana)

ElasticSearch

Elasticsearch是一个基于Lucene库的搜索引擎。它提供了一个分布式、支持多租户的全文搜索引擎,具有HTTP Web接口和无模式JSON文档。

特点

分布式的实时文件存储,每个字段都能被索引
分布式的实时分析搜索引擎,不规则查询
高拓展性PB级数量级,可处理结构和非结构化数据

应用场景

全文检索(全字段查询)
模糊查询(搜索)
数据分析(提供分析语法)

es安装

  1. 首先装好java环境以及静态网络配置
  2. 下载好安装包到指定目录下,解压安装
    linux添加一个用户es
    adduser es
    passwd es
  3. 授权es用户给指定的安装目录
    chown -R es:es /usr/elastic_search/es
  4. 用es账户启动elasticSearch
    ./elasticsearch
  5. 本机检验是否启动成功
    curl 127.0.0.1:9200
  6. 其他主机校验成功
    需要修改配置文件elasticsearch.yml
    network.host参数为你的静态ip或者主机名

安装中问题解决

再次启动报错
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
[2]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

解决
vim /etc/security/limits.conf
在end之前添加下面信息

  • hard nofile 65536
  • soft nofile 131072
  • hard nproc 4096
  • soft nproc 2048
    参数说明
    nofile 打开文件的最大数目
    nproc 进程的最大数目
    hard 当前系统生效的设置值
    soft 系统中所能设置的最大值

vim /etc/sysctl.conf
插入下面信息
vm.max_map_count=655360
fs.file-max=655360
参数说明
vm.max_map_count 单个jvm能开启的最大线程数
fs.file-max 系统所有进程一共可以打开的文件数量

让修改生效
sysctl -p

在浏览器访问http://hadoop1:9200/,看到下面消息就成功了
{
“name” : “hR4B3zp”,
“cluster_name” : “elasticsearch”,
“cluster_uuid” : “b-d3OuvoRimcc951UCxdvw”,
“version” : {
“number” : “6.3.1”,
“build_flavor” : “default”,
“build_type” : “tar”,
“build_hash” : “eb782d0”,
“build_date” : “2018-06-29T21:59:26.107521Z”,
“build_snapshot” : false,
“lucene_version” : “7.3.1”,
“minimum_wire_compatibility_version” : “5.6.0”,
“minimum_index_compatibility_version” : “5.0.0”
},
“tagline” : “You Know, for Search”
}

es的集群安装

修改配置文件elasticsearch.yml
vim /elasticsearch.yml

配置参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cluster.name: arnold-application #集群名字,可自定义

node.master: true #设置为主节点

node.data: true #设置为数据节点

node.name: hadoop-1 #节点名字可自定义

path.data: /usr/elk/es_data #es数据路径

path.logs: /usr/elk/es_logs #es日志路径


network.host: hadoop1 #主机名

http.port: 9200 #端口

discovery.zen.ping.unicast.hosts: ["hadoop2", "hadoop3"] #集群通信主机名配置

transport.tcp.port: 9300 #集群通信端口

discovery.zen.minimum_master_nodes: 3 #集群节点最少数目,避免脑裂最好设置半数+1

安装head插件(管控es集群的插件)

  1. 安装nodejs
  2. 下载地址
    https://github.com/mobz/elasticsearch-head
  3. 配置
    https://blog.csdn.net/Mr_Mocha/article/details/89175469
  4. 配置文件添加
    elasticsearch默认不支持第三方插件,head插件在elasticsearch5+版本后被移除elasticsearch,需要配置config/elasticsearch.yml
    文件末尾插入代码:
    #allow origin
    http.cors.enabled: true
    http.cors.allow-origin: “*”

head集群中的status显示状态

green 所有主要分片和复制分片都可用
yellow 所有主要分片可用,但不是所有复制分片都可用
red 不是所有的主要分片可用

集群术语定义

索引:一个用来指向一个或多个分片(shards)的逻辑命名空间
分片(shard):一个最小级别的工作单元,只是保存索引中所有数据的一部分,是一个lucene实例,本身就是一个完成的搜索引擎,我们的文档存储在索引中,可以把分片想象成数据的容器,文档存储在分片中,然后分片分配到集群的节点上
主分片:索引中的每个文档属于一个单独的主分片,所以主分片的数量决定了索引最多能存储多少数据
副分片:复制分片只是主分片的一个副本,可以提供读请求
故障转移:文档索引主要被存储在主分片中,然后复制到对应的副分片上,主副节点可做到相互转换,并且放着数据挂掉之后的数据完整性问题

es存储方式

面向文档
json

数据结构

一个索引库index下,老版本还有多个type,后期版本中就存在一个type,多个document,一个document就是一条数据,有多个field

一些常用命令(可在kibana下的Dev Tools进行相关命令操作)

创建一个文档数据

1
2
3
4
5
6
7
8
9
10
11
PUT {Index}/{type}/{id}
{
}
eg:POST arnold/doc/1
{
"name":"arnold",
"age":18
}
arnold可理解成一个索引数据库
doc为type类型
1 _id 主键

批量插入文档(对象之间不能有\n)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST {Index}/{type}/_bulk
{
"index":{
"_id":1
}
{
数据实体对象
}
"index":{
"_id":2
}
{
数据实体对象
}
}

查询文档

1
GET arnold/doc/1 获取一个文档信息

检索文档的一部分

1
GET arnold/doc/1?_source=name

检索一个索引文档

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
GET arnold/doc/_search
回传信息
{
"took": 5, //检索花费时间
"timed_out": false, //是否超时
"_shards": { //分片
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": { //查询命中
"total": 3, //总数
"max_score": 1, //分值
"hits": [ //命中数据结果集
{
"_index": "arnold",
"_type": "doc",
"_id": "2",
"_score": 1,
"_source": {
"name": "xiaoming",
"age": 20
}
},
{
"_index": "arnold",
"_type": "doc",
"_id": "1",
"_score": 1,
"_source": {
"name": "arnold",
"age": 18
}
},
{
"_index": "arnold",
"_type": "doc",
"_id": "3",
"_score": 1,
"_source": {
"name": "xiaohong",
"age": 26
}
}
]
}
}

全文检索(多字段的模糊查询)

1
GET arnold/doc/_search?q=关键词 

聚合查询(有问题)

1
2
3
4
5
6
7
8
9
10
GET arnold/doc/_search
{
"aggs" :{
"interests_all" :{
"term" :{
"field" :"interests"
}
}
}
}

指定分词器分词

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
POST _analyze
{
"analyzer":"standard",
"text":"hello world"
}
回参
{
"tokens": [
{
"token": "hello",
"start_offset": 0,
"end_offset": 5,
"type": "<ALPHANUM>",
"position": 0
},
{
"token": "world",
"start_offset": 6,
"end_offset": 11,
"type": "<ALPHANUM>",
"position": 1
}
]
}

删除文档

1
DELETE arnold/doc/1

查询所有索引文档

1
GET /_search 

查询指定索引文档

1
GET /arnold/_search

多索引查询

1
GET /arnold,index1,index2/_search

指定字段查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
GET /arnold/_search?q=name:arnold

GET /arnold/_search?q=keyword&df=name&sort=age:asc&from=4&size=10&timeout=10s
q:指定查询语句
df(q):指定相应字段,不指定默认全文检索
sort:排序,升序降序
timeout:指定默认超时时间,默认不超时
from ,size:分页
term:单词查询,多个单词的或查询
phrase:词语查询,短语的先后顺序也是匹配条件,""引起来查询
group:使用()指定匹配规则
布尔操作符:AND(&&),OR(||)NOT(!)
+,-:对应must和must_not
范围查询:区间[TO]闭区间,{TO}开区间
算术符号写法:>,<,=
通配符查询:?,*
正则表达式
模糊查询:~
近似度查询

search(Request Body Search) API

Match Query(字段类查询)

1
2
3
4
5
6
7
8
9
10
Get arnold/_search
{
"profile":true, #显示执行计划
"query":{
"match":{
"name":"xiaohong",
"operator":"and"
}
}
}

Match _phrase(词语查询)

1
2
3
4
5
6
7
8
9
10
Get arnold/_search
{
"profile":true,
"query":{
"match_phrase":{
"name":"xiaohong",
"slop":1 #允许几个词的差异
}
}
}

字符查询,多字段相同关键词查询

1
2
3
4
5
6
7
8
9
Get arnold/_search
{
"query":{
"query_string":{
"fields":["name"],
"query":"xiaohong"
}
}
}

不分词查询

1
2
3
4
5
6
7
8
9
10
Get arnold/_search
{
"query":{
"term":{
"name":{
"value":"xiaohong"
}
}
}
}

范围查询

1
2
3
4
5
6
7
8
9
10
Get arnold/_search
{"query":{
"range":{
"age":{
"gte":10,
"lte":20
}
}
}
}

Bool query

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
filter 只过滤符合条件的文档,不计算相关性得分
must 文档必须符合must中的所有条件,会影响相关性得分
must_not 文档必须不符合must_not中的所有条件
should 文档可以符合should中的条件会影响相关性的得分
Get arnold/_search
{
"query":{
"bool":{
"must":[{}],
"must_not":[{}],
"should":[{}],
"filter":[{}],
}
}
}

Mapping

作用:定义数据库中的表的结构定义,通过mapping来控制索引存储数据的设置
定义index下的字段名
定义字段类型
定义倒排索引相关配置

获取索引mapping

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
不进行配置时,自动创建的mapping
默认Maping GET arnold/_mapping
回传data
{
"arnold": { #索引名称
"mappings": { #mapping设置
"doc": { #type名称
"properties": { #字段属性
"age": {
"type": "long" #字段类型,字符串默认类型
},
"interests": {
"type": "text",
"fields": { #子字段属性设置
"keyword": { #分词类型
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
}
}
}
}
}

elasticSearch原理

输入搜索关键词->关键词分词->正排索引,记录文档id与文档内容,单词的联系->倒排索引,记录单词到文档id的关联关系,包含单词词典(term dictionary,记录所有文档的单词,一般比较大),倒排索引(posting list,记录单词倒排列表的关联信息
其中包含docid文档id,TF,单词频率,记录该文档中出现的次数,用于后续相关性算分,offset,偏移量,记录单词在文档中开始和结束的位置,用于高亮显示等)

分词
将文本转换成一系列的单词(term or token)的过程,也可以叫做文本分析,es中称为analysis

分词机制
character filter 对原始文本进行处理
tokenizer 将原始文本进行分词
token filters 将分词后的关键词进行加工

es自带的分词器
Standard(默认分词器) 支持多语言,按词切分并做小写处理
Simple 按照非字母切分,小写处理
Whitespace 按照空格来切分
Stop 去除语气助词
Keyword 不分词
Pattern 正则分词,默认\w,即非字词符号做分隔符
Language 常见语言分词器
中文分词器
IK分词器(ik_smart,ik_max_word) 中英文单词切分,自定义词库
Jieba python流行分词系统,支持分词和词性标注,支持繁体,自定义,并行分词
Hanlp 一系列的模型与算法组成的java 工具包,普及自然语言处理在生产环境中的应用
THULAC 清华大学中文词法分析工具包 具有中文分词和词性标注功能

相关性算分
指文档与查询语句的相关度,通过倒排索引可以获取与查询语句相匹配的文档列表

影响相关度算分的参数
TF(Term Frequency)**词频,单词在文档中出现的次数,词频越高,相关度越高
**DF(Document Frequency)**文档词频,单词出现的文档数
**IDF(Inverse Document Frequency)
,反转文档词频,1/DF,即单词出现文档数越少,相关度越高
Field-length Norm 文档越短,相关度越高

Logstash

Logstash是一个开源数据收集引擎,具有实时管道功能,主要负责数据清洗(input,filter,output)

主要组件

input 输入
filter 过滤(Grok 匹配需搜集的字段,Date处理日期类型,Geoip 添加地理位置信息 Useragent 提取请求用户信息)
output 输出

安装

  1. 解压安装包到指定的文件夹下
  2. 执行logstash
    ./logstash 相应的配置文件(eg:./test.conf)
    安装input脚本,测试是否安装成功
    1
    2
    3
    4
    5
    6
    input {
    stdin{} //模拟输入
    }
    output {
    stdout {codec=>"rubydebug"} //调试输出
    }

input 插件

stdin 输入插件(管道输入,也可以终端交互输入)
通用配置属性
codec
type string自定义该事件类型可作为收集数据的区别字段,可用于后续判断
tags array自定义事件的tag,可用于后续判断
add_field 类型为hash,为该事件添加字段

file插件

从文件读取数据

1
2
3
4
5
6
7
8
9
10
11
12
13
input {
file{
path =>[文件路径]
exclue => "*.gz" #不读取那些文件
sincedb_path => #记录sincedb文件路径
start_position =>"beginning" #是否从头读取文件
stat_interval => #单位秒,定时检查文件是否更新 默认一秒
type =>"web"
}
}
output {
stdout {codec=>"rubydebug"} //调试输出
}

elasticsearch插件

从es读取数据

1
2
3
4
5
6
7
8
9
10
input {
elasticsearch{
hosts => "192.168.2.131"
index =>"索引名字"
query =>'{"query" :{"match_all":{}}}' //查询语句
}
}
output {
stdout {codec=>"rubydebug"} //调试输出
}

filter插件

可对数据进行丰富的处理,解析数据,删除字段,类型装换等

配置属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
date 日期解析
grok 正则解析
dissect 分隔符解析
mutate 对字段处理,重命名,删除,替换等
json 按照json解析字段内容到指定字段中
geoip 添加地理位置信息
ruby 利用ruby代码动态修改logstash event
input {
stdin{
codec=>"json"
}
}
filter {
date {
match =>["logdate","yyyy HH:mm:ss"]
}
}
output {
stdout {codec=>"rubydebug"} //调试输出
}

output插件

和input插件一样可以从文件读取,从es读取

Kibana

安装

  1. 下载好安装包到指定目录下,解压安装
  2. 修改config下的配合文件让kinbana与elasticSearch关联,修改端口号server.port: 5601,server.host: “localhost”,elasticsearch.url: “http://hadoop1:9200",kibana.index: “.kibana”
  3. 在bin目录下启动kibana,执行./kibana 启动
  4. 在浏览器可访问:主机名或者ip:5601

操作

可在management下面添加索引字段
下面filed可选添加

可在visualize下面生成图表