官網: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();
關於節點客戶端,需要做幾點說明:
- 節點客戶端將作為一個節點加入ES集群,故需要明確設置屬性:"cluster.name": "elasticsearch"。
- 通常我們不需要使用在該節點上存儲數據,設置屬性"node.client": "true"。
- 默認配置下節點客戶端將要負責響應外部對於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 Node
。
Client 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 Client
,Node Client
,Client Node
,Coordinating Only Node
,他們分別對應在不同的版本中使用。其中,Transport Client
和Node Client
都可以獨立使用,而Client Node
和Coordinating 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 Client
和Java 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
該參數在修改之后重啟系統后又恢復為默認值了,每次都需要重新設置。
總結
- ES基於Luence,但是使用上比Luence更加簡單,存儲文檔對象。
- 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