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。

    Elasticsearch入门实践

    另外,使用节点客户端还需要注意一个问题:频繁起动和停止一个或多个节点客户端会导致不必要的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集群中的所有节点建立连接,从而达到负载均衡的效果。

Elasticsearch入门实践

(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 Node

Client Node的使用模式:

Elasticsearch入门实践

<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选举,也不能保存数据。

Elasticsearch入门实践

<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-优化 亿级规模的Elasticsearch优化实战

https://www.elastic.co/guide/index.html Elastic Stack and Product Documentation

上一篇:ASP.NET MVC 的常用的HTML辅助方法笔记


下一篇:How to install tensorflow on ubuntu 18.04 64bit