转载

    ELK 从入门到实战(非常详细!)

    第一章:ELK 基本概念与环境搭建

    一、Elastic Stack 简介

    如果你没有听说过 Elastic Stack那你一定听说过 ELK 那么 ELK 到底是什么呢?ELK 是 Elasticsearch、Logstash、Kibana 三款软件的简称。在发展的过程中,又有新成员 Beats 的加入,所以就形成了 Elastic Stack 这个名称。所以说,ELK 是旧的称呼,Elastic Stack 是新的名字。 下图是 ELK 技术栈:

    下图是 Elastic Stack 技术栈:

    以下是 Elastic Stack 技术栈中各个技术的简单介绍:

    Elasticsearch 基于 Java 语言,是个开源分布式搜索引擎。特点:分布式,零配置,自动发现,索引自动分片,索引副本机制,RESTful 风格接口,多数据源,自动搜索负载等。

    Logstash 基于 Java 语言,是一个开源的用于 收集、分析和存储日志 的工具。

    Kibana 基于 nodejs 技术,也是一个开源和免费的工具。Kibana 可以为 Logstash 和 Elasticsearch 的日志分析 提供友好的 Web 界面,可以汇总、分析和搜索重要数据日志。

    Beats 是 elastic 公司开源的一款采集系统监控数据的代理 agent,是在被监控服务器上以客户端形式运行的数据收集器的统称。该技术可以直接把数据发送给 Elasticsearch 或者通过 Logstash 发送给 Elasticsearch 。然后进行后续的数据分析活动。 Beats 的组成如下:

    【Packetbeat】 是一个网络数据包分析器,用于监控、收集网络流量信息,Packetbeat 嗅探服务器之间的流量,解析应用层协议,并关联到消息的处理,其支持 ICMP (v4 and v6)、DNS、HTTP、Mysql、PostgreSQL、Redis、MongoDB、Memcache 等协议

    【Filebeat】 用于监控、收集服务器日志文件,其已取代 logstash forwarder;

    【Metricbeat】 可定期获取外部系统的监控指标信息,其可以监控、收集 Apache、HAProxy、MongoDB、MySQL、Nginx、PostgreSQL、Redis、System、Zookeeper 等服务;

    TIPS: Beats 和 Logstash 其实都可以进行数据的采集, 但是目前主流的是使用 Beats 进行数据采集。 然后使用 Logstash 进行数据的分割处理等,早期没有 Beats 的时候,使用的就是 Logstash 进行数据的采集。

    二、Elasticsearch 简介

    **更多详细介绍请参考 ES 链接

    官网链接: https://www.elastic.co/
    ES 链接: https://www.elastic.co/cn/elasticsearch/
    下载链接: https://www.elastic.co/cn/downloads/

    ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    我们建立一个网站或应用程序,并要添加搜索功能,但是想要完成搜索工作的创建是非常困难的。我们希望搜索解决方案要运行速度快,我们希望能有一个零配置和一个完全免费的搜索模式,我们希望能够简单地使用JSON通过HTTP来索引数据,我们希望我们的搜索服务器始终可用,我们希望能够从一台开始并扩展到数百台,我们要实时搜索,我们要简单的多租户,我们希望建立一个云的解决方案。因此我们利用Elasticsearch来解决所有这些问题及可能出现的更多其它问题。

    ElasticSearch是Elastic Stack的核心,同时Elasticsearch 是一个分布式、RESTful风格的搜索和数据分析引擎,能够解决不断涌现出的各种用例。作为Elastic Stack的核心,它集中存储您的数据,帮助您发现意料之中以及意料之外的情况。

    Elasticsearch的发展是非常快速的,所以在ES5.0之前,ELK的各个版本都不统一,出现了版本号混乱的状态,所以从5.0开始,所有Elastic Stack中的项目全部统一版本号。目前最新版本是6.5.4,我们将基于这一版本进行学习。

    http://47.113.85.135:8888/images/elk/elk008.png

    TIPS: Elasticsearch 简称 ES 或者 es

    三、Elasticsearch 环境搭建

    1、Elasticsearch 下载

    官网链接: https://www.elastic.co/
    ES 链接: https://www.elastic.co/cn/elasticsearch/
    下载链接: https://www.elastic.co/cn/downloads/

    点击上面的 下载链接 ,然后就跳转到了下载页面。如下图:

    然后点击 Elasticsearch 底部的下载, 去到 Elasticsearch 的下载页面。如下图:

    最后选择对应版本的数据下载即可。 建议: 建议使用 Linux 来进行安装 ElasticSearch ,所以下面的教程都是基于 Linux 进行安装的。

    2、Linux 安装 Elasticsearch

    具体的安装过程请按照以下命令顺序进行操作。命令如下:

    # 此时需要 root 用户的身份
    useradd elsearch         # 添加 elsearch 用户,用户名随便取
    passwd elsearch          # 给 elsearch 用户设置密码,自己设置就好了
    cd /
    mkdir Cluster-Software   # 创建一个目录,名字随意
    cd Cluster-Software
    mkdir es                 # 创建 es 目录,名字随意
    chown elsearch:elsearch Cluster-Software -R    # 更改目录的属主为 elsearch
    
    su - elsearch    # 切换到 elsearch 用户【以下操作都使用 elsearch 用户,如果要切换 root 用户,会进行提示】
    # 下载 es 安装包
    wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.5.4.tar.gz
    # 解压 es 安装包
    tar -zxcf elasticsearch-6.5.4.tar.gz -C /Cluster-Software/es
    # 进入到 config 目录进行配置
    cd /Cluster-Software/es/elasticsearch-6.5.4/config
    

    当进入到配置目录中之后,按照提示进行相关的配置编写即可。具体如下:

    # 打开 elasticsearch.yml 配置文件
    vim elasticsearch.yml
    
    # 添加一行配置,用于设置 ip 地址,任意网络均可访问。添加完后保存退出即可
    network.host: 0.0.0.0
    
    # 注意:建议在文件末尾添加自己的配置【只是建议】
    

    在 Elasticsearch 中如果,network.host 不是 localhost 或者 127.0.0.1 的话,就会认为是生产环境,会对环境的要求比较高, 我们的测试环境不一定能够满足,一般情况下 需要修改两处配置。 具体如下:

    # 第一处修改:修改 jvm 启动参数。
    vim jvm.options            # 该配置文件和 elasticsearch.yml 配置文件同一目录
    
    # 然后根据自己机器情况修改,然后保存退出
    -Xms128m 
    -Xmx128m
    
    
    # 第二处修改:系统级别配置。【注意啦】此时需要使用 root 用户进行登录
    su root
    vim /etc/sysctl.conf
    
    # 增加如下一行配置,一个进程在 VMAs(虚拟内存区域)创建内存映射最大数量。然后保存退出
    vm.max_map_count=655360
    
    # 检查配置是否生效
    sysctl -p
    
    # 【启动 ES】接下来就可以启动 Elasticsearch 了。【注意】此时需要切换到 elsearch 用户来启动 Elasticsearch
    su elsearch
    cd /Cluster-Software/es/elasticsearch-6.5.4/bin/
    
    # 以下三种启动方式,任选一种即可
    ./elasticsearch            # 前台启动
    ./elasticsearch -d         # 后台启动,可以直接作为一个服务
    ./elasticsearch &          # 后台启动,可以直接作为一个服务
    
    # 注意:这里默认你是启动成功了,一般都是不成功的。具体错误示例请参考下一小结:【3、可能遇到的问题】
    
    # 复制一个会话,【检查是否启动成功】如果使用以下命令能够查看结果,那说明启动成功了
    curl -X GET http://localhost:9200
    
    # 返回结果如下:
    {
      "name" : "YzgZ-pC",
      "cluster_name" : "elasticsearch",
      "cluster_uuid" : "_na_",
      "version" : {
        "number" : "6.5.4",
        "build_flavor" : "default",
        "build_type" : "tar",
        "build_hash" : "d2ef93d",
        "build_date" : "2018-12-17T21:17:40.758843Z",
        "build_snapshot" : false,
        "lucene_version" : "7.5.0",
        "minimum_wire_compatibility_version" : "5.6.0",
        "minimum_index_compatibility_version" : "5.0.0"
      },
      "tagline" : "You Know, for Search"
    }
    
    # 如果能看到上述结果,但在浏览器中访问虚拟机中的 es 出现连接失败,那么说明虚拟机中的 Linux 的防火墙没有关闭
    systemctl status firewalld      # 查看防火墙状态
    systemctl stop firewalld        # 关闭防火墙
    
    # 关闭防火墙之后即可在浏览器中访问了。
    # 访问地址:虚拟机IP + 9200       访问举例:192.168.111.128:9200
    
    
    # 那么如何停止 Elasticsearch 呢?
    jps                        # 查看 Elasticsearch 进程
    kill xxx                   # xxx 表示 Elasticsearch 的进程号
    ps -aux | grep elastic     # 查看 Elasticsearch 进程
    kill xxx
    kill -9 xxx                # 如果进程无法杀死,请带上 -9 这个参数【超暴力的】
    

    3、可能遇到的问题

    如果你在启动的时候遇到过问题,那么请参考下面的错误分析~

    错误情况一

    # 如果出现下面的错误信息,就说明你没有切换成 elsearch 用户,因为不能使用 root 操作 es
    
    java.lang.RuntimeException: can not run elasticsearch as root
        at org.elasticsearch.bootstrap.Bootstrap.initializeNatives(Bootstrap.java:111)
        at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:178)
        at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:393)
        at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:170)
        ......
    For complete error details, refer to the log at /soft/elsearch/logs/elasticsearch.log
    [root@e588039bc613 bin]# 2020-09-22 02:59:39,537121 UTC [536] ERROR CLogger.cc@310 Cannot log to named pipe /tmp/elasticsearch-5834501324803693929/controller_log_381 as it could not be opened for writing
    2020-09-22 02:59:39,537263 UTC [536] INFO  Main.cc@103 Parent process died - ML controller exiting
    
    
    # 【解决方法:】切换到 elsearch 用户,再次启动 Elasticsearch
    su - elsearch
    cd /Cluster-Software/es/elasticsearch-6.5.4/bin/
    ./elasticsearch
    

    错误情况二

    # 如果你遇到的是如下错误情况:
    
    [1]:max file descriptors [4096] for elasticsearch process is too low, increase to at least[65536]
    
    
    # 【解决方法:】切换到 root 用户,编辑 limits.conf 添加如下内容
    vi /etc/security/limits.conf
    
    # 在 【limits.conf】 配置文件添加如下内容。【注意】一定要把 * 号也带上】
    *  soft  nofile  65536
    *  hard  nofile  131072
    *  soft  nproc   2048
    *  hard  nproc   4096
    
    # 然后保存退出,切换回 elsearch 用户来启动 Elasticsearch 即可
    

    错误情况三

    # 如果你遇到的是如下错误情况,这表示最大线程数设置的太低了,需要改成 4096
    
    [2]: max number of threads [1024] for user [elsearch] is too low, increase to at least [4096]
    
    
    # 【解决方法:】切换到 root 用户,进入 limits.d 目录下修改 90-nproc.conf 配置文件
     vi /etc/security/limits.d/90-nproc.conf  
    
    # 修改如下内容
    *  soft  nproc  1024
    
    # 修改为
    *  soft  nproc  4096   # 修改完成之后保存退出即可
    
    
    # 【注意:】如果没有 90-nproc.conf 这个配置文件,那就新建 90-nproc.conf 文件
    touch 90-nproc.conf
    vim 90-nproc.conf
    *  soft  nproc  4096    # 添加这条内容即可,然后保存退出
    

    错误情况四

    # 如果你遇到的是如下错误情况,这表示Centos6 不支持 SecComp,而 ES5.2.0 默认 bootstrap.system_call_filter 为 true
    
    [3]: system call filters failed to install; check the logs and fix your configuration
    or disable system call filters at your own risk
    
    
    # 【解决方法】修改 elasticsearch.yml 配置文件
    vim elasticsearch.yml
    
    # 添加如下两行配置,然后保存退出,重新启动即可
    bootstrap.system_call_filter: false
    bootstrap.memory_lock: false
    

    错误情况五

    # 我们通过排查,发现是因为 /soft/elsearch/config/elasticsearch.keystore 存在问题
    # 也就是说该文件还是所属于 root 用户,而我们使用 elsearch 用户无法操作,所以需要把它变成 elsearch
    
    [elsearch@e588039bc613 bin]$ Exception in thread "main" org.elasticsearch.bootstrap.BootstrapException: java.nio.file.AccessDeniedException: /soft/elsearch/config/elasticsearch.keystore
    Likely root cause: java.nio.file.AccessDeniedException: /soft/elsearch/config/elasticsearch.keystore
        at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:90)
        at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
        ......
    
    
    # 【解决方法】
    chown elsearch:elsearch elasticsearch.keystore
    

    错误情况六

    # 如果你遇到的是如下错误情况:
    
    [1]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured
    ERROR: Elasticsearch did not exit normally - check the logs at /soft/elsearch/logs/elasticsearch.log
    
    
    # 【解决方法】继续修改 elasticsearch.yaml 配置文件。具体修改如下:
    node.name: node-1
    cluster.initial_master_nodes: ["node-1"]
    # 然后保存退出重新启动即可
    

    4、可视化插件的安装

    由于 ES 官方没有给 ES 提供可视化管理工具,仅仅是提供了后台的服务,elasticsearch-head 是一个为 ES 开发的一个页面客户端工具, 其源码托管于Github,地址为 https://github.com/mobz/elasticsearch-head

    # 该 head 插件提供了以下安装方式:
    
    1、源码安装,通过 npm run start 启动(不推荐)
    2、通过 docker 安装(推荐)
    3、通过 chrome 插件安装(推荐)
    4、通过 ES 的 plugin 方式安装(不推荐)
    
    # 建议使用 Chrome 浏览器安装此插件,具体安装请自行搜索解决。【搜索关键词】elasticsearch-head 插件安装
    
    # 通过 Docker 方式安装
    
    # 拉取镜像
    docker pull mobz/elasticsearch-head:5
    
    # 创建容器
    docker create --name elasticsearch-head -p 9100:9100 mobz/elasticsearch-head:5
    
    # 启动容器
    docker start elasticsearch-head
    
    # 注意:由于前后端分离开发,所以会存在跨域问题,需要在服务端做 CORS 的配置,如下:
    
    vim elasticsearch.yml         # 编辑此配置文件,然后添加如下两行配置即可
    http.cors.enabled: true
    http.cors.allow-origin: "*"
    
    # 通过 Chrome 插件的方式安装不存在该问题
    

    四、Elasticsearch 基础概念

    # Elasticsearch 中的术语和关系型数据库中的术语对应关系
    
    # Elasticsearch                关系型数据库
          索引       ------->         数据库
          类型       ------->         表
          文档       ------->         行/记录
          字段       ------->         列
    
    # 具体对应关系如下图:
    

    http://47.113.85.135:8888/images/elk/elk009.png

    1、索引

    # 索引
    索引(index)是Elasticsearch对逻辑数据的逻辑存储,所以它可以分为更小的部分。
    可以把索引看成关系型数据库的表,索引的结构是为快速有效的全文索引准备的,特别是它不存储原始值。
    Elasticsearch可以把索引存放在一台机器或者分散在多台服务器上,每个索引有一或多个分片(shard),每个分片可以有多个副本(replica)。
    

    2、文档

    # 文档
    存储在Elasticsearch中的主要实体叫文档(document)。用关系型数据库来类比的话,一个文档相当于数据库表中的一行记录。
    Elasticsearch和MongoDB中的文档类似,都可以有不同的结构,但Elasticsearch的文档中,相同字段必须有相同类型。
    文档由多个字段组成,每个字段可能多次出现在一个文档里,这样的字段叫多值字段(multivalued)。
    每个字段的类型,可以是文本、数值、日期等。字段类型也可以是复杂类型,一个字段包含其他子文档或者数组。
    

    3、映射

    # 映射
    所有文档写进索引之前都会先进行分析,如何将输入的文本分割为词条、
    哪些词条又会被过滤,这种行为叫做映射(mapping)。一般由用户自己定义规则。
    

    4、文档类型

    # 文档类型
    在Elasticsearch中,一个索引对象可以存储很多不同用途的对象。例如,一个博客应用程序可以保存文章和评论。
    每个文档可以有不同的结构。
    不同的文档类型不能为相同的属性设置不同的类型。例如,在同一索引中的所有文档类型中,一个叫title的字段必须具有相同的类型。
    
    
    

    第二章:Restful API 的使用

    TIPS: 在 Elasticsearch 中,提供了功能丰富的 RESTful API 的操作,包括基本的 CRUD、创建索引、删除索引等操作。【建议】 先安装好 Postman 接口测试工具,后面大部分都会使用这个工具进行测试。

    一、索引的创建和删除

    1、创建非结构化索引

    在 Lucene 中,创建索引是需要定义字段名称以及字段的类型的,在 Elasticsearch 中提供了非结构化的索引,就是不需要创建索引结构,即可写入数据到索引中。 实际上在 Elasticsearch 底层会进行结构化操作,只不过此操作对用户是透明的。

    2、创建空索引

    # 创建索引:发送一个 PUT 请求:http://192.168.111.128:9200/cmd
    # 注意:json 格式的注释使用双斜杠 // ,而不是 # 号,使用 # 号发送数据会报错
    # 发送请求时【一定记得】把注释给去掉
    {
        "settings": {
            "index": {
                "number_of_shards": "2",   // 分片数
                "number_of_replicas": "0"  // 副本数
            }
        }
    }
    

    创建索引完成之后,我们可以去浏览器中使用 elasticsearch-head 插件进行查看。 如下图:

    3、删除索引

    # 删除索引:发送一个 DELETE 请求:http://192.168.111.128:9200/cmd
    
    {
        "acknowledged": true
    }
    

    二、插入数据

    URL规则: POST /{索引}/{类型}/{id}

    # 插入数据:发送一个 POST 请求:http://192.168.111.128:9200/haoke/user/1001
    # haoke 是索引名称,user 是类型,1001 是这条数据的 id ,和下面 json 格式中的 id 没有啥关系
    
    {
        "id":1001,       // 和路径上的 id 没有什么关系
        "name":"张三",
        "age":20,
        "sex":"男"
    }
    

    具体操作如下图(在发送 JSON 数据时记得把注释给去掉):

    # 上述操作的返回结果如下:
    
    {
        "_index": "haoke",        // 索引
        "_type": "user",          // 类型
        "_id": "1001",            // 唯一ID
        "_version": 1,            // 版本信息
        "result": "created",      // 表示插入数据
        "_shards": {
            "total": 1,           // 插入数据总条数
            "successful": 1,      // 插入成功总条数
            "failed": 0           // 插入失败总条数
        },
        "_seq_no": 0,
        "_primary_term": 1
    }
    

    说明: 非结构化的索引,不需要事先创建,直接插入数据会默认创建索引。 不指定 id 插入数据如下:

    # 不指定 ID 插入数据:http://192.168.111.128:9200/haoke/user
    
    {
        "id":1002,
        "name":"李四",
        "age":21,
        "sex":"男"
    }
    

    有 ID 插入和无 ID 插入对比如下:

    三、更新数据

    在 Elasticsearch 中,文档数据是不能被修改的,但是可以通过覆盖的方式进行更新。操作如下:

    # 更新数据:发送一个 PUT 请求:http://192.168.111.128:9200/haoke/user/1001
    # 注意:更新数据一定要带上 ID 
    
    {
        "id":1001,
        "name":"张三",
        "age":21,
        "sex":"女"
    }
    
    # 更新数据之后返回结果如下:
    
    {
        "_index": "haoke",
        "_type": "user",
        "_id": "1001",
        "_version": 2,          // 更新之后,版本+1
        "result": "updated",    // 表示更新数据
        "_shards": {
            "total": 1,
            "successful": 1,
            "failed": 0
        },
        "_seq_no": 1,
        "_primary_term": 1
    }
    

    如果更新的时候少一个字段,会发生什么变化呢?如下:

    {
        "id":1001,
        "name":"张三",
        "age":21
    }
    
    # 更新数据之后返回结果如下:
    
    {
        "_index": "haoke",
        "_type": "user",
        "_id": "1001",
        "_version": 3,             // 更新之后,版本再+1
        "result": "updated",       // 表示更新
        "_shards": {
            "total": 1,
            "successful": 1,
            "failed": 0
        },
        "_seq_no": 2,
        "_primary_term": 1
    }
    

    更新之后发现数据被覆盖,且丢失了一个字段。如下图:

    # 可以看到数据已经被覆盖了。问题来了,可以局部更新吗?
    答案是可以的。但是前面不是说,文档数据不能更新吗? 
    其实是这样的:在 Elasticsearch 内部,依然会查询到这个文档数据,然后进行覆盖操作。其具体的步骤如下:
    
    1、从旧文档中检索 JSON 数据
    2、然后修改它
    3、删除旧文档
    4、索引新文档
    
    # 接下来就操作一下局部更新吧!接着往下看!!!
    
    # 局部更新数据:发送 POST 请求:http://192.168.111.128:9200/haoke/user/1001/_update
    # 注意:请求路径上多了_update 标识
    
    {
        "doc":{
            "age":23   // 这里只修改年龄,发送请求时记得把这注释给去掉
        }
    }
    
    # 更新数据之后返回结果如下:
    
    {
        "_index": "haoke",
        "_type": "user",
        "_id": "1001",
        "_version": 4,          // 更新之后,版本再+1
        "result": "updated",
        "_shards": {
            "total": 1,
            "successful": 1,
            "failed": 0
        },
        "_seq_no": 3,
        "_primary_term": 1
    }
    

    局部更新的最终结果如下图:

    四、删除数据

    在 Elasticsearch 中,删除文档数据,只需要发起 DELETE 请求即可,不用额外的参数。示例如下:

    # 删除数据:只需要发起 DELETE 请求即可,不需要其他参数和 JSON 请求数据
    # 发起 DELETE 请求示例:http://192.168.111.128:9200/haoke/user/1001
    
    # 返回结果如下:
    {
        "_index": "haoke",
        "_type": "user",
        "_id": "1001",
        "_version": 5,          # 版本再+1
        "result": "deleted",    # 表示删除数据
        "_shards": {
            "total": 1,
            "successful": 1,
            "failed": 0
        },
        "_seq_no": 4,
        "_primary_term": 1
    }
    
    # 如果看到上面结果,就表示删除成功了,在这里就不发图片了。
    # 需要注意的是,result 表示已经删除,version 也增加了。
    
    # 那么问题来了:如果删除一条不存在的数据,会怎么样呢?
    答案是:会响应 404 Not Found
    
    # 发起 DELETE 请求示例:http://192.168.111.128:9200/haoke/user/123456
    # 因为没有 123456 这个索引的数据,所以响应结果如下:
    
    {
        "_index": "haoke",
        "_type": "user",
        "_id": "123456",
        "_version": 1,
        "result": "not_found",   # 响应 not_found ,也就是 404 状态码
        "_shards": {
            "total": 1,
            "successful": 1,
            "failed": 0
        },
        "_seq_no": 1,
        "_primary_term": 1
    }
    

    TIPS: 在 Elasticsearch 中,删除一个文档也不会立即从磁盘上移除,它只是被标记成已删除。 Elasticsearch 将会在你之后添加更多索引的时候才会在后台进行删除内容的清理。【相当于批量操作】

    五、搜索数据

    1、根据 ID 查询数据

    在 Elasticsearch 中,搜索数据和删除数据的操作差不多,搜索数据只需要发起 GET 请求即可。示例如下:

    # 根据 id 搜索数据,发起 GET 请求:http://192.168.111.128:9200/haoke/user/slEeGXsBPO5WrcGKv8WO
    # 注意:slEeGXsBPO5WrcGKv8WO 是 id 值,每个人的是不一样的,填写自己的就好了
    
    # 返回结果如下:
    {
        "_index": "haoke",
        "_type": "user",
        "_id": "slEeGXsBPO5WrcGKv8WO",
        "_version": 1,
        "found": true,
        "_source": {          # 原始数据存放在这里
            "id": 1002,
            "name": "李四",
            "age": 21,
            "sex": "男"
        }
    }
    

    2、查询所有数据

    以上是根据 id 搜索数据,那如果要查询所有数据,该怎么做呢?示例如下:

    # 搜索全部数据,发送 GET 请求:http://192.168.111.128:9200/haoke/user/_search
    # 注意:请求路径上多了 _search 标识
    # 注意:使用查询全部数据的时候,默认只会返回 10 条
    
    # 返回结果如下,因为我只有一条数据,所有只返回一条数据:
    {
        "took": 16,
        "timed_out": false,
        "_shards": {
            "total": 2,
            "successful": 2,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": 1,
            "max_score": 1.0,
            "hits": [
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "slEeGXsBPO5WrcGKv8WO",
                    "_score": 1.0,
                    "_source": {
                        "id": 1002,
                        "name": "李四",
                        "age": 21,
                        "sex": "男"
                    }
                }
            ]
        }
    }
    

    3、关键字搜索数据

    关键字搜索 和查询所有数据差不多,只不过在后面拼接了一些参数而已。示例如下:

    # 关键字搜索数据,发送 GET 请求
    # 搜索年龄等于20岁的数据:http://192.168.111.128:9200/haoke/user/_search?q=age:20
    
    # 查询结果如下:
    {
        "took": 107,
        "timed_out": false,
        "_shards": {
            "total": 2,
            "successful": 2,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": 0,
            "max_score": null,
            "hits": []
        }
    }
    
    # 由结果可知,没有查询到年龄等于20岁的数据
    
    # 搜索年龄等于21岁的数据:http://192.168.111.128:9200/haoke/user/_search?q=age:21
    
    # 查询结果如下:
    {
        "took": 8,
        "timed_out": false,
        "_shards": {
            "total": 2,
            "successful": 2,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": 1,
            "max_score": 1.0,
            "hits": [
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "slEeGXsBPO5WrcGKv8WO",
                    "_score": 1.0,
                    "_source": {
                        "id": 1002,
                        "name": "李四",
                        "age": 21,
                        "sex": "男"
                    }
                }
            ]
        }
    }
    

    六、DSL 搜索数据

    由于 关键字搜索 不太灵活,具有局限性,所以需要使用 DSL 来进行更加高级的搜索。因此,Elasticsearch 提供丰富且灵活的查询语言叫做 DSL 查询 ,它允许你构建更加复杂、强大的查询。 DSL(Domain Specific Language 特定领域语言) 允许以 JSON 请求体的形式出现。具体的使用如下:

    # DSL 搜索数据:发送 POST 请求:http://192.168.111.128:9200/haoke/user/_search
    # 请求体如下(查询年龄等于21岁的数据):
    {
        "query" : {
            "match" : {     # match 只是查询的一种,查询时去掉此行注释
                "age" : 21
            }
        }
    }
    
    # 查询结果如下:
    {
        "took": 5,
        "timed_out": false,
        "_shards": {
            "total": 2,
            "successful": 2,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": 1,
            "max_score": 1.0,
            "hits": [
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "slEeGXsBPO5WrcGKv8WO",
                    "_score": 1.0,
                    "_source": {
                        "id": 1002,
                        "name": "李四",
                        "age": 21,
                        "sex": "男"
                    }
                }
            ]
        }
    }
    

    既然 DSL 这么强,那就使用 DSL 来实现这个 需求: 实现查询年龄大于 30 岁的男性用户。【注意】这里有两个条件:1、年龄大于30岁 2、男性用户。 具体的实现步骤如下:

    # 第一步:先插入 5 条数据:
    {"id":1002,"name":"李四","age":30, "sex":"男"}
    {"id":1003,"name":"王五","age":25, "sex":"男"}
    {"id":1004,"name":"妲己","age":33, "sex":"女"}
    {"id":1005,"name":"赵六","age":35, "sex":"男"}
    {"id":1006,"name":"虞姬","age":31, "sex":"女"}
    

    插入成功之后,结果如下:

    # 第二步:实现查询年龄大于 30 岁的男性用户
    # 1、发起 POST 请求:http://192.168.111.128:9200/haoke/user/_search
    # 2、编辑请求数据,如下:
    {
        "query": {
            "bool": {
                "filter": {
                    "range": {
                        "age": {
                            "gt": 30
                        }
                    }
                },
                "must": {
                    "match": {
                        "sex": "男"
                    }
                }
            }
        }
    }
    
    # 3、返回结果如下:
    {
        "took": 88,
        "timed_out": false,
        "_shards": {
            "total": 2,
            "successful": 2,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": 1,
            "max_score": 0.44183275,
            "hits": [
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "tlF_GXsBPO5WrcGKzcUV",
                    "_score": 0.44183275,
                    "_source": {
                        "id": 1005,
                        "name": "赵六",
                        "age": 35,
                        "sex": "男"
                    }
                }
            ]
        }
    }
    

    除此之外,我们还可以去实现 全文搜索 ,具体示例如下:

    # 全文搜索:发起 POST 请求:http://192.168.111.128:9200/haoke/user/_search
    # 编辑请求数据,如下:
    {
        "query": {
            "match": {
                 "name": "妲己 虞姬"
            }
        }
    }
    
    # 返回结果如下:
    {
        "took": 13,
        "timed_out": false,
        "_shards": {
            "total": 2,
            "successful": 2,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": 2,
            "max_score": 3.0808902,
            "hits": [
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "tVF_GXsBPO5WrcGKp8UH",
                    "_score": 3.0808902,
                    "_source": {
                        "id": 1004,
                        "name": "妲己",
                        "age": 33,
                        "sex": "女"
                    }
                },
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "t1F_GXsBPO5WrcGK3sXo",
                    "_score": 3.0808902,
                    "_source": {
                        "id": 1006,
                        "name": "虞姬",
                        "age": 31,
                        "sex": "女"
                    }
                }
            ]
        }
    }
    

    七、高亮显示和聚合

    1、高亮显示

    高亮显示,只需要在添加一个 highlight 即可。具体操作如下:

    # 高亮显示的前提仍是搜索,所以还是发起 POST 请求:http://192.168.111.128:9200/haoke/user/_search
    # 编辑请求数据,添加一个 highlight 属性。具体如下:
    {
        "query": {
            "match": {
                "name": "妲己 虞姬"
            }
        },
        "highlight": {
            "fields": {
                "name": {}
            }
        }
    }
    
    # 返回结果如下:
    {
        "took": 84,
        "timed_out": false,
        "_shards": {
            "total": 2,
            "successful": 2,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": 2,
            "max_score": 3.0808902,
            "hits": [
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "tVF_GXsBPO5WrcGKp8UH",
                    "_score": 3.0808902,
                    "_source": {
                        "id": 1004,
                        "name": "妲己",
                        "age": 33,
                        "sex": "女"
                    },
                    "highlight": {
                        "name": [
                            "<em>妲</em><em>己</em>"
                        ]
                    }
                },
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "t1F_GXsBPO5WrcGK3sXo",
                    "_score": 3.0808902,
                    "_source": {
                        "id": 1006,
                        "name": "虞姬",
                        "age": 31,
                        "sex": "女"
                    },
                    "highlight": {
                        "name": [
                            "<em>虞</em><em>姬</em>"
                        ]
                    }
                }
            ]
        }
    }
    
    # 由于暂时没有加入分词器,所以高亮部分是每一字,分词器会在后面介绍!
    

    2、聚合

    在 Elasticsearch 中,支持聚合操作,这类似 SQL 中的 group by 操作。具体如下:

    # 聚合的前提仍是搜索,所以还是发起 POST 请求:http://192.168.111.128:9200/haoke/user/_search
    # 编辑请求数据,具体如下:
    {
        "aggs": {
            "all_interests": {
                "terms": {
                    "field": "age"   // 以 age 进行聚合,即以 age 进行分组。发送请求时去掉此行注释
                }
            }
        }
    }
    

    上述请求的结果如下:

    {
        "took": 86,
        "timed_out": false,
        "_shards": {
            "total": 2,
            "successful": 2,
            "skipped": 0,
            "failed": 0
        },
        "hits": {
            "total": 6,
            "max_score": 1.0,
            "hits": [
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "slEeGXsBPO5WrcGKv8WO",
                    "_score": 1.0,
                    "_source": {
                        "id": 1002,
                        "name": "李四",
                        "age": 21,
                        "sex": "男"
                    }
                },
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "s1F8GXsBPO5WrcGK4MVL",
                    "_score": 1.0,
                    "_source": {
                        "id": 1002,
                        "name": "李四",
                        "age": 30,
                        "sex": "男"
                    }
                },
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "tFF_GXsBPO5WrcGKiMW-",
                    "_score": 1.0,
                    "_source": {
                        "id": 1003,
                        "name": "王五",
                        "age": 25,
                        "sex": "男"
                    }
                },
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "tVF_GXsBPO5WrcGKp8UH",
                    "_score": 1.0,
                    "_source": {
                        "id": 1004,
                        "name": "妲己",
                        "age": 33,
                        "sex": "女"
                    }
                },
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "tlF_GXsBPO5WrcGKzcUV",
                    "_score": 1.0,
                    "_source": {
                        "id": 1005,
                        "name": "赵六",
                        "age": 35,
                        "sex": "男"
                    }
                },
                {
                    "_index": "haoke",
                    "_type": "user",
                    "_id": "t1F_GXsBPO5WrcGK3sXo",
                    "_score": 1.0,
                    "_source": {
                        "id": 1006,
                        "name": "虞姬",
                        "age": 31,
                        "sex": "女"
                    }
                }
            ]
        },
        "aggregations": {
            "all_interests": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [
                    {
                        "key": 21,
                        "doc_count": 1   // 表示年龄为 21 的有 1 个,以下几个以此类推
                    },
                    {
                        "key": 25,
                        "doc_count": 1
                    },
                    {
                        "key": 30,
                        "doc_count": 1
                    },
                    {
                        "key": 31,
                        "doc_count": 1
                    },
                    {
                        "key": 33,
                        "doc_count": 1
                    },
                    {
                        "key": 35,
                        "doc_count": 1
                    }
                ]
            }
        }
    }
    

    第三章:Elasticsearch 的集群搭建

    # 第一步:使用 root 用户,关闭防火墙
    systemctl status firewalld
    systemctl stop firewalld             # 一定一定要记得关闭防火墙
    ps -aux | grep elastic
    
    # 第二步:编写配置文件,具体可以查看每台服务器的配置
    cd /Cluster-Software/es-cluster/elasticsearch-6.5.4/config
    vim elasticsearch.yml                # 编写 3 个主机的配置文件
    
    # 第三步:使用 elsearch 用户启动 elasticsearch
    su elsearch
    ../bin/elasticsearch                # 三台都一样,最终可以启动
    
    # 第四步:查看结果,如下图:
    

    
    # 暂时先放放……
    
    

    第四章:实时日志系统构建及使用

    一、先启动 Elasticserch

    cd /Cluster-Software/es/elasticsearch-6.5.4/bin
    su es
    ./elasticsearch -d                   # 后台启动
    curl -X GET http://localhost:9200    # 如果能查看结果,说明启动成功
    
    # 切换回 root 用户,关闭防火墙
    su root
    systemctl status firewalld           # 查看防火墙状态,如果开启了,就把它关闭
    systemctl stop firewalld
    
    # 最后在 elasticsearch-head 插件中连接即可
    

    二、再启动 filebeat 和 Logstash

    执行项目 jar 包,用于生成日志。 具体操作如下:

    # 1、使用 root 用户且在 /root 目录下
    java -jar elk.jar > /tmp/elk_log.log &
    tail -f /tmp/elk_log.log
    
    # 2、启动 Logstash 
    cd /Cluster-Software/logstash
    touch dashboard.yml
    vim dashboard.yml
    ./bin/logstash -f dashboard.yml      # 启动 logstash
    

    dashboard.yml 配置文件内容如下:

    input {
      beats {
        port => "5044"
      }
    }
    
    filter {
      mutate {
        split => {"message"=>"|"}
      }
      mutate {
        add_field => {
          "userId" => "%{[message][1]}"
          "visit" => "%{[message][2]}"
          "date" => "%{[message][3]}"
        }
      }
      mutate {
        convert => {
          "userId" => "string"
          "visit" => "string"
          "date" => "string"
        }
      }
    }
    
    #output {
    # stdout {codec => rubydebug}
    #}
    
    output {
      elasticsearch {
        hosts => ["127.0.0.1:9200"]
      }
    }
    
    # 3、启动 filebeat 进行日志数据采集
    cd /Cluster-Software/beats/filebeats
    touch dashboard-boot.yml
    vim dashboard-boot.yml
    ./filebeat -e -c dashboard-boot.yml  # 启动 filebeat
    

    dashboard-boot.yml 配置文件内容如下:

    filebeat.inputs:      # filebeat input输入
    - type: log           # 标准输入
      enabled: true       # 启用标准输入
      paths:
        - /tmp/elk_log.log
    setup.template.settings:
      index.number_of_shards: 3      
    output.logstash:
      hosts: ["192.168.120.128:5044"]
    
      #output.console:     # 控制台输出
      #pretty: true        # 启用美化功能
      #enable: true
    

    三、最后启动 Kibana

    # 进入到 kibana 目录
    cd /Cluster-Software/kibana
    
    # 启动 kibana,如果保存,编辑 config/kibana.yml 配置文件
    ./bin/kibana
    
    # 如果成功启动,其访问地址如下。注意:192.168.120.128 是我的 ip 地址
    http://192.168.120.128:5601
    http://192.168.120.128:5601/app/kibana
    

    最终的实时日志监控系统效果如下:

    Elasticsearch
    • 文章作者:GuoShiZhan
    • 创建时间:2021-08-04 11:44:27
    • 更新时间:2021-08-17 18:00:36
    • 版权声明:本文为博主原创文章,未经博主允许不得转载!
    请 在 评 论 区 留 言 哦 ~~~
    1024