DevOps元素周期表—2号元素Kibana
Kibana 是一款开源的数据分析和可视化平台,它是 Elastic Stack 成员之一,设计用于和 Elasticsearch 协作。您可以使用 Kibana 对 Elasticsearch 索引中的数据进行搜索、查看、交互操作。您可以很方便的利用图表、表格及地图对数据进行多元化的分析和呈现。
目录
- 引子
- ELK快速安装
- Elasticsearch快速入门
- SpringBoot整合ELK日志中心
ELK是Elastic公司提供的一套完整的日志收集以及展示的解决方案,也就是我们常说的日志中心,其中E代表Elasticsearch,L代表Logstash,K就是本文的中心Kibana。
Elasticsearch在其中担当了数据源的作用,用于对数据快速搜索定位,这也是Github搜索使用的解决方案。
在超大数据规模的情况下,能够将查询条件匹配然后返回,高亮显示,你应该知道Elasticsearch的强大了。
Logstash的作用是日志收集器,可以将不同来源的日志数据进行处理输出。下图是我的Logstash配置文件logstash.conf,配置分为两个核心模块,input和output,input中是logstash开放的端口5000,用于应用将日志提交给logstash,在output中是logstash处理完日志后将日志输出的地方,可以看到是输出到Elasticsearch,至于下面的用户名密码,如果你的Elasticsearch有设置即填,没有设置则忽略。
Kibana的作用是对Elasticsearch中存储的数据进行数据分析和可视化处理。
Kibana主要的作用是对日志进行可视化处理,同样的还有Grafana,不过Grafana可以指定多种数据源,比如Prometheus,Mysql,Elasticsearch等
一. ELK快速安装
需要了解的ELK开放端口
- 5000: Logstash TCP input
- 9200: Elasticsearch HTTP
- 9300: Elasticsearch TCP transport
- 5601: Kibana
-
方式一:
使用docker安装,克隆改仓库https://github.com/deviantony/docker-elk
在目录下执行
docker-compose up
。 -
方式二:
使用同版本的包,此处ELK三个包版本必须相同,以免使用出现问题,我本地都是7.1.0。
我已经将三个同版本的包打包上传好了,公众号回复【ELK】获得网盘下载地址
将包解压后,在各个bin目录下执行相应程序即可。
# ..\elasticsearch-7.1.0\bin .\elasticsearch.bat
# E:\kibana-7.1.0\bin .\kibana.bat
类似这样,先启动elasticsearch。
浏览器访问 localhost:9200,可以看到elasticsearch的启动状态,然后启动kibana,浏览器访问 localhost:5601。
二. Elasticsearch快速入门
Ⅰ. 索引,文档和REST API
1. 文档
- Elasticsearch是面向文档的,文档是所有可搜索数据的最小单位。
- 日志文件中的日志项
- 一部电影的具体信息 / 一张唱片的详细信息
- MP3播放器中的一首歌 / 一篇PDF文档中的具体内容
- 文档会被序列化成JSON格式,保存在ElasticSearch中
- JSON对象由字段组成
- 每个字段都有对应的字段类型(字符串/数值/布尔/日期/二进制/范围类型)
- 每个文档都有一个Unique ID
- 你可以自己指定ID
- 或者通过Elasticsearch自动生成
2. JSON文档
-
一篇文档包含了一系列字段。类似数据库表中一条记录
-
JSON文档,格式灵活,不需要预先定义格式
- 字段的类型可以指定或者通过ElasticSearch自动推算
- 支持数组/支持嵌套
3. 文档的元数据
- 元数据,用于标注文档的相关信息
- _index 文档所属的索引名
- _type 文档所属的类型名
- _id 文档唯一id
- _source 文档的原始Json数据
- _all 整合所有字段内容到该字段,已被废除
- _version 文档的版本信息
- _score 相关性打分
4. 索引
-
Index — 索引是文档的容器,是一类文档的结合
- Index体现了逻辑空间的概念:每个索引都有自己的Mapping定义,用于定义包含的文档的字段名和字段类型
- Shard体现了物理空间的概念:索引中数据分散在Shard上
-
索引的Mapping与Setting
- Mapping定义文档字段的类型
- Setting定义不同的数据分布
-
索引的不同语义
索引(动词)文档到ElasticSearch的索引(名词)中
- 名词:一个ElasticSearch集群中,可以创建很多个不同的索引
- 动词:保存一个文档到ElasticSearch的过程也叫索引(Indexing)
- ES中创建一个倒排索引的过程
- 名词: 一个B树索引,一个倒排索引
5. Type
- 在7.0之前,一个Index可以设置多个Types
- 6.0开始,Type已经被Deprecated。7.0开始,一个索引只能有一个Type—”_doc”
6. 与关系型数据库类比
RDBMS | ElasticSearch |
---|---|
Table | Index |
Row | Document |
Column | Filed |
Schema | Mapping |
SQL | DSL |
- 传统关系型数据库与ElasticSearch的区别
- ElasticSearch — Schemaless / 相关性高 / 高性能全文检索
- RDMS — 事物性 / Join
7. REST API — 很容易被各种语言调用
8. 一些基本的API
- Indices
- 创建Index
- PUT Movies
- 查看所有Index
- _cat/indices
- 创建Index
// 查看指定索引的相关信息 Mapping/Setting的设置
GET index_name
// 查看指定索引的文档总数
GET index_name/_count
// 查看指定索引的前10条文档
POST index_name/_search
// _cat indices API
// 对索引名称进行通配符查询
GET /_cat/indices/kibana*v&s=index
// 查看索引状态为绿的索引
GET /_cat/indices/v&health=green
// 按照文档个数排序
GET /_cat/indices/v&s=docs.count:desc
Ⅱ. 节点,集群,分片和副本
1. 分布式系统的可用性与扩展性
- 高可用性
- 服务可用性 — 允许有节点停止服务
- 数据可用性 — 部分节点丢失,不会丢失数据
- 可扩展性
- 请求量提示 / 数据的不断增长 (将数据分布到所有节点上)
2. 分布式特性
-
ElasticSearch的分布式架构的好处
- 存储的水平扩容
- 提升系统的可用性,部分节点停止服务,整个集群的服务不受影响
-
Elasticsearch的分布式架构
- 不同的集群通过不同的名字来区分,默认名字”elasticsearch”
- 通过配置文件修改,或者在命令行中 -E cluster.name=clustername 进行设定
- 一个集群可以有一个或多个节点
3. 节点
- 节点是一个Elasticsearch的实例
- 本质上就是一个JAVA进程
- 一台机器上可以运行多个Elasticsearch进程,但生产环境一个一机一个
- 每个节点都有名字,通过配置文件,或者启动时通过 -E node.name=nodename进行设定
- 每个节点在启动之后,会分配一个UID,保存在data目录下
4. Master-ekigible nodes 和 Master Node
- 每个节点启动后,默认就是一个Master eligible节点
- 可以设置node.master: false 禁止
- Master-eligible节点可以参与选主流程,成为Master节点
- 当第一个节点启动时,他会将自己选举为Master节点
- 每个节点上都保存了集群的状态,只有Master节点才能修改集群的状态信息
- 集群状态,维护了一个集群中,必要的信息
- 所有的节点信息
- 所有的索引和其相关的Mapping与Setting信息
- 分片的路由信息
- 任意节点都能修改信息会导致数据的不一致性
- 集群状态,维护了一个集群中,必要的信息
5. Data Node & Coordinating Node
- Data Node
- 可以保存数据的节点,叫做Data Node。负责保存分片数据。在数据扩展上起到了至关重要的作用
- Coordinating Node
- 负责接收Client的请求,将请求发到合适的节点,最终把结果汇聚到一起
- 每个节点默认都起到Coordinating Node的职责
6. 其他的节点类型
- Hot & Warm Node
- 不同硬件配置的Data Node,用来实现Hot & Warm架构,降低集群部署的成本
- Machine Learning Node
- 负责跑机器学习的Job,用来做异常检测
- Tribe Node
- Tribe Node连接到不同的Elasticsearch集群,并且支持将这些集群当成一个单独的集群处理
7. 配置节点类型
8. 分片(Primary Shard & Replica Shard)
- 主分片,用以解决数据水平扩展的问题。通过主分片,可以将数据发布到集群内所有节点上
- 一个分片是一个运行的Lucene实例
- 主分片在索引创建时指定,后续不允许修改,除非Reindex
- 副本,用以解决数据高可用的问题。分片是主分片的拷贝
- 副本分片数,可以动态调整
- 增加副本数,还可以在一定程度上提高服务的可用性(读取的吞吐)
9. 分片的设定
- 对于生产环境中分片的设定,需要提前做好容量规划
- 分片数设置过小
- 导致后续无法增加节点实现水品扩展
- 单个分片的数据量太大,导致数据重新分配耗时
- 分片数设置过大,7.0开始,默认主分片设置成1,解决了over- sharding的问题
- 影响搜索结果的相关性打分,影响统计结果的准确性
- 单个节点上过多的分片,会导致资源浪费,同时也会影响性能
- 分片数设置过小
10. 查看集群状态
-
使用REST API
- _cat/nodes
- _cat/shard
-
使用cerebro
- 启动访问localhost:9000
Ⅲ. 文档的基本CRUD与批量操作
1. 文档的CRUD
-
Index (如果ID不存在,创建新的文档,如果存在,删除原有的再创建,版本会增加)
PUT my_index/_doc/1 { "user": "mike", "comment": "hello" }
-
Create
PUT my_index/_create/1 { "user": "mike", "comment": "hello" } POST my_index/_doc(不用指定ID,自动生成) { "user": "mike", "comment": "hello" }
-
Read
GET my_index/_doc/1
-
Update 文档必须存在,更新字段
POST my_index/_update/1 { "user": "mike", "comment": "hello es" }
-
Delete
DELETE my_index/_doc/1
2. Bulk API
支持在一次API调用中,对不同的索引进行操作
- 支持四种类型操作
- Index
- Create
- Update
- Delete
- 可以在URL中指定Index,也可以在请求的Payload中进行
- 操作中单个操作失败,不影响其他操作
- 返回结果包括了每一条操作执行的结果
POST _bulk
{"index": {"_index": "test", "_id": "1"}}
{"field1": "value1"}
{"delete": {"_index": "test", "_id":"2"}}
3. 批量读取 mget
批量操作,可以减少网络连接所产生的开销,提高性能
GET _mget
{
"docs": [
{
"_index": "user",
"_id": 1
},
{
"_index": "comment",
"_id": 1
}
]
}
4. 批量查询 msearch
POST my_index/_msearch
{}
{"query": {"match_all":{}, "from":0, "size":10}}
{}
{"query": {"match_all":{}}
{"index": "twitter2"}
{"query": {"match_all":{}}
Ⅳ. 倒排索引
1. 正排与倒排索引
- 目录页,根据目录页索引,
正排索引
,章名称+页码号 - 根据关键字进行索引到目录页,
倒排索引
在搜索引擎中
- 正排索引 — 文档ID到文档内容和单词的关联
- 倒排索引 — 单词到文档ID的关系
2. 倒排索引的核心组成
- 倒排索引包含两个部分
- 单词词典,记录所有文档的单词,记录单词到倒排列表的关联关系
- 单词词典一般比较大,可以通过B+树或者哈希拉链法实现,以满足高性能的插入与查询
- 倒排列表,记录了单词对应的文档结合,由倒排索引项组成
- 倒排索引项
- 文档ID
- 词频TF
- 位置 — 单词在文档中分词的位置。用于语句搜索
- 偏移 — 记录单词的开始结束位置,实现高亮显示
- 倒排索引项
- 单词词典,记录所有文档的单词,记录单词到倒排列表的关联关系
3. Elasticsearch的倒排索引
- Elasticsearch的JSON文档中的每个字段,都有自己的倒排索引
- 可以指定对某些字段不做索引
- 优点: 节省存储空间
- 缺点:字段无法被搜索
Ⅴ. 通过Analyzer进行分词
1. Analysis与Analyzer
-
Analysis — 文本分析是把全文本转换为一系列单词(term/token)的过程,也叫分词
-
Analysis是通过Analyzer来实现的
- 可使用Elasticsearch内置的分析器/或者按需定制分析器
-
除了在数据写入时转换词条,匹配Query语句时也需要用相同的分析器对查询语句进行分析
2. Analyzer的组成
-
分词器是专门处理分词的组件,Analyzer由三部分组成
- Character Filter,针对原始文本处理,例如去除html / Tokenizer 按照规则切分为单词 / Token Filter 将切分的单词进行加工,小写,删除stopwords,增加同义词
3. Elasticsearch内置分词器
4. 使用_analyzer API
-
直接指定Analyzer进行测试
GET /_analyze { "analyzer": "standard", "text": "Mastering Elasticsearch, elasticsearch in Action" }
-
指定索引字段进行测试
POST books/_analyze { "field": "title", "text": "Mastering Elasticsearch" }
-
自定义分词进行测试
POST /_analyze
{
"tokenizer": "standard",
"filter": ["lowercase"],
"text": "Mastering Elasticsearch"
}
5. 中文分词
-
中文句子,切分成一个一个词,而不是字
-
英文中,单词有自然空格分隔
-
一句中文,不同上下文有不同理解
- 这个苹果,不大好吃 / 这个苹果,不大,好吃!
-
安装ICU Analyzer
在elasticsearch的bin目录下执行
elasticsearch-plugin install analysis-icu
提供了Unicode的支持,更好的支持亚洲语言
6. 更多好用的中文分词器
- LK
- 支持自定义词库,支持热更新分词字典
- THULAC
- THU Lexuacal Analyzer for Chinese,清华大学自然语言处理和社会人文计算实验室的一套中文分词器
Ⅵ. Search API概览
1. Search API
- URI Search
- 在URL中使用查询参数
- Request Body Search
- 使用Elasticsearch提供的,基于JSON格式的更加完备的Query Domain Specific Language(DSL)
2. 指定查询的索引
- /_search 集群上所有的索引
- /index1/_search 索引index1
- /index1,index2/_search 索引index1和2
- /index*/_search 查询index开头的索引
3. Request Body
4. 搜索Response
Ⅶ. URI Search
1. 通过URI query实现搜索
GET /movies/_search?q=2012&df=title&sort=year:desc&from=0&size=10&timeout=1s
{
"profile": true
}
- q 指定查询语句,使用Query String Syntax
- df 默认字段,不指定时,会对所有字段进行查询
- sort 排序 / from和size用于分页
- profile 可以查看查询是如何被执行的
2. Query String Syntax
-
指定字段 v.s 范查询
-
q=title:2012 / q=2012
查询title存在2012的,查询存在2012的
-
-
Term v.s Phrase
- Beautiful Mind 等效于Beautiful OR Mind
- “Beautiful Mind”,等效于Beautiful AND Mind。Phrase查询,要求前后顺序一致
-
分组与引号
- title:(Beautiful AND Mind) —> title:Beautiful title:Mind
- title=”Beautiful Mind” —> title:Beautiful Mind
-
布尔操作
- AND / OR / NOT 或者 && / || / !
- 必须大写
- title:(matrix NOT reloaded)
- AND / OR / NOT 或者 && / || / !
-
分组
-
+
表示must -
-
表示must_not - title:(+matrix -reloaded)
-
-
通配符查询(不建议使用,占用内存大,查询效率低)
- ? 代表1个字符,*代表0或者多个
- title:mi?d
- title:be*
- ? 代表1个字符,*代表0或者多个
-
正则表达
- title:[bt]oy 匹配boy / toy
-
模糊匹配与近似匹配
- title:befutifl~1 允许输入错一个
- title:”lord rings”~2 可以不用相邻,挨着两个
Ⅷ. Request Body Search与Query DSL
1. Request Body Search
-
将查询语句通过HTTP Request Body发送给Elasticsearch
-
Query DSL
POST /movies,404_idx/_search?ignore_unavailable=true { "profile": true, "query": { "match_all": {} } }
2. 使用查询表达式 Match
GET /comments/_doc/_search
{
"query": {
"match": {
"comment": "Last Christmas"
}
}
}
GET /comments/_doc/_search
{
"query": {
"match": {
"comment": {
"query":"Last Christmas",
"operator": "AND"
}
}
}
}
3. Query String Query
类似URI Query
POST users/_search
{
"query": {
"query_string": {
"default_field": "name",
"query": "Ruan AND Ming"
}
}
}
三. SpringBoot整合ELK日志中心
SpringBoot整合ELK的核心在于将日志发送给logstash的开放端口,常用的方案就是使用logstash提供好的日志上传包。
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>5.1</version>
</dependency>
添加该依赖,该依赖提供了一个appender类LogstashTcpSocketAppender,是logback日志框架的上报日志需要的类的实现,在logback.xml中添加相应的appender规则即可,指定输出到logstash端口。
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml" />
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>127.0.0.1:5000</destination>
<!-- 上述端口为elk-docker默认 -->
<!-- 日志输出编码 -->
<encoder charset="UTF-8"
class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<timeZone>UTC</timeZone>
</timestamp>
<pattern>
<pattern>
{
"logLevel": "%level",
"serviceName": "${springAppName:-}",
"pid": "${PID:-}",
"thread": "%thread",
"class": "%logger{40}",
"rest": "%message"
}
</pattern>
</pattern>
</providers>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="LOGSTASH" />
<appender-ref ref="CONSOLE" />
</root>
</configuration>
记得将logstash的配置文件也进行修改。
input {
tcp {
port => 5000
codec => json_lines # 上传使用json_lines插件格式化
}
}
output {
elasticsearch {
hosts => "elasticsearch:9200"
}
}
启动ELK三个应用,然后启动你的SpringBoot应用,就可以在索引管理中看到应用的日志索引了。
然后在管理中创建索引模式,将你的应用索引添加进去,就可以在仪表盘中对日志进行搜索服务了。