Elasticsearch目前的发展可谓如日中天,DBEngine上在搜索引擎领域位列第一,作为后来者热度远高于排第二、三的Splunk和Solr。Elasticsearch的创造者叫Shay Banon,最初是因为Lucence的接口使用困难,开发了一个库Compass,让Lucence更好用,2010年Shay Banon对Compass进行重写,把它变成一个高性能的、分布式的服务端软件,取名叫Elasticsearch,并在github开源。这背后还有一个温情的故事,据说起因是为了给新婚老婆写一个菜谱搜索应用,但是最后菜谱应用没有写出来,倒是造就了一个伟大的软件。
Elasticsearch发展非常快,2010年2月发布第一个版本,2012年成立Elastic公司,2014年开始商业化,2018年纽交所上市,在全球股市低迷的背景下上市当天仍大涨94%,创造了开源软件的传奇。而Elastic公司非常的厚道,坚持开源路线,从6.3版本开始将其收费部分x-pack也"开源",x-pack的基础功能终身免费,不需要注册,其中就包括安全方面必须的HTTPS,权限控制等。
今天开始我想通过一系列文章来探索和学习一下ES,第一篇介绍一下ES的基本概念,搭建单节点的ES,通过图形客户端去探索ES的数据结构和操作,通过监控了解ES运行状态,建立对ES总体上的一个认识。
ES简介
ES是基于Apache Lucence的一个开源的,高性能的分布式搜索引擎,Java语言开发,对外提供RESTful接口,使用方便。
ES从6.3版本开始内置支持SQL,当然只支持查询操作,从而降低了学习其特有query DSL的成本,更是让上层基于SQL的应用可以无缝和ES对接。虽然ES越来越像一个数据库,但是它们之间还是有区别的,最显著的一个区别是,ES添加数据不是立刻刷新索引的,有一个刷新间隔,默认1s,所以不会立刻查询到,这就是所谓的近实时,ES强在检索和分析。所以ES和关系数据库的区别像是OLAP和OLTP的区别,适用于不同场景。
ES主要的应用场景,一个是作为应用的前端检索缓存,提高海量数据的检索效率和做一些聚合检索,先从ES检索,然后再从后端存储检索。第二个是日志和监控,以ES为中心,Elastic公司发展起一个生态圈,之前叫ELK,也就是Elasticsearch、Logstash和Kibana,后来加入Beats,名字改成了Elastic Stack。以Kibana为入口,发展到上层的各种分析和可视化应用,包括热门的机器学习。
先理解ES的一些基本概念,可以和关系数据库做一个类比:
- index:类似关系数据库的表,但是index不需要预先定义schema。
- document:类似关系数据库的记录,json格式。
- mapping:也就是类似关系数据的schema了,可以显式定义,也可以添加document时ES自动识别创建。可以指定mapping为严格模式,这样添加数据库就必须严格符合mapping中定义的字段。
- type:从7.0开始删除了,其实就是mapping的名字,一个index下只有一个type,有点鸡肋。虽然删除了,但是其实内部默认还是有一个type,名字固定是_doc。
- index template:创建index时自动对index做一些设置,例如index的主分片个数,复制分片个数,mapping字段的类型等等。
- ilm:也就是index lifecycle management,可以对数据分为Hot,Warm,Cold,Delete四个阶段,可以相应的定义不同的策略。
ES安装
最简单的方式就是用docker来运行。
官方参考文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html
我使用的最新的7.6.2版本,单节点运行时需要指定discovery.type=single-node,以前老的版本是不需要的。
1 | docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.6.2 |
为了后续配置方面可以把配置文件放到host机器上,然后mount到容器。
1 | docker run -d --name es -p 9200:9200 -p 9300:9300 -v $(pwd)/elasticsearch.docker.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /etc/localtime:/etc/localtime elasticsearch:7.6.2 |
这里加入-v /etc/localtime:/etc/localtime是为了将容器的时间和host保持一致,后面再讲为什么。
配置文件elasticsearch.docker.yml如下。
1 | cluster.name: "es_cluster" |
从上面命令看到ES暴露2个端口,9200用于提供RESTful接口,9300端口提供TCP的内部协议通信,9300对外的访问在7.0标识为Deprecated,只有集群内部之间仍通过9300通信。
通过curl就可以很方便的操作ES。
1 | curl http://127.0.0.1:9200 |
返回如下内容表示ES启动正常。
1 | { |
图形客户端
推荐一个图形客户端dejavu,使用reactjs开发,相比常用的elasticsearch-head插件更加现代化一些,功能也丰富一些,对于探索ES非常有帮助。
为了解决跨站访问问题,需要修改ES的配置如下,其中http.cors.allow-origin也可以指定为具体的地址,也就是dejavu的地址,例如http://localhost:1358。
1 | cluster.name: "es_cluster" |
然后重启一下ES。
dejavu也支持docker运行。
1 | docker run -d --name=es-ui -p 1358:1358 -d appbaseio/dejavu |
访问http://localhost:1358即可使用。
输入ES地址和index名(*表示所有)就可以开始读取和操作document和mapping。目前不支持index tempalte,ILM策略等。
需要注意如果ES是空的是连接不上的,必须至少有一个index。
监控
ES最常用的场景是用于监控和分析,对ES自身的监控自然也不在话下。ES本生提供了丰富的监控指标,结合Kibana可以将他们可视化。通过监控可以让我们更了解ES内部的细节。
Kibana安装
官方文档:https://www.elastic.co/guide/en/kibana/7.6/docker.html
同样使用docker运行:
1 | docker run -d --link es:elasticsearch -p 5601:5601 -v $(pwd)/kibana.docker.yml:/usr/share/kibana/config/kibana.yml -v /etc/localtime:/etc/localtime --name kibana kibana:7.6.2 |
–link可以在kibana容器中通过http://elasticsearch:9200访问ES。
配置文件kibana.docker.yml如下。
1 | server.name: kibana |
kibana中对ES的监控是在Stack Monitoring功能中,其中也包含对Kibana,Logstash及Beats的监控。
数据采集有两种方式,通过Metricbeat采集或内部采集,官方推荐前者:
时区问题
先说遇到的一个问题,从Kibana查询最近一个小时的数据会发现查询不到,但是采集是正常的,也可以看到监控的index已经有数据了。
问题原因是访问kibana的机器是用的本地时间,而ES、Kibana运行的机器是UTC时间。需要把ES运行的机器改成本地时间。ES是运行在容器中的,问题就变成了怎么修改容器的时区。答案就是先改Host的,然后让容器和Host保持一致。我是用的centos,以下是centos的修改方法。
1 | sudo timedatectl set-timezone Asia/Shanghai |
ES的容器基础镜像也是centos,所以运行容器的时候加上-v /etc/localtime:/etc/localtime即可。
通过内部采集
官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.6/monitoring-production.html
先来看第一种方式,非常简单,通过kibana图形界面就可以操作。
点击Turn on monitoring就可以了,Kibana会帮我们将ES的xpack.monitoring.collection.enabled设为true,你也可以通过Kibana的Dev Tools中的Console自己修改,是一样的效果:
1 | PUT _cluster/settings |
另外有几个参数也很重要,它们默认是true的,如果它们任意一个为false,那么也无法监控。
-
xpack.monitoring.enabled:决定是否启用监控
-
xpack.monitoring.elasticsearch.collection.enabled:决定是否采集elasticsearch
内部采集是Kibana默认通过local
exporter保存在被监控ES集群中,index名为.monitoring-*,例如对kibana的采集数据的index形如.monitorning-kibana-7-2020.04.13,每天一个。
通过Metricbeat采集
官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.6/configuring-metricbeat.html
这是官方推荐的方式,两种方式二选一。
首先同样需要ES的xpack.monitoring.collection.enabled设置为true,为了禁用内部采集将xpack.monitoring.elasticsearch.collection.enabled设置为false。
然后安装Metricbeat,官方文档:https://www.elastic.co/guide/en/beats/metricbeat/7.6/running-on-docker.html
同样用Docker运行,分两步,第一步是setup过程,主要是初始化一些数据。
1 | docker run --rm --link kibana:kibana --link es:elasticsearch \ |
第二步启动Metricbeat。
1 | docker run -d --link es:elasticsearch \ |
这里可能会遇到一个问题。
1 | Exiting: error loading config file: config file ("metricbeat.yml") must be owned by the user identifier (uid=0) or root |
或者:
1 | Exiting: error loading config file: config file ("metricbeat.yml") can only be writable by the owner but the permissions are "-rw-rw-r--" (to fix the permissions use: 'chmod go-w /usr/share/metricbeat/metricbeat.yml') |
因为在host中我是用的non-root用户uid1000,到容器里面的uid1000是metricbeat用户,但是beats要求配置文件必须是root拥有并且权限为0644。解决办法是把metricbeat.docker.yml的owner改成root。
1 | sudo chown root metricbeat.docker.yml |
配置文件metricbeat.docker.yml如下。
1 | metricbeat.config: |
用dejavu可以查看到metricbeat写入的index形如.monitoring-es-7-mb-2020.04.13,也是每天一个。
回到Kibana的Stack Monitoring可以查看到ES和Kibana的监控了,其中ES是通过Metricbeat采集的数据,而Kibana是通过第一种方式内部采集的。