专栏首页后端开发随笔Elasticsearch入门实践

Elasticsearch入门实践

官网:https://www.elastic.co/ 下载:https://www.elastic.co/downloads/elasticsearch 文档:https://www.elastic.co/guide/index.html

一. 系统环境

操作系统:CentOS release 6.8 (Final) ES版本:6.1.1

二. 安装

先确认安装了Java运行时环境:

[es@localhost]$ java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

解压ES压缩包:

[es@localhost]$ curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.1.1.zip
[es@localhost]$ unzip elasticsearch-6.1.1.zip

三. 启动

1. 启动ES单节点

[es@localhost]$ cd elasticsearch-6.1.1
[es@localhost]$ ./bin/elasticsearch      # 在前台启动,可以通过CTRL + C停止
[es@localhost]$ ./bin/elasticsearch -d   # 在后台以守护进程模式运行,通过信号通知关闭: kill -SIGTERM $pid

当然,对于在后台以守护进程模式运行的ES,可以在启动时将进程ID保存到指定文件,在停止时读取进程ID,发送SIGTERM信号给进程进行关闭。

[es@localhost]$ cd elasticsearch-6.1.1
[es@localhost]$ ./bin/elasticsearch -p /tmp/elasticsearch-pid -d
[es@localhost]$ kill -SIGTERM `cat /tmp/elasticsearch-pid`

实际上,我们还可以直接将这个启动和停止ES的操作命令写到一个脚本文件中来实现,这样就避免了每次都输入命令。 注意: 在Shell脚本不能直接使用信号SIGRTMIN,需要使用信号编号15代替,如:

#!/bin/bash
pid=`cat /tmp/elasticsearch-pid`
kill -15 $pid

验证是否启动成功:

[es@localhost]$ curl http://localhost:9200/?pretty
{
  "name" : "4t5PbHS",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "l7iMk0Y2QOWWu5UG-MWlpA",
  "version" : {
    "number" : "6.1.1",
    "build_hash" : "bd92e7f",
    "build_date" : "2017-12-17T20:23:25.338Z",
    "build_snapshot" : false,
    "lucene_version" : "7.1.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

另外,需要注意的是通过上述方式启动的ES只能在本地访问,即:只能通过localhost方式访问。

[es@localhost]$ netstat -anpt|grep 92
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 192.168.80.133:22           192.168.80.1:52710          ESTABLISHED -                   
tcp        0      0 192.168.80.133:22           192.168.80.1:52730          ESTABLISHED -                   
tcp        0     64 192.168.80.133:22           192.168.80.1:52742          ESTABLISHED -                   
tcp        0      0 ::ffff:127.0.0.1:9200       :::*                        LISTEN      4512/java           
tcp        0      0 ::1:9200                    :::*                        LISTEN      4512/java     

通常我们的ES是需要能够在外部访问的,所以需要修改elasticsearch.yml中的network.host参数为network.host: 0.0.0.0

2. 启动ES集群

节点(node)是一个运行着的Elasticsearch实例。集群(cluster)是一组具有相同cluster.name的节点集合,他们协同工作,共享数据并提供故障转移和扩展功能,当然一个节点也可以组成一个集群。必须设置一个合适的名字来替代cluster.name的默认值,这样可以防止一个新启动的节点加入到相同网络中的另一个同名的集群中。可以通过修改文件elasticsearch.yml中参数cluster.name值,然后重启ES来做到这一点。 ES默认的集群名称为:elasticsearch。

四. ES应用实践

1. 如何与ES进行交互

关于与ES的交互方式,总结起来为2种:Java API和RESTful接口。 其中,Java API比较混乱,不同版本之间无法兼容。下面,我们对在不同版本的客户端进行详细说明。

1.1 Java API

(1)[v0.90, v2.2]:在ES2.2及之前的版本中,ES为Java用户提供了两种内置客户端:

  • 节点客户端(Node Client) 节点客户端以无数据节点身份加入集群,换言之,它自己不存储任何数据,但是它知道数据在集群中的具体位置,并且能够直接转发请求到对应的节点上。
  • 传输客户端(Transport Client) 这个更轻量的传输客户端能够发送请求到远程集群。它自己不加入集群,只是简单转发请求给集群中的节点。

两种Java客户端都通过9300端口与集群交互,使用ES传输协议(ElasticsearchTransport Protocol)。集群中的节点之间也通过9300端口进行通信。如果此端口未开放,你的节点将不能组成集群。 具体来说这两种Java客户端的使用方式不相同:

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>2.2.2</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>4.5.1</version>
</dependency>
使用节点客户端:
// Embedded node clients behave just like standalone nodes,
// which means that they will leave the HTTP port open!
Settings settings = Settings.settingsBuilder()
                .put("http.enabled", false)
                .put("path.home","D:\\elasticsearch-2.2.2")
                .build();
Node node = new NodeBuilder()
        .settings(settings )
        .clusterName("elasticsearch")
        .client(true) // should not hold data
        .node();
Client client = node.client();

// 添加文档
Map<String, Object> source = new HashMap<String, Object>();
source.put("first_name", "John");
source.put("last_name", "Smith");
source.put("age", 25);
source.put("about", "I love to go rock climbing");
source.put("interests", Arrays.asList(new String[] {"sports", "music"}));
IndexRequest req = new IndexRequest().index("megacorp").type("employee")
        .id("1")
        .source(source);
client.index(req);

// on shutdown
node.close();

关于节点客户端,需要做几点说明:

  1. 节点客户端将作为一个节点加入ES集群,故需要明确设置属性:"cluster.name": "elasticsearch"。
  2. 通常我们不需要使用在该节点上存储数据,设置属性"node.client": "true"。
  3. 默认配置下节点客户端将要负责响应外部对于ES集群的请求,即:所有其他客户端对ES集群的操作都需要节点客户端进行响应,如果不希望承担这样的工作,需要设置属性:"http.enabled": false。

另外,使用节点客户端还需要注意一个问题:频繁起动和停止一个或多个节点客户端会导致不必要的ES集群抖动。

使用传输客户端:
Settings settings = Settings.settingsBuilder()
        .put("cluster.name", "elasticsearch")
        .put("client.transport.sniff", true)
        .build();
Client client = TransportClient.builder().settings(settings).build()
        .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
        //.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("test.com"), 9300));

// 添加文档
Map<String, Object> source = new HashMap<String, Object>();
source.put("first_name", "Jane");
source.put("last_name", "Smith");
source.put("age", 32);
source.put("about", "I like to collect rock albums");
source.put("interests", Arrays.asList(new String[] {"music"}));
IndexRequest req = new IndexRequest().index("megacorp").type("employee")
        .id("2")
        .source(source);
client.index(req);

// on shutdown
client.close();

很显然,传输客户端其实是使用轮训算法与ES集群中的所有节点建立连接,从而达到负载均衡的效果。

(2)[v2.3, v2.4]:在ES2.3和2.4版本中,ES提供的Java客户端被分别叫做:

  • Transport Client
  • Client Node

这里的Transport Client与之前的传输客户端是同一个东西。相比起ES2.2及之前的版本,在ES2.3和ES2.4版本中引入了一个专门用于路由请求的客户端节点Client Node,暂且称之为“路由客户端节点”。这个“路由客户端节点”与之前的节点客户端类似,需要加入ES集群,但是其不能参与Master选举,也不能保存数据,本质上来讲它就是一个轻量级的“节点客户端”。但是它不能独立为客户端服务,而是通过Transport Client连接到Client NodeClient Node的使用模式:

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>2.4.1</version>
</dependency>
<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>4.5.1</version>
</dependency>
/**
 * 启动路由客户端节点
 */
public static void startClientNode() {
    Settings settings = Settings.settingsBuilder()
            .put("node.master", false)
            .put("node.data", false)
            .put("path.home","D:\\elasticsearch-2.4.1")
            .build();
    Node node = new NodeBuilder()
            .settings(settings )
            .clusterName("elasticsearch")
            .node();
    node.start();
    System.out.println("Client Node Started");
}

/**
 * 传输客户端与客户端节点通信
 * @throws UnknownHostException
 */
public static void transportClient() throws UnknownHostException {
    System.out.println("Do transport client");
    // 传输客户端直接与"路由客户端节点"通信
    Client client = TransportClient.builder().build()
            .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9301));

    // 添加文档
    Map<String, Object> source = new HashMap<String, Object>();
    source.put("first_name", "John");
    source.put("last_name", "Smith");
    source.put("age", 25);
    source.put("about", "I love to go rock climbing");
    source.put("interests", Arrays.asList(new String[] {"sports","music"}));
    IndexRequest req = new IndexRequest().index("megacorp").type("employee")
            .id("1")
            .source(source);
    client.index(req);

    // on shutdown
    client.close();
}

(3)[v5.0,v6.1]:从ES5.0版本开始,到现在的6.1版本,ES提供的Java客户端被统一为如下2种:

  • Transport Client
  • Coordinating Only Node

从ES5.0版本开始,引入了一个新的协调节点:Coordinating Only Node,专门用于路由请求,分发批量索引操作。与Client Node类似,该协调节点不能参与master选举,也不能保存数据。

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>6.1.1</version>
</dependency>
/**
 * 从5.0版本开始,传输客户端的使用方式与之前不同(不同版本的ES Java API使用方式可能不同)
 * @throws UnknownHostException
 */
public static void transportClient() throws UnknownHostException {
    System.out.println("Do transport client");
    TransportClient client = new PreBuiltTransportClient(Settings.EMPTY)
            .addTransportAddress(new TransportAddress(InetAddress.getByName("localhost"), 9300));

    // 添加文档
    Map<String, Object> source = new HashMap<String, Object>();
    source.put("first_name", "John");
    source.put("last_name", "Smith");
    source.put("age", 25);
    source.put("about", "I love to go rock climbing");
    source.put("interests", Arrays.asList(new String[] {"sports","music"}));
    IndexRequest req = new IndexRequest().index("megacorp").type("employee")
            .id("1")
            .source(source);
    client.index(req);
    
    // on shutdown
    client.close();
}

总结起来,关于ES提供的Java API,到目前(v6.1.1)为止一共提供了4种客户端:Transport ClientNode ClientClient NodeCoordinating Only Node,他们分别对应在不同的版本中使用。其中,Transport ClientNode Client都可以独立使用,而Client NodeCoordinating Only Node都不能独立提供查询服务,他们作为一个功能节点加入ES集群,然后通过Transport Client进行连接。

注意:

  • 如上所说的Java API版本必须与集群中ES节点版本一致,否则,它们可能互相无法识别。
  • 根据ES官方的计划,TransportClient客户端将在7.0版本被标记为废弃,在8.0版本将彻底被移除,官方建议使用Java High Level REST Client。

另外,从ES5.0版本开始,还提供了一个Java REST Client,这个客户端可以兼容所有的ES版本。并且,从ES5.6版本开始,这个Java REST Client又细分为两个版本:Java Low Level REST ClientJava High Level REST Client。 其中,Java Low Level REST Client能兼容所有ES版本;而Java High Level REST Client只能兼容主版本号与之相同的ES版本,并且ES的小版本号必须大于等于Java High Level REST Client的对应小版本号。举个例子,6.0版本的Java High Level REST Client可以兼容所有6.x版本的ES,但是6.1版本的Java High Level REST Client可能无法兼容6.0版本的ES,因为ES的小版本号(0)小于Java High Level REST Client的小版本号(1)。关于更多Java REST Client信息,详见:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/5.0/index.html。

Java API虽然对Java程序员提供了一定的便利性,但是并不友好,对于非Java栈的应用来说就不能使用Java API。与之相对应的,RESTful风格的API就不能再这个限制,而且更加灵活,自由度更大。当然,ES官方提供了多种程序语言的客户端,如:Groovy,JavaScript,.NET,PHP,Perl,Python以及Ruby。关于Java API的更多信息详见:https://www.elastic.co/guide/en/elasticsearch/client/index.html

1.2 RESTful API

基于HTTP协议,以JSON为数据交互格式的RESTful API。 其他所有程序语言都可以使用RESTful API,通过9200端口的与ES进行通信,可以使用任何你喜欢的WEB客户端。事实上,如你所见,你甚至可以通过curl命令与ES通信。

1.3 其他交互方式

上面谈到的ES交互方式都是ES官方提供的API或接口,基于这些API或接口还存在一些第三方组件,对于在应用开发或调试过程中非常有用。 (1)spring-data-elasticsearch 该组件是Spring官方提供的一个与ES交互的组件库,便于在基于Spring框架的应用程序中操作ES。 详见:https://github.com/spring-projects/spring-data-elasticsearch

(2)ElasticSearch Query Builder 这是一个Chrome插件,在进行简单的调试查询时使用该插件非常便利和高效。 https://chrome.google.com/webstore/detail/elasticsearch-query-build/cioobgbmiehdijndbmjkbjlkdeijdibp?utm_source=chrome-ntp-icon

(3)ElasticSearch Head Chrome插件,用于编写DSL查询,对于学习DSL查询非常有帮助。 https://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm

2. ES操作实践

2.1 添加文档

如下示例均已RESTful接口说明。 语法:PUT http://host:port/index/type/id,文档内容使用json格式作为http请求body。

curl -i -XPUT http://localhost:9200/megacorp/employee/1 -d '
{
    "first_name": "John",
    "last_name": "Smith",
    "age": 25,
    "about": "I love to go rock climbing",
    "interests": [
        "sports",
        "music"
    ]
}
'

2.2 搜索文档

2.2.1 简单搜索
  • 语法1:GET http://host:port/index/type/id,查询指定id的文档
curl -i -XGET http://localhost:9200/megacorp/employee/1

返回:

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: 205

{
  "_index": "megacorp",
  "_type": "employee",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "about": "I love to go rock climbing",
    "last_name": "Smith",
    "interests": [
      "sports",
      "music"
    ],
    "first_name": "John",
    "age": 25
  }
}
  • 语法2:GET http://host:port/index/type/_search,查询全部文档
curl -i -XGET http://localhost:9200/megacorp/employee/_search

返回:

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: 501

{
  "took": 16,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 1,
    "hits": [
      {
        "_index": "megacorp",
        "_type": "employee",
        "_id": "2",
        "_score": 1,
        "_source": {
          "about": "I like to collect rock albums",
          "last_name": "Smith",
          "interests": [
            "music"
          ],
          "first_name": "Jane",
          "age": 32
        }
      }
    ]
  }
}
2.2.2 查询字符串搜索

语法:http://host:port/index/type/_search?q=querystring

示例:查询姓氏为Smith的员工

curl -i -XGET http://localhost:9200/megacorp/employee/_search?q=last_name:Smith

返回:

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Content-Length: 522

{
  "took": 9,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 0.30685282,
    "hits": [
      {
        "_index": "megacorp",
        "_type": "employee",
        "_id": "2",
        "_score": 0.30685282,
        "_source": {
          "about": "I like to collect rock albums",
          "last_name": "Smith",
          "interests": [
            "music"
          ],
          "first_name": "Jane",
          "age": 32
        }
      }
    ]
  }
}
2.2.3 使用DSL语句查询

查询字符串搜索便于通过命令行完成特定(ad hoc)的搜索,但是它也有局限性。Elasticsearch提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。我们可以这样表示之前关于“Smith”的查询:

curl -i -H 'Content-Type: application/json' -XPOST http://localhost:9200/megacorp/employee/_search -d '
{
    "query": {
        "match": {
            "last_name": "Smith"
        }
    }
}
'

这会返回与之前查询相同的结果。你可以看到有些东西改变了,我们不再使用查询字符串做为参数,而是使用请求体代替。这个请求体使用JSON表示,其中使用了match语句。 显然,在DSL查询中,需要传递消息体,所以只能使用POST方法。

五. 启动报错&解决方案

Q1. can not run elasticsearch as root

[root@localhost ~]# ./bin/elasticsearch
[2017-12-22T19:08:28,283][WARN ][o.e.b.ElasticsearchUncaughtExceptionHandler] [] uncaught exception in thread [main]
org.elasticsearch.bootstrap.StartupException: java.lang.RuntimeException: can not run elasticsearch as root
    at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:125) ~[elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:112) ~[elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) ~[elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:124) ~[elasticsearch-cli-6.1.1.jar:6.1.1]
    at org.elasticsearch.cli.Command.main(Command.java:90) ~[elasticsearch-cli-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92) ~[elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:85) ~[elasticsearch-6.1.1.jar:6.1.1]
Caused by: java.lang.RuntimeException: can not run elasticsearch as root
    at org.elasticsearch.bootstrap.Bootstrap.initializeNatives(Bootstrap.java:104) ~[elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:171) ~[elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:322) ~[elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:121) ~[elasticsearch-6.1.1.jar:6.1.1]
    ... 6 more

原因: ES不能使用root用户启动 解决: 使用非ROOT用户登录并启动ES即可

Q2: CONFIG_SECCOMP not compiled into kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed

[es@localhost]$ ./bin/elasticsearch
[2017-12-22T19:20:25,868][WARN ][o.e.b.JNANatives         ] unable to install syscall filter: 
java.lang.UnsupportedOperationException: seccomp unavailable: CONFIG_SECCOMP not compiled into kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed
    at org.elasticsearch.bootstrap.SystemCallFilter.linuxImpl(SystemCallFilter.java:341) ~[elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.SystemCallFilter.init(SystemCallFilter.java:616) ~[elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.JNANatives.tryInstallSystemCallFilter(JNANatives.java:258) [elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Natives.tryInstallSystemCallFilter(Natives.java:113) [elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Bootstrap.initializeNatives(Bootstrap.java:109) [elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:171) [elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:322) [elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:121) [elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:112) [elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) [elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:124) [elasticsearch-cli-6.1.1.jar:6.1.1]
    at org.elasticsearch.cli.Command.main(Command.java:90) [elasticsearch-cli-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:92) [elasticsearch-6.1.1.jar:6.1.1]
    at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:85) [elasticsearch-6.1.1.jar:6.1.1]

当我们使用非root用户启动ES时,在启动日志中看到一段异常日志:CONFIG_SECCOMP not compiled into kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed

原因: seccomp是linux kernel从2.6.23版本开始所支持的一种安全机制,详见:https://en.wikipedia.org/wiki/Seccomp 而我的主机操作系统是:CentOS release 6.8 (Final)

[root@localhost ~]# cat /etc/redhat-release 
CentOS release 6.8 (Final)
[root@localhost ~]# uname -a
Linux centosx64_tomcat1 2.6.32-642.el6.x86_64 #1 SMP Tue May 10 17:27:01 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

虽然我使用的CentOS 6.8 Final使用的内核版本为2.6.32-642,但是似乎没有支持seccomp。然而ES默认将利用内核的seccomp机制,所以报错,详见:https://github.com/elastic/elasticsearch/issues/22899

解决: ES是通过配置参数bootstrap.system_call_filter: true使用内核seccomp机制的,在开发环境下可以将该参数值设为false。

[es@localhost]$ vim config/elasticsearch.yml
bootstrap.system_call_filter: false # 默认该参数值不在elasticsearch.yml配置文件中,添加并设置为false即可。

Q3:bootstrap checks failed 当修改了参数network.host: 0.0.0.0之后再启动ES时将会报错:

[es@localhost]$ ./bin/elasticsearch
[2017-12-22T23:16:23,511][INFO ][o.e.n.Node               ] initialized
[2017-12-22T23:16:23,515][INFO ][o.e.n.Node               ] [4t5PbHS] starting ...
[2017-12-22T23:16:24,421][INFO ][o.e.t.TransportService   ] [4t5PbHS] publish_address {192.168.80.133:9300}, bound_addresses {[::]:9300}
[2017-12-22T23:16:24,494][INFO ][o.e.b.BootstrapChecks    ] [4t5PbHS] bound or publishing to a non-loopback or non-link-local address, enforcing bootstrap checks
[2017-12-22T23:16:24,509][ERROR][o.e.b.Bootstrap          ] [4t5PbHS] node validation exception
[3] bootstrap checks failed
[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
[2]: max number of threads [1024] for user [es] is too low, increase to at least [4096]
[3]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
[2017-12-22T23:16:24,524][INFO ][o.e.n.Node               ] [4t5PbHS] stopping ...
[2017-12-22T23:16:24,620][INFO ][o.e.n.Node               ] [4t5PbHS] stopped
[2017-12-22T23:16:24,620][INFO ][o.e.n.Node               ] [4t5PbHS] closing ...
[2017-12-22T23:16:24,672][INFO ][o.e.n.Node               ] [4t5PbHS] closed

原因: 在启动日志中给出了非常清楚的提示:

[1]: max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
[2]: max number of threads [1024] for user [es] is too low, increase to at least [4096]
[3]: max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

详见:https://serverfault.com/questions/681745/unable-to-change-vm-max-map-count-for-elasticsearch

解决: 以root用户身份登录 1.修改最大文件描述符数

# 先查看一下当前的最大文件描述符数
[root@localhost]# ulimit -n
1024

# 修改最大文件描述符数
[root@localhost]# vim /etc/security/limits.conf
# 添加如下2行配置
es               hard    nofile          65536
es               soft    nofile          65536

2.修改最大线程数:非root用户允许的最大线程数默认为1024

[root@localhost]# vim /etc/security/limits.conf
# 添加如2行配置
es               hard    nproc           4096
es               soft    nproc           4096

上述2项修改完毕之后需要重启系统。

3.修改vm.max_map_count:在虚拟机上运行ES时才需要修改这个值

# 先查看当前值
[root@localhost]# cat /proc/sys/vm/max_map_count
65530

# 修改
[root@localhost]# echo 262144 > /proc/sys/vm/max_map_count

该参数在修改之后重启系统后又恢复为默认值了,每次都需要重新设置。

总结

  1. ES基于Luence,但是使用上比Luence更加简单,存储文档对象。
  2. ES天生就是分布式的,易于扩展,具备良好的容错性,非常适合用于存储并检索海量数据的场景,如构建日志分析系统。

【参考】 https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html Elasticsearch: 权威指南 https://www.gitbook.com/book/looly/elasticsearch-the-definitive-guide-cn/details es gitbook https://www.gitbook.com/book/fuxiaopang/learnelasticsearch/details Elasticsearch 权威指南 http://itindex.net/detail/54168-elasticsearch-%E4%BC%98%E5%8C%96 亿级规模的Elasticsearch优化实战 https://www.elastic.co/guide/index.html Elastic Stack and Product Documentation

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 从零开始学TensorFlow【01-搭建环境、HelloWorld篇】

    最近在学习TensorFlow的相关知识,了解了TensorFlow一些基础的知识,现在周末有空了,就写写一些笔记,记录一下自己的成长~

    Java3y
  • 10.源码分析---SOFARPC内置链路追踪SOFATRACER是怎么做的?

    大家在看链路追踪之前可以先去看看官方的这篇文章SOFARPC 链路追踪剖析,有助于理解。

    luozhiyun
  • 源码分析--dubbo服务端暴露

    服务暴露的入口方法是 ServiceBean 的 onApplicationEvent。onApplicationEvent 是一个事件响应方法,该方法会在收到...

    luozhiyun
  • 动态加载css方法实现和深入解析

    此动态加载css方法 loadCss,剥离自Sea.js,并做了进一步的优化(优化代码后续会进行分析)。

    我是leon
  • Kafka实战(五) - Kafka的秘技"坂本"之争

    如果不了解各个版本之间的差异和功能变化,怎么能够准确地评判某Kafka版本是不是满足你的业务需求呢?

    JavaEdge
  • confd + Nacos | 无代码侵入的配置变更管理

    为什么要支持confd,老的应用配置管理模式是启动时读取配置文件,然后重新读取配置文件需要应用重启。

    Java技术栈
  • JavaScript嗅探执行神器-sniffer.js,你值得拥有!

    这样,不管a.js文件多大,Wall.say('wall')都可以等到文件真正加载完后,再执行。

    我是leon
  • 4个点说清楚Java中synchronized和volatile的区别

    1、Java语言为了解决并发编程中存在的原子性、可见性和有序性问题,提供了一系列和并发处理相关的关键字,比如synchronized、volatile、fina...

    程序员追风
  • 聊聊dubbo的DubboComponentScanRegistrar

    本文主要研究一下dubbo的DubboComponentScanRegistrar

    codecraft
  • 分享:手把手生成漂亮的静态文档说明页

    最近经常被问 https://t.itmuch.com/doc.html 文档页是怎么制作的,考虑到步骤略复杂,写篇手记总结下吧。

    用户1516716

扫码关注云+社区

领取腾讯云代金券