es 订阅
ES即etamsports ,全名上海英模特制衣有限公司,是法国Etam集团在中国的分支企业,创立于1994年底。ES的服装适合出游、朋友聚会、晚间娱乐、校园生活等各种轻松的休闲场合。ES为所有生活在世界各大都市的独立、 自由、追求时尚和品质敏感的现代女性设计。代表年轻人活力,有趣的生活方式,充满动感和浓厚的时代气息。 展开全文
ES即etamsports ,全名上海英模特制衣有限公司,是法国Etam集团在中国的分支企业,创立于1994年底。ES的服装适合出游、朋友聚会、晚间娱乐、校园生活等各种轻松的休闲场合。ES为所有生活在世界各大都市的独立、 自由、追求时尚和品质敏感的现代女性设计。代表年轻人活力,有趣的生活方式,充满动感和浓厚的时代气息。
信息
所属公司
上海英模特制衣有限公司
所属行业
服饰
中文名称
ES服饰
创立时间
1994
英文名称
etamsports
ES品牌介绍
ES即etamsports ,可以说ES是艾格的一个分支 跟etam weekend 和etam的关系一样
收起全文
精华内容
参与话题
问答
  • ES基本介绍

    万次阅读 多人点赞 2019-06-28 16:10:23
    ES是一个基于RESTful web接口并且构建在Apache Lucene之上的开源分布式搜索引擎。 同时ES还是一个分布式文档数据库,其中每个字段均可被索引,而且每个字段的数据均可被搜索,能够横向扩展至数以百计的服务器存储...

    简介

    ES是一个基于RESTful web接口并且构建在Apache Lucene之上的开源分布式搜索引擎。

    同时ES还是一个分布式文档数据库,其中每个字段均可被索引,而且每个字段的数据均可被搜索,能够横向扩展至数以百计的服务器存储以及处理PB级的数据。

    可以在极短的时间内存储、搜索和分析大量的数据。通常作为具有复杂搜索场景情况下的核心发动机。

    ES就是为高可用和可扩展而生的。一方面可以通过升级硬件来完成系统扩展,称为垂直或向上扩展(Vertical Scale/Scaling Up)。

    另一方面,增加更多的服务器来完成系统扩展,称为水平扩展或者向外扩展(Horizontal Scale/Scaling Out)。尽管ES能够利用更强劲的硬件,但是垂直扩展毕竟还是有它的极限。真正的可扩展性来自于水平扩展,通过向集群中添加更多的节点来分担负载,增加可靠性。ES天生就是分布式的,它知道如何管理多个节点来完成扩展和实现高可用性。意味应用不需要做任何的改动。

    Gateway,代表ES索引的持久化存储方式。在Gateway中,ES默认先把索引存储在内存中,然后当内存满的时候,再持久化到Gateway里。当ES集群关闭或重启的时候,它就会从Gateway里去读取索引数据。比如LocalFileSystem和HDFS、AS3等。

    DistributedLucene Directory,它是Lucene里的一些列索引文件组成的目录。它负责管理这些索引文件。包括数据的读取、写入,以及索引的添加和合并等。

    River,代表是数据源。是以插件的形式存在于ES中。 

    Mapping,映射的意思,非常类似于静态语言中的数据类型。比如我们声明一个int类型的变量,那以后这个变量只能存储int类型的数据。比如我们声明一个double类型的mapping字段,则只能存储double类型的数据。

    Mapping不仅是告诉ES,哪个字段是哪种类型。还能告诉ES如何来索引数据,以及数据是否被索引到等。

    Search Moudle,搜索模块,支持搜索的一些常用操作

    Index Moudle,索引模块,支持索引的一些常用操作

    Disvcovery,主要是负责集群的master节点发现。比如某个节点突然离开或进来的情况,进行一个分片重新分片等。这里有个发现机制。

    发现机制默认的实现方式是单播和多播的形式,即Zen,同时也支持点对点的实现。另外一种是以插件的形式,即EC2。

    Scripting,即脚本语言。包括很多,这里不多赘述。如mvel、js、python等。   

    Transport,代表ES内部节点,代表跟集群的客户端交互。包括 Thrift、Memcached、Http等协议

    RESTful Style API,通过RESTful方式来实现API编程。

    3rd plugins,代表第三方插件。

    Java(Netty),是开发框架。

    JMX,是监控。

    使用案例

    1、将ES作为网站的主要后端系统

    比如现在搭建一个博客系统,对于博客帖子的数据可以直接在ES上存储,并且使用ES来进行检索,统计。ES提供了持久化的存储、统计和很多其他数据存储的特性。

    注意:但是像其他的NOSQL数据存储一样,ES是不支持事务的,如果要事务机制,还是考虑使用其他的数据库做真实库。

    2、将ES添加到现有系统

    有些时候不需要ES提供所有数据的存储功能,只是想在一个数据存储的基础之上使用ES。比如已经有一个复杂的系统在运行,但是现在想加一个搜索的功能,就可以使用该方案。

    3、将ES作为现有解决方案的后端部分

    因为ES是开源的系统,提供了直接的HTTP接口,并且现在有一个大型的生态系统在支持他。比如现在我们想部署大规模的日志框架、用于存储、搜索和分析海量的事件,考虑到现有的工具可以写入和读取ES,可以不需要进行任何开发,配置这些工具就可以去运作。

    设计结构

    1、逻辑设计

    文档

    文档是可以被索引的信息的基本单位,它包含几个重要的属性:

    1. 是自我包含的。一篇文档同时包含字段和他们的取值。
    2. 是层次型的。文档中还可以包含新的文档,一个字段的取值可以是简单的,例如location字段的取值可以是字符串,还可以包含其他字段和取值,比如可以同时包含城市和街道地址。
    3. 拥有灵活的结构。文档不依赖于预先定义的模式。也就是说并非所有的文档都需要拥有相同的字段,并不受限于同一个模式

    {

      "name":"meeting",

      "location":"office",

      "organizer":"yanping"

    }

    {

      "name":"meeting",

      "location":{

        "name":"sheshouzuo",

           "date":"2019-6-28"

      },

      "memebers":["leio","shiyi"]

    }

    类型

    类型是文档的逻辑容器,类似于表格是行的容器。在不同的类型中,最好放入不同的结构的文档。

    字段

    ES中,每个文档,其实是以json形式存储的。而一个文档可以被视为多个字段的集合。

    映射

    每个类型中字段的定义称为映射。例如,name字段映射为String。

    索引

    索引是映射类型的容器一个ES的索引非常像关系型世界中的数据库,是独立的大量文档集合。

     

    关系型数据库与ES的结构上的对比

    2、物理设计

    节点

    一个节点是一个ES的实例,在服务器上启动ES之后,就拥有了一个节点,如果在另一个服务器上启动ES,这就是另一个节点。甚至可以在一台服务器上启动多个ES进程,在一台服务器上拥有多个节点。多个节点可以加入同一个集群。

    当ElasticSearch的节点启动后,它会利用多播(multicast)(或者单播,如果用户更改了配置)寻找集群中的其它节点,并与之建立连接。这个过程如下图所示:

    节点主要有3种类型,第一种类型是client_node,主要是起到请求分发的作用,类似路由。第二种类型是master_node,是主的节点,所有的新增,删除,数据分片都是由主节点操作(elasticsearch底层是没有更新数据操作的,上层对外提供的更新实际上是删除了再新增),当然也能承担搜索操作。第三种类型是date_node,该类型的节点只能做搜索操作,具体会分配到哪个date_node,就是由client_node决定,而data_node的数据都是从master_node同步过来的

    分片

    一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。

     

    为了解决这个问题,ES提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。每个分片本身也是一个功能完善并且独立的“索引”,这个“索引”可以被放置到集群中的任何节点上。

    分片之所以重要,主要有两方面的原因:

     

    1、允许你水平分割/扩展你的内容容量

    允许你在分片(潜在地,位于多个节点上)之上进行分布式的、并行的操作,进而提高性能/吞吐量

    至于一个分片怎样分布,它的文档怎样聚合回搜索请求,是完全由ES管理的,对于作为用户的你来说,这些都是透明的。

     

    2、在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了。这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,ES允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。

    复制之所以重要,主要有两方面的原因:

    (1)在分片/节点失败的情况下,提供了高可用性。因为这个原因,注意到复制分片从不与原/主要(original/primary)分片置于同一节点上是非常重要的。

    (2)扩展你的搜索量/吞吐量,因为搜索可以在所有的复制上并行运行

    总之,每个索引可以被分成多个分片。一个索引也可以被复制0次(意思是没有复制)或多次。一旦复制了,每个索引就有了主分片(作为复制源的原来的分片)和复制分片(主分片的拷贝)之别。分片和复制的数量可以在索引创建的时候指定。在索引创建之后,你可以在任何时候动态地改变复制数量,但是不能改变分片的数量。

     

    默认情况下,ES中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。一个索引的多个分片可以存放在集群中的一台主机上,也可以存放在多台主机上,这取决于你的集群机器数量。主分片和复制分片的具体位置是由ES内在的策略所决定的。

    3、插件HEAD

    elasticsearch-head是一个界面化的集群操作和管理工具

    ● node:即一个 Elasticsearch 的运行实例,使用多播或单播方式发现 cluster 并加入。

    ● cluster:包含一个或多个拥有相同集群名称的 node,其中包含一个master node。

    ● index:类比关系型数据库里的DB,是一个逻辑命名空间。

    ● alias:可以给 index 添加零个或多个alias,通过 alias 使用index 和根据index name 访问index一样,但是,alias给我们提供了一种切换index的能力,比如重建了index,取名● customer_online_v2,这时,有了alias,我要访问新 index,只需要把 alias 添加到新 index 即可,并把alias从旧的 index 删除。不用修改代码。

    ● type:类比关系数据库里的Table。其中,一个index可以定义多个type,但一般使用习惯仅配一个type。

    ● mapping:类比关系型数据库中的 schema 概念,mapping 定义了 index 中的 type。mapping 可以显示的定义,也可以在 document 被索引时自动生成,如果有新的 field,Elasticsearch 会自动推测出 field 的type并加到mapping中。

    ● document:类比关系数据库里的一行记录(record),document 是 Elasticsearch 里的一个 JSON 对象,包括零个或多个field。

    ● field:类比关系数据库里的field,每个field 都有自己的字段类型。

    ● shard:是一个Lucene 实例。Elasticsearch 基于 Lucene,shard 是一个 Lucene 实例,被 Elasticsearch 自动管理。之前提到,index 是一个逻辑命名空间,shard 是具体的物理概念,建索引、查询等都是具体的shard在工作。shard 包括primary shard 和 replica shard,写数据时,先写到primary shard,然后,同步到replica shard,查询时,primary 和 replica 充当相同的作用。replica shard 可以有多份,也可以没有,replica shard的存在有两个作用,一是容灾,如果primary shard 挂了,数据也不会丢失,集群仍然能正常工作;二是提高性能,因为replica 和 primary shard 都能处理查询。另外,如上图右侧红框所示,shard数和replica数都可以设置,但是,shard 数只能在建立index 时设置,后期不能更改,但是,replica 数可以随时更改。但是,由于 Elasticsearch 很友好的封装了这部分,在使用Elasticsearch 的过程中,我们一般仅需要关注 index 即可,不需关注shard。

     

    shard、node、cluster 在物理上构成了 Elasticsearch 集群,field、type、index 在逻辑上构成一个index的基本概念,在使用 Elasticsearch 过程中,我们一般关注到逻辑概念就好,就像我们在使用MySQL 时,我们一般就关注DB Name、Table和schema即可,而不会关注DBA维护了几个MySQL实例、master 和 slave 等怎么部署的一样。

    ES中的索引原理

    (1)传统的关系型数据库

    二叉树查找效率是logN,同时插入新的节点不必移动全部节点,所以用树型结构存储索引,能同时兼顾插入和查询的性能。因此在这个基础上,再结合磁盘的读取特性(顺序读/随机读),传统关系型数据库采用了B-Tree/B+Tree这样的数据结构做索引

    (2)ES

    采用倒排索引

    那么,倒排索引是个什么样子呢?

    https://img2018.cnblogs.com/blog/874963/201901/874963-20190127172829635-1286260863.png

    首先,来搞清楚几个概念,为此,举个例子:

    假设有个user索引,它有四个字段:分别是name,gender,age,address。画出来的话,大概是下面这个样子,跟关系型数据库一样

    https://img2018.cnblogs.com/blog/874963/201901/874963-20190127173241683-1331385372.png

    Term(单词):一段文本经过分析器分析以后就会输出一串单词,这一个一个的就叫做Term

    Term Dictionary(单词字典):顾名思义,它里面维护的是Term,可以理解为Term的集合

    Term Index(单词索引):为了更快的找到某个单词,我们为单词建立索引

    Posting List(倒排列表):倒排列表记录了出现过某个单词的所有文档的文档列表及单词在该文档中出现的位置信息,每条记录称为一个倒排项(Posting)。根据倒排列表,即可获知哪些文档包含某个单词。(PS:实际的倒排列表中并不只是存了文档ID这么简单,还有一些其它的信息,比如:词频(Term出现的次数)、偏移量(offset)等,可以想象成是Python中的元组,或者Java中的对象)

    (PS:如果类比现代汉语词典的话,那么Term就相当于词语,Term Dictionary相当于汉语词典本身,Term Index相当于词典的目录索引)

    我们知道,每个文档都有一个ID,如果插入的时候没有指定的话,Elasticsearch会自动生成一个,因此ID字段就不多说了

    上面的例子,Elasticsearch建立的索引大致如下:

    name字段:

    https://img2018.cnblogs.com/blog/874963/201901/874963-20190127175423615-230290274.png

    age字段:

    https://img2018.cnblogs.com/blog/874963/201901/874963-20190127175627644-1013476663.png

    gender字段:

    https://img2018.cnblogs.com/blog/874963/201901/874963-20190127175809626-1224287371.png

    address字段:

    https://img2018.cnblogs.com/blog/874963/201901/874963-20190127180053644-1305820142.png

    Elasticsearch分别为每个字段都建立了一个倒排索引。比如,在上面“张三”、“北京市”、22 这些都是Term,而[1,3]就是Posting List。Posting list就是一个数组,存储了所有符合某个Term的文档ID。

    只要知道文档ID,就能快速找到文档。可是,要怎样通过我们给定的关键词快速找到这个Term呢?

    当然是建索引了,为Terms建立索引,最好的就是B-Tree索引(MySQL就是B树索引最好的例子)。

    我们查找Term的过程跟在MyISAM中记录ID的过程大致是一样的

    MyISAM中,索引和数据是分开,通过索引可以找到记录的地址,进而可以找到这条记录

    在倒排索引中,通过Term索引可以找到Term在Term Dictionary中的位置,进而找到Posting List,有了倒排列表就可以根据ID找到文档了

    (PS:可以这样理解,类比MyISAM的话,Term Index相当于索引文件,Term Dictionary相当于数据文件)

    (PS:其实,前面我们分了三步,我们可以把Term Index和Term Dictionary看成一步,就是找Term。因此,可以这样理解倒排索引:通过单词找到对应的倒排列表,根据倒排列表中的倒排项进而可以找到文档记录)

    为了更进一步理解,用两张图来具现化这一过程:

    https://img2018.cnblogs.com/blog/874963/201901/874963-20190127184959667-1135956344.pnghttps://img2018.cnblogs.com/blog/874963/201901/874963-20190127185725607-2022920549.png

    (至于里面涉及的更加高深的数据压缩技巧,以及多个field联合查询利用跳表的数据结构快速做运算来查询,这些大家有兴趣可以自己去了解)

     

    展开全文
  • 一、分布式ELK平台 1.1 ELK 简介 1.1.1 什么是ELK ELK是一套日志管理的解决方案,是一套集中式日志收集系统。 – Elasticsearch:负责日志检索和储存 – Logstash:负责日志的收集和分析、处理 ...

    一、分布式ELK平台

    1.1 ELK 简介

    1.1.1 什么是ELK

    ELK是一套日志管理的解决方案,是一套集中式日志收集系统。

    – Elasticsearch:负责日志检索和储存
    – Logstash:负责日志的收集和分析、处理
    – Kibana:负责日志的可视化

    1.1.2 ELK 能做什么

    ELK组件在海量日志系统的运维中,可用于解决:
    – 分布式日志数据集中式查询和管理
    – 系统监控,包含系统硬件和应用各个组件的监控
    – 故障排查
    – 安全信息和事件管理
    – 报表功能

    二、Elasticsearch概述

    2.1 Elasticsearch简介

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

    2.2 Elasticsearch主要特点

    1.实时分析
    2.分布式实时文件存储,并将每一个字段都编入索引
    3.文档导向,所有的对象全部是文档
    4.高可用性,易扩展,支持集群(Cluster)、分片和复制(Shards 和 Replicas)
    5. 接口友好,支持 JSON

    6.Elasticsearch 是一种面向文档的数据库。

    2.3 Elasticsearch相关术语

    相关概念:
    1. Node: 装有一个 ES 服务器的节点。
    2. Cluster: 有多个Node组成的集群
    3. Document: 一个可被搜素的基础信息单元
    4. Index: 拥有相似特征的文档的集合
    5. Type: 一个索引中可以定义一种或多种类型
    6. Filed: 是 ES 的最小单位,相当于数据的某一列
    7. Shards: 索引的分片,每一个分片就是一个 Shard
    8. Replicas: 索引的拷贝

    2.4 ES 与 关系型数据库的类比

    1. 在 ES 中,文档归属于一种 类型 (type) ,而这些类型
    存在于索引 (index) 中,类比传统关系型数据库
    2.关系型数据库

    DB -> Databases -> Tables -> Rows -> Columns
    – 关系型    数据库          表           行             列

    3.Elasticsearch数据库

    ES -> Indices -> Types -> Documents -> Fields
    – ES       索引          类型          文档        域(字段)

    4.图解ES与DBMS

    5.Elasticsearch架构图

    三、ES 集群安装

    3.1 安装第一台 ES 服务器

    1.设置 ip 与主机名称对应关系
    – 配置 /etc/hosts
    192.168.5.11 node1

    2.安装 JDK
    – Elasticsearch 要求至少 Java 7
    – 一般推荐使用 OpenJDK 1.8
    – 配置好安装源以后,我们先解决依赖关系
    ~] # yum install -y java-1.8.0-openjdk

    3.安装 ES
    ~] # rpm -ivh elasticsearch-2.3.4-1.noarch

    4. 修改配置文件
    ~]# vim /etc/elasticsearch/elasticsearch.yml
    network.host: 0.0.0.0

    5.启动服务,设置自启动
    ~] # systemctl enable elasticsearch
    ~] # systemctl start elasticsearch

    6.验证服务是否正常启动

    ~] # netstat –ltunp

    ~] # curl http://192.168.4.11:9200/

    3.2 ES集群安装

    1.es1~es5 安装JDK8和elasticsearch

    ~ ] # yum -y install java-1.8.0-openjdk  elasticsearch

    2.es1~es5 集群配置文件

    ~]# vim /etc/elasticsearch/elasticsearch.yml

    cluster.name: my-es     //集群名称配置要求完全一致
    node.name: es1 [..es5]  //当前节点标识,配置本机的主机名
    network.host: 0.0.0.0     //本机IP地址
    discovery.zen.ping.unicast.hosts: [“es1”, “es2”,”es3”]   //集群节点机器,不需要全部配置

    3.启动所有节点服务

    ~] # for i in {1..5} do ssh es${i} systemctl start elasticsearch done

    4.验证集群,使用 ES 内置字段 _cluster/health

    ~] # curl http://192.168.5.11:9200/_cluster/health?pretty

     

    四、HTTP 协议简介

    4.1 http请求由三部分组成

    – 分别是:请求行、消息报头、请求正文
    – 请求行以一个方法符号开头,以空格分开,后面跟着
    请求的URI和协议的版本,格式如下:
    Method Request-URI HTTP-Version CRLF

    4.2 http请求方法

    – 常用方法 GET, POST, HEAD
    – 其他方法 OPTIONS, PUT, DELETE, TRACE 和CONNECT

    4.3 RESTFUL请求中哪些是幂等操作

    POST   –POST不是幂等操作,因为多次请求会产生不同的结果,因此POST不是幂等操作

    DELETE  – DELETE是幂等操作,第一次将资源删除后,后面多次进行此删除请求,最终结果是一样的。

    PUT      – PUT是幂等性,将A修改为B,它第一次请求值变为了B,再进行多次此操作,最终的结果还是B,与一次执行的结果是              一样的。

    GET      –GET是幂等操作,第一次请求与多次请求得到的查询结果是一样的。

    4.4 系统命令 curl

    在linux中curl是一个利用URL规则在命令行下工作的
    文件传输工具,可以说是一款很强大的http命令行工
    具。它支持多种请求模式,自定义请求 头等强大功
    能,是一款综合工具

    curl 常用参数介绍
    – -A 修改请求 agent
    – -X 设置请求方法
    – -i 显示返回头信息

    五、ES 插件的安装与使用

    5.1 ES 常用插件

    5.1.1  head 插件

    1. 它展现ES集群的拓扑结构,并且可以通过它来进行索
    引(Index)和节点(Node)级别的操作
    2. 它提供一组针对集群的查询API,并将结果以json和表
    格形式返回
    3. 它提供一些快捷菜单,用以展现集群的各种状态

    5.1.2 kopf 插件

    1. 是一个ElasticSearch的管理工具
    2. 它提供了对ES集群操作的API

    5.1.3 bigdesk 插件

    1.bigdesk是elasticsearch的一个集群监控工具
    2.可以通过它来查看es集群的各种状态,如:cpu、内存
    使用情况,索引数据、搜索情况,http连接数等

    5.2 插件安装、查看

    5.2.1 插件安装

    elk软件包下载地址:elk.zip

    /usr/share/elasticsearch/bin/plugin install ftp://192.168.1.254/public/bigdesk-master.zip
    /usr/share/elasticsearch/bin/plugin install ftp://192.168.1.254/public/elasticsearch-head-master.zip
    /usr/share/elasticsearch/bin/plugin install ftp://192.168.1.254/public/elasticsearch-kopf-master.zip

    5.2.2 查看安装的插件

    /usr/share/elasticsearch/bin/plugin list

    5.2.3 插件压缩包的路径要通过url的方式指定

    这里必须使用 url 的方式进行安装,如果文件在本地,我们也需要使用 file:// 的方式指定路径,例如文件在
    /tmp/xxx 下面,我们要写成 file:///tmp/xxx 删除使用 remove 指令

    5.2.4 访问head、kopf、desk 插件web页面

    1.ES HEAD插件   【通过它来进行索引(Index)和节点(Node)级别的操作】

    http://192.168.5.15:9200/_plugin/head/

    2. ES KOPF插件

    http://192.168.5.15:9200/_plugin/kopf

    3.ES bigdesk 插件   【查看集群状态】

    http://192.168.5.15:9200/_plugin/bigdesk/

    六、RESTful API操作ES集群

    6.1 Elasticsearch提供了一系列RESTful的API主要实现的功能

    1.检查集群、节点、索引的健康度、状态和统计
    2. 管理集群、节点、索引的数据及元数据
    3. 对索引进行CRUD操作及查询操作
    4. 执行其他高级操作如分页、排序、过滤等

    6.2 Rest API 的简单使用

    – v 参数显示详细信息
    http://192.168.4.15:9200/_cat/health?v
    – help 显示帮助信息
    http://192.168.4.15:9200/_cat/health?help

    – nodes 查询节点状态信息
    http://192.168.4.15:9200/_cat/nodes?v
    – 索引信息
    http://192.168.4.15:9200/_cat/indices?v

    6.3 RESTful API增删改查的使用

    6.3.1 创建索引

    curl -XPUT ‘http://192.168.1.13:9200/tedu/’ -d \
    ‘{
        “settings”:{
            “index”:{
                “number_of_shards”: 5,
                “number_of_replicas”: 1
            }
        }
    }’

    6.3.2 增加数据 PUT

    curl -XPUT “http://192.168.1.11:9200/nsd1804/teacher/2” -d \
    ‘{
      “title”: “dog”,
      “name”: {“first”:”huang”, “last”:”a”},
      “age”:2
    }’

    6.3.3 更改数据 POST

    curl -XPOST “http://192.168.1.15:9200/nsd1804/teacher/3/_update” -d \
    ‘{
      “doc”: { “age”:18 }
    }’

    6.3.4 查询与删除数据

    ~] # curl -XGET    “http://192.168.1.14:9200/nsd1804/teacher/1?pretty”
    ~] # curl -XDELETE “http://192.168.1.14:9200/nsd1804/teacher/1?pretty

    展开全文
  • ES(四)ES使用(基本查询、聚合查询)

    万次阅读 多人点赞 2019-01-08 22:31:50
    基本操作 操作索引 1.新建索引 curl -XPUT localhost:9200/index01 2.查看索引 curl -XGET http://192.168.168.101:9200/index01/_settings curl -XGET ...3.删除索引 curl -XDELETE ht...

    基本操作

    操作索引

    1.新建索引

    curl -XPUT localhost:9200/index01

    2.查看索引

    curl -XGET http://192.168.168.101:9200/index01/_settings

    curl -XGET http://192.168.168.101:9200/index01,blog/_settings

    3.删除索引

    curl -XDELETE http://192.168.168.101:9200/index02

    4.打开关闭索引

    curl -XPOST http://192.168.168.101:9200/index01/_close

    curl -XPOST http://192.168.168.101:9200/index01/_open

    文档管理

    1.新建文档

    curl -XPUT -d ‘{‘id’:1,‘title’:‘es简介’}’ http://localhost:9200/index01/article/1

    2.获取文档

    curl -XGET http://192.168.168.101:9200/index01/article/1

    3.删除文档

    curl -XDELETE http://192.168.168.101:9200/index01/article/1

    查询操作

    类Lucene查询

    
    _exists_:execution_completed_time
    __type:company_extended_business
    weibo_type:18 OR weibo_type:24 OR weibo_type:25
    NOT company_id:442966
    first_consume_time:{'2019-01-03 00:00:00' TO '2019-01-03 00:00:00'}
    
    
    

    基本查询

    指定请求头

    –header “content-Type:application/json”

    准备数据

    curl -XPUT -d '{"id":1,"title":"es简介","content":"es好用好用真好用"}' http://192.168.168.101:9200/index01/article/1
    curl -XPUT -d '{"id":1,"title":"java编程思想","content":"这就是个工具书"}' http://192.168.168.101:9200/index01/article/2
    curl -XPUT -d '{"id":1,"title":"大数据简介","content":"你知道什么是大数据吗,就是大数据"}' http://192.168.168.101:9200/index01/article/3
    

    term query

    curl -XGET http://192.168.168.101:9200/index01/_search -d {'query':{'term':{'title':'你好'}}}
    

    查询的字段只有一个值得时候,应该使用term而不是terms,在查询字段包含多个的时候才使用terms,使用terms语法,json中必须包含数组

    match在匹配时会对所查找的关键词进行分词,然后按分词匹配查找,而term会直接对关键词进行查找。一般**模糊查找的时候,多用match,而精确查找时可以使用term

    terms query

    {
        'query':{
            'terms':{
                'tag':["search",'nosql','hello']
            }
        }
    }
    

    match query

    {'query':{'match':{'title':'你好'}}}
    
    {
       "query": {
         "match": {
           "__type": "info"
         }
       },
       "sort": [
         {
           "campaign_end_time": {
             "order": "desc"
           }
         }
       ]
    }
    

    match_all

    {'query':{'match_all':{'title':'标题一样'}}}
    

    multi match

    多值匹配查询

    {
      "query": {
        "multi_match": {
          "query": "运动 上衣",
          "fields": [
            "brandName^100",
            "brandName.brandName_pinyin^100",
            "brandName.brandName_keyword^100",
            "sortName^80",
            "sortName.sortName_pinyin^80",
            "productName^60",
            "productKeyword^20"
          ],
          "type": <multi-match-type>,
          "operator": "AND"
        }
      }
    }
    
    

    Bool query

    bool查询包含四个子句,must,filter,should,must_not

    {
        'query':{
            'bool':{
                'must':[{
                    'term':{
                        '_type':{
                            'value':'age'
                        }
                    }
                 },{
                     'term':{
                         'account_grade':{
                             'value':'23'
                         }
                     }
                 }
               ]
                
            }
        }
        
    }
    
    {
    	"bool":{
                "must":{
                    "term":{"user":"lucy"}
                },
                "filter":{
                    "term":{"tag":"teach"}	
                },
                "should":[
                  	{"term":{"tag":"wow"}},
                    {"term":{"tag":"elasticsearch"}}
                ],
               	"mininum_should_match":1,
               	"boost":1.0  		            
            }
    }
    

    Filter query

    query和filter的区别:query查询的时候,会先比较查询条件,然后计算分值,最后返回文档结果;而filter是先判断是否满足查询条件,如果不满足会缓存查询结果(记录该文档不满足结果),满足的话,就直接缓存结果

    filter快在:对结果进行缓存,避免计算分值

    {
        "query": {
          "bool": {
            "must": [
              {"match_all": {}}
            ],
            "filter": {
              "range": {
                "create_admin_id": {
                  "gte": 10,
                  "lte": 20
                }
              }
            }
          }
        }
    }
    

    range query

    {
    	'query':{
        	'range':{
                'age':{
                    'gte':'30',
                    'lte':'20'
                }
        	}
    	}
    }
    

    通配符查询

    {
        'query':{
            'wildcard':{
                'title':'cr?me'
            }
        }
        
    }
    
    

    正则表达式查询

    {
        'query':{
            'regex':{
                'title':{
                    'value':'cr.m[ae]',
                    'boost':10.0
                }
            }
        }
    }
    

    前缀查询

    {
        'query':{
            'match_phrase_prefix':{
                'title':{
                    'query':'crime punish',
                    'slop':1
                }
            }
        }
    }
    

    query_string

    {
        'query':{
            'query_string':{
                'query':'title:crime^10 +title:punishment -otitle:cat +author:(+Fyodor +dostoevsky)'
            }
        }
    }
    

    聚合查询

    聚合提供了用户进行分组和数理统计的能力,可以把聚合理解成SQL中的GROUP BY和分组函数

    指标聚合/桶聚合

    Metrics(度量/指标):简单的对过滤出来的数据集进行avg,max操作,是一个单一的数值

    Bucket(桶):将过滤出来的数据集按条件分成多个小数据集,然后Metrics会分别作用在这些小数据集上

    max/min/avg/sum/stats

    {
        'aggs':{c
            'group_sum':{
                'sum':{
                    'field':'money'
                }
            }
        }
    }
    
    {
       "aggs":{
          "avg_fees":{
          		"avg":{
          			"field":"fees"
          		}
          	}
       }
    }
    

    terms聚合

    terms根据字段值项分组聚合.field按什么字段分组,size指定返回多少个分组,shard_size指定每个分片上返回多少个分组,order排序方式.可以指定include和exclude正则筛选表达式的值,指定missing设置缺省值

    {
        'aggs':{
            'group_by_type':{
                'terms':{
                    'field':'_type'
                }
            }
        }
    }
    
    {
        "size": 0, 
        "aggs": {
          "terms":{
            "terms": {
              "field": "__type",
              "size": 10
            }
          }
        }
    }
    {
        "size": 0, 
        "aggs": {
          "terms":{
            "terms": {
              "field": "__type",
              "size": 10,
              "order": {
                "_count": "asc"
              }
            }
          }
        }
    }
    {
        "size": 0, 
        "aggs": {
          "agg_terms": {
            "terms": {
              "field": "cost",
              "order": {
                "_count": "asc"
              }
            },
            "aggs": {
              "max_balance": {
                "max": {
                  "field": "cost"
                }
              }
            }
          }
        }
    }
    {
        "size": 0, 
        "aggs": {
          "agg_terms": {
            "terms": {
              "field": "cost",
              "include": ".*",
              "exclude": ".*"
            }
          }
        }
    }
    

    cardinality去重

    {
        "size": 0, 
        "aggs": {
          "count_type": {
            "cardinality": {
              "field": "__type"
            }
          }
        }
    }
    cardinality
    
    

    percentiles百分比

    percentiles对指定字段(脚本)的值按从小到大累计每个值对应的文档数的占比(占所有命中文档数的百分比),返回指定占比比例对应的值。默认返回[ 1, 5, 25, 50, 75, 95, 99 ]分位上的值
    {
        "size": 0, 
        "aggs": {
          "age_percents":{
            "percentiles": {
              "field": "age",
              "percents": [
                1,
                5,
                25,
                50,
                75,
                95,
                99
              ]
            }
          }
           
        }
    }
    
    
    {
      "size": 0,
      "aggs": {
        "states": {
          "terms": {
            "field": "gender"
          },
          "aggs": {
            "banlances": {
              "percentile_ranks": {
                "field": "balance",
                "values": [
                  20000,
                  40000
                ]
              }
            }
          }
        }
      }
    

    percentiles rank

    统计小于等于指定值得文档比

    {
        "size": 0, 
        "aggs": {
          "tests": {
            "percentile_ranks": {
              "field": "age",
              "values": [
                10,
                15
              ]
            }
          }
        }
    }
    

    filter聚合

    filter对满足过滤查询的文档进行聚合计算,在查询命中的文档中选取过滤条件的文档进行聚合,先过滤在聚合

    {
        "size": 0, 
        "aggs": {
          "agg_filter":{
            "filter": {
              "match":{"gender":"F"}
            },
            "aggs": {
              "avgs": {
                "avg": {
                  "field": "age"
                }
              }
            }
          }
        }
    }
    

    filtters聚合

    多个过滤组聚合计算

    {
        "size": 0, 
        "aggs": {
          "message": {
            "filters": {
              
              "filters": {
                "errors": {
                  "exists": {
                    "field": "__type"
                  }
                },
                "warring":{
                  "term": {
                    "__type": "info"
                  }
                }
              }
            }
          }
        }
    }
    

    range聚合

    {
        "aggs": {
          "agg_range": {
            "range": {
              "field": "cost",
              "ranges": [
                {
                  "from": 50,
                  "to": 70
                },
                {
                  "from": 100
                }
              ]
            },
            "aggs": {
              "bmax": {
                "max": {
                  "field": "cost"
                }
              }
            }
          }
        }
    }
    
    

    date_range聚合

    {
         "aggs": {
           "date_aggrs": {
             "date_range": {
               "field": "accepted_time",
               "format": "MM-yyy", 
               "ranges": [
                 {
                   "from": "now-10d/d",
                   "to": "now"
                 }
               ]
             }
           }
         }
    }
    

    date_histogram

    时间直方图聚合,就是按天、月、年等进行聚合统计。可按 year (1y), quarter (1q), month (1M), week (1w), day (1d), hour (1h), minute (1m), second (1s) 间隔聚合或指定的时间间隔聚合

    { 
      "aggs": {
        "sales_over_time": {
          "date_histogram": {
            "field": "accepted_time",
            "interval": "quarter",
            "min_doc_count" : 0, //可以返回没有数据的月份
            "extended_bounds" : { //强制返回数据的范围
               "min" : "2014-01-01",
               "max" : "2014-12-31"
            }
          }
        }
      }
    }
    

    missing聚合

    { 
      
      "aggs": {
        "account_missing": {
          "missing": {
            "field": "__type"
          }
        }
      }
    }
    

    LogStash操作

    启动logStash

    logstash -e ‘input{stdin{}}output{stdout{codec=>rubydebug}}’

    IK分词器

    curl -XPOST http://192.168.168.101:9200/_analyze -d ‘{“analyzer”:“ik”,“text”:“JAVA编程思想”}’
    http://192.168.168.101:9200/index01/_analyze?analyzer=ik&text=%E4%B8%AD%E5%8D%8E%E4%BA%BA%E6%B0%91%E5%85%B1%E5%92%8C%E5%9B%BD

    IK分词器
    curl -XPUT -d ‘{“id”:1,“kw”:“我们都爱中华人民共和国”}’ http://192.168.168.101:9200/haha1/haha/1

    Mapping

    查看mapping
    curl -XGET http://192.168.168.101:9200/jtdb_item/tb_item/_mapping


    个人微信公众号【码农峰】,每天推送最新行业资讯,每周推送原创技术文章,欢迎关注。

    展开全文
  • SpringBoot整合ES的三种方式(API、REST Client、Data-ES

    万次阅读 多人点赞 2018-09-16 21:02:56
     这种方式,官方已经明确表示在ES 7.0版本中将弃用TransportClient客户端,且在8.0版本中完全移除它,我在学习ES时,版本已经是6.4.0了。 版本搭配:SpringBoot 2.0.5,ES 5.5.0 1.1 依赖如下: &amp;...

    1. 整合案例一(使用Java API)

     这种方式,官方已经明确表示在ES 7.0版本中将弃用TransportClient客户端,且在8.0版本中完全移除它,我在学习ES时,版本已经是6.4.0了。

    版本搭配:SpringBoot 2.0.5,ES 5.5.0

    1.1 依赖如下:

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.glodon</groupId>
        <artifactId>elasticsearch_data</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <!--SpringBoot的基本父级依赖-->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.6.RELEASE</version>
        </parent>
    
        <properties>
            <java.version>1.8</java.version>
            <elasticsearch.version>5.5.0</elasticsearch.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
            </dependency>
            <!--springboot对web项目的支持-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--引入spring-data-es的依赖-->
            <dependency>
                <groupId>org.elasticsearch.client</groupId>
                <artifactId>transport</artifactId>
                <version>${elasticsearch.version}</version>
            </dependency>
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-core</artifactId>
                <version>2.7</version>
            </dependency>
            <!--<dependency>-->
                <!--<groupId>org.elasticsearch</groupId>-->
                <!--<artifactId>elasticsearch</artifactId>-->
                <!--<version>5.5.0</version>-->
            <!--</dependency>-->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.8</version>
            </dependency>
    
    
            <!--引入ES推荐的操作客户端:rest-high-level-client-->
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    1.2 配置文件

    @Configuration
    public class MyConfig {
    
        @Bean
        public TransportClient client() throws UnknownHostException {
    
            // 指定集群名,默认为elasticsearch,如果改了集群名,这里一定要加
            Settings settings = Settings.builder()
                    .put("cluster.name", "elasticsearch")
                    .build();
    
            TransportClient client = new PreBuiltTransportClient(settings);
    
            /*
            ES的TCP端口为9300,而不是之前练习的HTTP端口9200
            这里只配置了一个节点的地址然添加进去,也可以配置多个从节点添加进去再返回
             */
            InetSocketTransportAddress node = new InetSocketTransportAddress(
                    InetAddress.getByName("localhost"),
                    9300
            );
            client.addTransportAddress(node);
    
            return client;
        }
    }
    

    1.3 控制器

    @RestController
    @RequestMapping("/es")
    public class BookController {
        @Autowired
        private TransportClient client;
    
        @RequestMapping(value = "/go")
        public String go() {
            return "go1";
        }
    
        /**
         * 根据id查询
         *
         * @param id book id
         */
        @RequestMapping(value = "/book", method = RequestMethod.GET)
        public ResponseEntity<java.util.Map<String, Object>> get(@RequestParam("id") String id) {
            GetResponse result = client.prepareGet("book", "novel", id).get();
            return new ResponseEntity<>(result.getSource(), HttpStatus.OK);
        }
    
        /**
         * 添加文档
         *
         * @param id   book id
         * @param name book name
         */
        @RequestMapping(value = "/book", method = RequestMethod.POST)
        public ResponseEntity<String> add(@RequestParam("id") String id, @RequestParam("name") String name) {
            try {
                // 构造ES的文档,这里注意startObject()开始构造,结束构造一定要加上endObject()
                XContentBuilder content = XContentFactory.jsonBuilder().startObject().
                        field("id", id)
                        .field("name", name)
                        .endObject();
                IndexResponse result = client.prepareIndex("book", "novel")
                        .setSource(content).get();
                return new ResponseEntity<>(result.getId(), HttpStatus.OK);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 根据id删除book
         *
         * @param id book id
         */
        @RequestMapping(value = "/book/{id}", method = RequestMethod.DELETE)
        public ResponseEntity<String> delete(@PathVariable(value = "id") String id) {
            DeleteResponse result = client.prepareDelete("book", "novel", id).get();
            return new ResponseEntity<>(result.getResult().toString(), HttpStatus.OK);
        }
    
        /**
         * 更新文档,这里的Book可以不管他,这样做是为了解决PUT请求的问题,随便搞
         */
        @RequestMapping(value = "/book", method = RequestMethod.PUT)
        public ResponseEntity<String> update(@RequestBody Book book) {
            System.out.println(book);
            // 根据id查询
            UpdateRequest updateRequest = new UpdateRequest("book", "novel", book.getId().toString());
            try {
                XContentBuilder contentBuilder = XContentFactory.jsonBuilder().startObject();
                if (StringUtils.isNotBlank(book.getName())) {
                    contentBuilder.field("name", book.getName());
                }
                contentBuilder.endObject();
                updateRequest.doc(contentBuilder);
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 进行更新
            UpdateResponse updateResponse = new UpdateResponse();
            try {
                updateResponse = client.update(updateRequest).get();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
            return new ResponseEntity<>(updateResponse.getResult().toString(), HttpStatus.OK);
        }
    
    }
    

    具体项目案例见Jacksonary/elasticsearch_data中的es_java_api模块

    对于最新的ES 6.4.0版本搭配Transport整合流程大体相同,但有部分改变,比如配置TCP端口时InetSocketTransportAddress改成了TransportAddress,具体过程不再赘述,参见elasticsearch_data中的es_java_api2模块

    【问题】

    运行一天后出现问题:

    2018-09-16 09:48:58.742 ERROR 15004 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{NJVJTWeGTV2SqhbOX1oFiQ}{localhost}{127.0.0.1:9300}]]] with root cause
    
    org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{NJVJTWeGTV2SqhbOX1oFiQ}{localhost}{127.0.0.1:9300}]
    	at org.elasticsearch.client.transport.TransportClientNodesService.ensureNodesAreAvailable(TransportClientNodesService.java:347) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.client.transport.TransportClientNodesService.execute(TransportClientNodesService.java:245) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.client.transport.TransportProxyClient.execute(TransportProxyClient.java:59) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.client.transport.TransportClient.doExecute(TransportClient.java:363) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:408) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:80) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:54) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.action.ActionRequestBuilder.get(ActionRequestBuilder.java:62) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at com.glodon.controllers.BookController.get(BookController.java:28) ~[classes/:na]
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
    	at sun.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009) ~[na:1.8.0_181]
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012) ~[na:1.8.0_181]
    	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
    	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:40002) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181]
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181]
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
    
    2018-09-16 09:49:27.782 ERROR 15004 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{NJVJTWeGTV2SqhbOX1oFiQ}{localhost}{127.0.0.1:9300}]]] with root cause
    
    org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{NJVJTWeGTV2SqhbOX1oFiQ}{localhost}{127.0.0.1:9300}]
    	at org.elasticsearch.client.transport.TransportClientNodesService.ensureNodesAreAvailable(TransportClientNodesService.java:347) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.client.transport.TransportClientNodesService.execute(TransportClientNodesService.java:245) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.client.transport.TransportProxyClient.execute(TransportProxyClient.java:59) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.client.transport.TransportClient.doExecute(TransportClient.java:363) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:408) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:80) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:54) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at org.elasticsearch.action.ActionRequestBuilder.get(ActionRequestBuilder.java:62) ~[elasticsearch-5.5.0.jar:5.5.0]
    	at com.glodon.controllers.BookController.get(BookController.java:28) ~[classes/:na]
    	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
    	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
    	at sun.reflect.DelegatingMethodAccessorImpl.__invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45009) ~[na:1.8.0_181]
    	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:45012) ~[na:1.8.0_181]
    	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
    	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:40002) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181]
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181]
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.16.jar:8.5.16]
    	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
    

    随后的几次又出现这样的问题org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available,一番查找,解释莫非以下几种:

    1. TCP端口和HTTP搞混或者IP写错,误写成9200。反查本案例正确;
    2. 集群名改了之后,配置Client这个Bean时没有在Settingsput进去。反查本案例正确;

    重启SpringBoot项目没有报错,重启ES执行查询报错信息消失,解决方案不明,报错原因未知!

    2. 整合案例二(使用REST Clinet)

     上面的案例1是基于TCP和ES通信的(而且TransPort将来会被抛弃……),官方也给出了基于HTTP的客户端REST Client(推荐使用),官方给出来的REST Client有Java Low Level REST Client和Java Hight Level REST Client两个,前者兼容所有版本的ES,后者是基于前者开发出来的,只暴露了部分API,待完善。这个案例中使用Java Low Level REST Client,有如下的一些特点:

    • 最小化依赖;
    • 提供跨所有可用节点的负载平衡;
    • 提供节点故障和特定响应代码时的故障转移;
    • 提供失败重连的惩罚机制(是否对一个连接失败的节点尝试重连,取决于它连续失败的次数,尝试重连且失败的次数越多,客户端在再次尝试重连这个节点时等的时间就越长。说那么多,太复杂了,其实给一个场景就是:我找你玩儿,你不答应,我伤自尊了,下次去找你我隔了一个星期再去找你,你又不答应,我又伤自尊了,下次再找你的话,那我就隔两个星期,依次类推);
    • 持久连接;
    • 跟踪请求和响应的日志记录;
    • 可选的集群节点自动发现功能;

    这里使用的ES版本为最新版的6.4.0,其实官方推这个REST Client,个人还是觉得是因为它是基于HTTP端口去通信的,便于操作,而且跟ES版本几乎没有关系。

    2.1 引入依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>elasticsearch_data</artifactId>
        <groupId>com.glodon</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    
    <artifactId>es_java_rest</artifactId>
    
    <dependencies>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-client</artifactId>
            <version>6.4.0</version>
        </dependency>
            <!--引入json进行HTTP序列化-->
        <dependency>
            <groupId>org.json</groupId>
            <artifactId>json</artifactId>
            <version>20160810</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.1.0</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals><goal>shade</goal></goals>
                        <configuration>
                            <relocations>
                                <relocation>
                                    <pattern>org.apache.http</pattern>
                                    <shadedPattern>hidden.org.apache.http</shadedPattern>
                                </relocation>
                                <relocation>
                                    <pattern>org.apache.logging</pattern>
                                    <shadedPattern>hidden.org.apache.logging</shadedPattern>
                                </relocation>
                                <relocation>
                                    <pattern>org.apache.commons.codec</pattern>
                                    <shadedPattern>hidden.org.apache.commons.codec</shadedPattern>
                                </relocation>
                                <relocation>
                                    <pattern>org.apache.commons.logging</pattern>
                                    <shadedPattern>hidden.org.apache.commons.logging</shadedPattern>
                                </relocation>
                            </relocations>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    
    </project>
    

    2.2 配置文件

    基本配置如下

    @Configuration
    public class RestConfig {
        @Bean
        public RestClient getClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
            // 如果有多个从节点可以持续在内部new多个HttpHost,参数1是ip,参数2是HTTP端口,参数3是通信协议
            RestClientBuilder clientBuilder = RestClient.builder(new HttpHost("localhost", 9200, "http"));
    
            // 添加其他配置,返回来的还是RestClientBuilder对象,这些配置都是可选的
            // clientBuilder.setXX()...
    
            // 最后配置好的clientBuilder再build一下即可得到真正的Client
            return clientBuilder.build();
        }
    }
    

    2.2.1 RestClientBuilder中的其中配置

    上述的基本配置过程省去了很多东西,可以根据自己需求适当添加以下的一些配置:

    【1. 设置请求头】

    // 设置请求头,每个请求都会带上这个请求头
    Header[] defaultHeaders = {new BasicHeader("header", "value")};
    clientBuilder.setDefaultHeaders(defaultHeaders);
    

    【2. 设置超时时间】

    // 设置超时时间,多次尝试同一请求时应该遵守的超时。默认值为30秒,与默认套接字超时相同。若自定义套接字超时,则应相应地调整最大重试超时
    clientBuilder.setMaxRetryTimeoutMillis(60000);
    

    【3. 设置节点失败监听器】

    // 设置监听器,每次节点失败都可以监听到,可以作额外处理
    clientBuilder.setFailureListener(new RestClient.FailureListener() {
        @Override
        public void onFailure(Node node) {
            super.onFailure(node);
            System.out.println(node.getName() + "==节点失败了");
        }
    });
    

    【4. 设置节点选择器】

    /* 配置节点选择器,客户端以循环方式将每个请求发送到每一个配置的节点上,
    发送请求的节点,用于过滤客户端,将请求发送到这些客户端节点,默认向每个配置节点发送,
    这个配置通常是用户在启用嗅探时向专用主节点发送请求(即只有专用的主节点应该被HTTP请求命中)
    */
    clientBuilder.setNodeSelector(NodeSelector.SKIP_DEDICATED_MASTERS);
    

    除了上面有简单需求外,还可以自定义节点选择器的需求:

    // 进行详细的配置
    clientBuilder.setNodeSelector(new NodeSelector() {
        // 设置分配感知节点选择器,允许选择本地机架中的节点(如果有),否则转到任何机架中的任何其他节点。
        @Override
        public void select(Iterable<Node> nodes) {
            boolean foundOne = false;
            for (Node node: nodes) {
                String rackId = node.getAttributes().get("rack_id").get(0);
                if ("rack_one".equals(rackId)) {
                    foundOne = true;
                    break;
                }
            }
            if (foundOne) {
                Iterator<Node> nodesIt = nodes.iterator();
                while (nodesIt.hasNext()) {
                    Node node = nodesIt.next();
                    String rackId = node.getAttributes().get("rack_id").get(0);
                    if ("rack_one".equals(rackId) == false) {
                        nodesIt.remove();
                    }
                }
            }
        }
    });
    

    【5. 配置HTTP异步请求ES的线程数】

    /* 配置异步请求的线程数量,Apache Http Async Client默认启动一个调度程序线程,以及由连接管理器使用的许多工作线程
    (与本地检测到的处理器数量一样多,取决于Runtime.getRuntime().availableProcessors()返回的数量)。线程数可以修改如下,
    这里是修改为1个线程,即默认情况
    */
    clientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
            return httpAsyncClientBuilder.setDefaultIOReactorConfig(
                    IOReactorConfig.custom().setIoThreadCount(1).build()
            );
        }
    });
    

    【6. 配置连接超时和套接字超时】

    /*
        配置请求超时,将连接超时(默认为1秒)和套接字超时(默认为30秒)增加,
        这里配置完应该相应地调整最大重试超时(默认为30秒),即上面的setMaxRetryTimeoutMillis,一般于最大的那个值一致即60000
        */
    clientBuilder.setRequestConfigCallback(new RestClientBuilder.RequestConfigCallback() {
        @Override
        public RequestConfig.Builder customizeRequestConfig(RequestConfig.Builder requestConfigBuilder) {
            // 连接5秒超时,套接字连接60s超时
            return requestConfigBuilder.setConnectTimeout(5000).setSocketTimeout(60000);
        }
    });
    

    【7. 配置ES安全认证】

    /*
    如果ES设置了密码,那这里也提供了一个基本的认证机制,下面设置了ES需要基本身份验证的默认凭据提供程序
        */
    final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(AuthScope.ANY,
            new UsernamePasswordCredentials("user", "password"));
    clientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
            return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
        }
    });
    
    /*
    上面采用异步机制实现抢先认证,这个功能也可以禁用,这意味着每个请求都将在没有授权标头的情况下发送,然后查看它是否被接受,
    并且在收到HTTP 401响应后,它再使用基本认证头重新发送完全相同的请求,这个可能是基于安全、性能的考虑
        */
    clientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
            // 禁用抢先认证的方式
            httpClientBuilder.disableAuthCaching();
            return httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
        }
    });
    

    【8. 配置通信加密】

    /*
    配置通信加密,有多种方式:setSSLContext、setSSLSessionStrategy和setConnectionManager(它们的重要性逐渐递增)
        */
    KeyStore truststore = KeyStore.getInstance("jks");
    try (InputStream is = Files.newInputStream(keyStorePath)) {
        truststore.load(is, keyStorePass.toCharArray());
    }
    SSLContextBuilder sslBuilder = SSLContexts.custom().loadTrustMaterial(truststore, null);
    final SSLContext sslContext = sslBuilder.build();
    clientBuilder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
        @Override
        public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
            return httpClientBuilder.setSSLContext(sslContext);
        }
    });
    

    2.3 控制器

    主要看getEsInfo这个方法和它的返回结果

    @RestController
    @RequestMapping("/rest/book")
    public class BookController {
        @Autowired
        private RestClient client;
    
    //    // RequestOptions类保存应在同一应用程序中的多个请求之间共享的部分请求
    //    private static final RequestOptions COMMON_OPTIONS;
    //
    //    static {
    //        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
    //        // 添加所有请求所需的任何标头。
    //        builder.addHeader("Authorization", "Bearer " + TOKEN);
    //        // 自定义响应使用者
    //        builder.setHttpAsyncResponseConsumerFactory(
    //                new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(30 * 1024 * 1024 * 1024));
    //        COMMON_OPTIONS = builder.build();
    //    }
    
        @RequestMapping(value = "/go", method = RequestMethod.GET)
        public ResponseEntity<String> go() {
            return new ResponseEntity<>("go", HttpStatus.OK);
        }
    
        /**
         * 同步执行HTTP请求
         * @return
         * @throws IOException
         */
        @RequestMapping(value = "/es", method = RequestMethod.GET)
        public ResponseEntity<String> getEsInfo() throws IOException {
            // 构造HTTP请求,第一个参数是请求方法,第二个参数是服务器的端点,host默认是http://localhost:9200
            Request request = new Request("GET", "/");
    //        // 设置其他一些参数比如美化json
    //        request.addParameter("pretty", "true");
    //        // 设置请求体
    //        request.setEntity(new NStringEntity("{\"json\":\"text\"}", ContentType.APPLICATION_JSON));
    //        // 还可以将其设置为String,默认为ContentType为application/json
    //        request.setJsonEntity("{\"json\":\"text\"}");
    
            /*
            performRequest是同步的,将阻塞调用线程并在请求成功时返回Response,如果失败则抛出异常
            内部属性可以取出来通过下面的方法
             */
            Response response = client.performRequest(request);
    //        // 获取请求行
    //        RequestLine requestLine = response.getRequestLine();
    //        // 获取host
    //        HttpHost host = response.getHost();
    //        // 获取状态码
    //        int statusCode = response.getStatusLine().getStatusCode();
    //        // 获取响应头
    //        Header[] headers = response.getHeaders();
            // 获取响应体
            String responseBody = EntityUtils.toString(response.getEntity());
            return new ResponseEntity<>(responseBody, HttpStatus.OK);
        }
    
    
        /**
         * 异步执行HTTP请求
         * @return
         */
        @RequestMapping(value = "/es/asyn", method = RequestMethod.GET)
        public ResponseEntity<String> asynchronous() {
            Request request = new Request(
                    "GET",
                    "/");
            client.performRequestAsync(request, new ResponseListener() {
                @Override
                public void onSuccess(Response response) {
                    System.out.println("异步执行HTTP请求并成功");
                }
    
                @Override
                public void onFailure(Exception exception) {
                    System.out.println("异步执行HTTP请求并失败");
                }
            });
            return null;
        }
    
        /**
         * 并行异步执行HTTP请求
         */
        @RequestMapping(value = "/ps", method = RequestMethod.POST)
        public void parallAsyn(@RequestBody Book[] documents) {
    //        final CountDownLatch latch = new CountDownLatch(documents.length);
    //        for (int i = 0; i < documents.length; i++) {
    //            Request request = new Request("PUT", "/posts/doc/" + i);
    //            //let's assume that the documents are stored in an HttpEntity array
    //            request.setEntity(documents[i]);
    //            client.performRequestAsync(
    //                    request,
    //                    new ResponseListener() {
    //                        @Override
    //                        public void onSuccess(Response response) {
    //
    //                            latch.countDown();
    //                        }
    //
    //                        @Override
    //                        public void onFailure(Exception exception) {
    //
    //                            latch.countDown();
    //                        }
    //                    }
    //            );
    //        }
    //        latch.await();
        }
    
            /**
         * 添加ES对象, Book的ID就是ES中存储的document的ID,所以最好不要为空,自定义生成的ID太浮夸
         *
         * @return ResponseEntity
         * @throws IOException
         */
        @RequestMapping(value = "/", method = RequestMethod.POST)
        public ResponseEntity<String> add(@RequestBody Book book) throws IOException {
            // 构造HTTP请求,第一个参数是请求方法,第二个参数是服务器的端点,host默认是http://localhost:9200,
            // endpoint直接指定为index/type的形式
            Request request = new Request("POST", new StringBuilder("/book/book/").
                    append(book.getId()).toString());
            // 设置其他一些参数比如美化json
            request.addParameter("pretty", "true");
    
            JSONObject jsonObject = new JSONObject(book);
            System.out.println(jsonObject.toString());
            // 设置请求体并指定ContentType,如果不指定默认为APPLICATION_JSON
            request.setEntity(new NStringEntity(jsonObject.toString()));
    
            // 发送HTTP请求
            Response response = client.performRequest(request);
    
            // 获取响应体, id: AWXvzZYWXWr3RnGSLyhH
            String responseBody = EntityUtils.toString(response.getEntity());
            return new ResponseEntity<>(responseBody, HttpStatus.OK);
        }
    
        /**
         * 根据id获取ES对象
         *
         * @param id
         * @return
         * @throws IOException
         */
        @RequestMapping(value = "/{id}", method = RequestMethod.GET)
        public ResponseEntity<String> getBookById(@PathVariable("id") String id) {
            Request request = new Request("GET", new StringBuilder("/book/book/").
                    append(id).toString());
            // 添加json返回优化
            request.addParameter("pretty", "true");
            Response response = null;
            String responseBody = null;
            try {
                // 执行HHTP请求
                response = client.performRequest(request);
                responseBody = EntityUtils.toString(response.getEntity());
            } catch (IOException e) {
                return new ResponseEntity<>("can not found the book by your id", HttpStatus.NOT_FOUND);
            }
            return new ResponseEntity<>(responseBody, HttpStatus.OK);
        }
    
        /**
         * 根据id更新Book
         *
         * @param id
         * @param book
         * @return
         */
        @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
        public ResponseEntity<String> updateBook(@PathVariable("id") String id, @RequestBody Book book) throws IOException {
            // 构造HTTP请求
            Request request = new Request("POST", new StringBuilder("/book/book/").
                    append(id).append("/_update").toString());
            request.addParameter("pretty", "true");
    
            // 将数据丢进去,这里一定要外包一层“doc”,否则内部不能识别
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("doc", new JSONObject(book));
            request.setEntity(new NStringEntity(jsonObject.toString()));
    
            // 执行HTTP请求
            Response response = client.performRequest(request);
    
            // 获取返回的内容
            String responseBody = EntityUtils.toString(response.getEntity());
    
            return new ResponseEntity<>(responseBody, HttpStatus.OK);
        }
    
        /**
         * 使用脚本更新Book
         * @param id
         * @param
         * @return
         * @throws IOException
         */
        @RequestMapping(value = "/update2/{id}", method = RequestMethod.PUT)
        public ResponseEntity<String> updateBook2(@PathVariable("id") String id, @RequestParam("name") String name) throws IOException {
            // 构造HTTP请求
            Request request = new Request("POST", new StringBuilder("/book/book/").
                    append(id).append("/_update").toString());
            request.addParameter("pretty", "true");
    
            JSONObject jsonObject = new JSONObject();
            // 创建脚本语言,如果是字符变量,必须加单引号
            StringBuilder op1 = new StringBuilder("ctx._source.name=").append("'" + name + "'");
            jsonObject.put("script", op1);
    
            request.setEntity(new NStringEntity(jsonObject.toString(), ContentType.APPLICATION_JSON));
    
            // 执行HTTP请求
            Response response = client.performRequest(request);
    
            // 获取返回的内容
            String responseBody = EntityUtils.toString(response.getEntity());
    
            return new ResponseEntity<>(responseBody, HttpStatus.OK);
        }
    
        @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
        public ResponseEntity<String> deleteById(@PathVariable("id") String id) throws IOException {
            Request request = new Request("DELETE", new StringBuilder("/book/book/").append(id).toString());
            request.addParameter("pretty", "true");
            // 执行HTTP请求
            Response response = client.performRequest(request);
            // 获取结果
            String responseBody = EntityUtils.toString(response.getEntity());
    
            return new ResponseEntity<>(responseBody, HttpStatus.OK);
        }
    }
    

    详细案例见Jacksonary/elasticsearch_data中的es_java_rest模块

    3. 整合案例三(使用Spring-data-es)

     除了上述方式,Spring也提供了本身基于SpringData实现的一套方案spring-data-elasticsearch,版本之间的搭配建议为:

    spring data elasticsearch elasticsearch
    3.1.x 6.2.2
    3.0.x 5.5.0
    2.1.x 2.4.0
    2.0.x 2.2.0
    1.3.x 1.5.2

    由于ES 6.4还没有被支持,这里选择的版本搭配为ES 6.2.2, Spring-data-es版本为3.1.0.BUILD-SNAPSHOT,结果整合失败,一直报错failed to load elasticsearch nodes : org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available,然后尝试换成Data ES 3.0.10版本成功整合,步骤如下:

    1.引入依赖

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>elasticsearch_data</artifactId>
            <groupId>com.glodon</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>es_java_data</artifactId>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-elasticsearch</artifactId>
                <version>3.0.10.RELEASE</version>
            </dependency>
        </dependencies>
        <repositories>
            <repository>
                <id>spring-libs-release</id>
                <name>Spring Releases</name>
                <url>https://repo.spring.io/libs-release</url>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </repository>
        </repositories>
    
    </project>
    

    2.配置Data ES

    spring:
      data:
        elasticsearch:
          cluster-nodes: localhost:9300 # 配置IP及端口号
          cluster-name: elasticsearch
    #      cluster-name: elasticsearch622 # 配置集群名,默认为elasticsearch,如果手动更改过,这里一定要指定
    #      repositories:
    #        enabled: true
    
    

    3.创建ElasticsearchRepository实例对象

    public interface BookRepository extends ElasticsearchRepository<Book, String> {
    
        Book findByName(String name);
        List<Book> findByAuthor(String author);
        Book findBookById(String id);
    }
    

    4.配置Repositories扫描

    /**
     * @author liuwg-a
     * @date 2018/9/18 14:04
     * @description 基础包的注释驱动配置,配置自动扫描的repositories根目录
     */
    @Configuration
    @EnableElasticsearchRepositories(basePackages = "com.glodon.repositories")
    public interface ESConfig {
    }
    

    5.控制器一顿操作,增、删、改、查

    package com.glodon.controllers;
    
    import com.glodon.models.Book;
    import com.glodon.repositories.BookRepository;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.*;
    
    /**
     * @author liuwg-a
     * @date 2018/9/18 10:43
     * @description
     */
    @RequestMapping("/book")
    @RestController
    public class BookController {
    
        @Autowired
        BookRepository bookRepository;
    
        @RequestMapping(value = "/add_index", method = RequestMethod.POST)
        public ResponseEntity<String> indexDoc(@RequestBody Book book) {
            System.out.println("book===" + book);
            bookRepository.save(book);
            return new ResponseEntity<>("save executed!", HttpStatus.OK);
        }
    
        @RequestMapping(value = "/", method = RequestMethod.GET)
        public ResponseEntity<Iterable> getAll() {
            Iterable<Book> all = bookRepository.findAll();
            return new ResponseEntity<>(all, HttpStatus.OK);
        }
    
        @RequestMapping(value = "/{name}", method = RequestMethod.GET)
        public ResponseEntity<Book> getByName(@PathVariable("name") String name) {
            Book book = bookRepository.findByName(name);
            return new ResponseEntity<>(book, HttpStatus.OK);
        }
    
        @RequestMapping(value = "/{id}", method = RequestMethod.PUT)
        public ResponseEntity<Book> updateBook(@PathVariable("id") String id,
                                               @RequestBody Book updateBook) {
            Book book = bookRepository.findBookById(id);
            if (StringUtils.isNotBlank(updateBook.getId())) {
                book.setId(updateBook.getId());
            }
            if (StringUtils.isNotBlank(updateBook.getName())) {
                book.setName(updateBook.getName());
            }
            if (StringUtils.isNotBlank(updateBook.getAuthor())) {
                book.setAuthor(updateBook.getAuthor());
            }
            bookRepository.save(book);
            return new ResponseEntity<>(book, HttpStatus.OK);
        }
    
        @RequestMapping(value = "/{id}", method = RequestMethod.DELETE)
        public ResponseEntity<String> deleteBook(@PathVariable("id") String id) {
            bookRepository.deleteById(id);
            return new ResponseEntity<>("delete execute!", HttpStatus.OK);
        }
    }
    

    具体案例见Jacksonary/elasticsearch_data中的es_java_data模块

    后来我再次尝试上述的配置也是可以操作ES 5.5.0版本。

    ES官方对于不同语言操作提供了不同客户端,上述只是入门的简单操作,具体参看Elasticsearch Clients

    展开全文
  • FFmpeg+OpenGL ES+OpenSL ES打造Android视频播放器教程,该课程基于C++语言,用FFmpeg、OpenGL ES、OpenSL ES和MediaCodec打造Android视频播放器。以录播课形式讲解课程所涉及的知识点和整体流程,每节课都有相关的...
  • OpenGL ES2.0基础

    万人学习 2015-05-27 16:39:31
    初级学习OpenGL ES2.0的课程,从无到有,从进本的函数讲起,每一课时都附带一个例子程序。深入浅出的讲解可编程管线技术,令人费解的文理,以及混合技术,各种优化技术:顶点缓冲区,索引缓冲区,帧缓冲区,介绍精灵...
  • docker安装es和kibana教程

    万次阅读 2020-08-16 19:38:16
    docker安装es和kibana教程 文章目录docker安装es和kibana教程1、前提2、拉去es和kibana的镜像(由于工作原因,本人拉去6.5.0版本)3、启动es4、查看启动进程5、启动kibana 1、前提 已经安装好docker 如果没有安装...
  • 最近小编负责的一个语音质检 项目中用到了ES,下面结合实例代码分享一下java操作ES查用的查询写法。 关于es的基本操作,例如新建索引、查询封装类,请参考前面博客:【ElasticSearch实战】——封装java操作es基础...
  • 注意权限,不建议使用root,同es集群的启动用户相同即可 1. 下载 & 解压 # 下载 wget https://github.com/lmenezes/cerebro/releases/download/v0.8.3/cerebro-0.8.3.zip # 解压 unzip cerebro-0.8.3.zip # ...
  • ES6,ES7,ES8,ES9,ES10新特性一览

    万次阅读 多人点赞 2019-04-21 14:28:39
    ECMA规范最终由TC39敲定。TC39由包括浏览器厂商在内的各方组成,他们开会推动JavaScript提案沿着一条严格的发展道路前进。 从提案到入选ECMA规范主要有以下几个阶段: Stage 0: strawman——最初想法的提交。...
  • OpenGL和OpenGLes opengles1.x和opengles2.0

    千次阅读 2014-05-01 22:05:23
    关于OPENGL 1.x与OPENGL ES 1.x的区别 早先定义OpenGL ES是OpenGL的嵌入式设备版本,但由于嵌入式设备要求的是高性能,所以一些其它纯追求高性能的设备也开始用这种API方式,比如 SONY PlayStation 3。   ...
  • 【OpenGL ES】OpenGL ES简介

    千次阅读 2017-04-25 20:12:48
    【参考-khronos】https://www.khronos.org/opengles/1、简介OpenGL ES(OpenGL for Embeded System)是OpenGL(Open Graphics Library)的精简子集,是以手持和嵌入式设备为目标的高级3D图形API,如现在火爆的智能...
  • ES mapping 详解

    万次阅读 2018-10-12 15:41:21
    1 mapping type 映射(mapping) 映射是定义一个文档以及其所包含的字段如何被存储和索引的方法。 例如,用映射来定义以下内容: 哪些 string 类型的 field 应当被当成当成 full-text 字段 ...
  • 参考:https://blog.csdn.net/wwd0501/article/details/78812873 ... 之前在 2.X版本里 这个Delete By Query功能被去掉了,因为官方认为会引发一些错误,如需使用 ...
  • [OpenGL ES 01]OpenGL ES之初体验

    万次阅读 多人点赞 2012-11-25 08:38:28
    [OpenGL ES 01]OpenGL ES之初体验 罗朝辉 (http://blog.csdn.net/kesalin) 本文遵循“署名-非商业用途-保持一致”创作公用协议   一,什么是 OpenGL ES? OpenGL ES 是专门为手持设备制定的 3D 规范,...
  • Android OpenGLES2.0(一)——了解OpenGLES2.0

    万次阅读 多人点赞 2016-10-12 00:04:25
    什么是OpenGL ES? OpenGL(全写Open Graphics Library)是指定义了一个跨编程语言、跨平台的编程接口规格的专业的图形程序接口。它用于三维图像(二维的亦可),是一个功能强大,调用方便的底层图形库。 OpenGL在...
  • ES6、ES7、ES8、ES9、ES10新特性一览

    千次阅读 2019-04-11 12:06:43
    https://juejin.im/post/5ca2e1935188254416288eb2
  • springboot 本人已经 整合完毕,es配置直接写在配置文件中, 然后按照网上的配置就可以使用ElasticsearchRepository。 但是如果是spring的话 会有问题,ElasticsearchRepository 这个类的 子类 应该是不同实例...
  • springboot+es

    千次阅读 2019-04-14 14:42:34
    springboot-es 本文 :Elasticsearch 与 sprigboot 的结合,springboot 操作es 关于es 的介绍和初识 可以看 https://blog.csdn.net/u012373815/article/details/50460248 安装 ......

空空如也

1 2 3 4 5 ... 20
收藏数 111,000
精华内容 44,400
热门标签
关键字:

es