ElasticSearch 实践过程中遇到的几个小问题
ulimit “不生效”
有一臺機器的在啟動 ES 的時候始終報錯
| 1 | max file descriptors [65000] for elasticsearch process is too low |
但是我已經在/etc/security/limits.conf里增加了如下配置,
| 1 2 3 4 | elasticsearch soft memlock unlimited elasticsearch hard memlock unlimited elasticsearch hard nofile 65536 elasticsearch soft nofile 65536 |
按理說ulimit -n的時候應該是會到看到 65536 的,但是依舊輸出的是 65000。郁悶
最后受這篇文章?ulimit 到底誰說了算??的啟發,我把排查目標放在了 profile 和 bashrc 文件上面。
最終發現原來還真是有人在這臺機器的/etc/bashrc的文末加了一句ulimit -n 65000,把這行去掉后就正常了。
如果你也出現了這個問題,建議排查一下以下四個文件:
| 1 2 3 4 | /etc/profile /etc/bashrc ~/.profile ~/.bashrc |
由 X-Pack 的認證機制引起的問題
X-Pack 是一個 Elastic Stack 的擴展,將安全,警報,監視,報告和圖形功能包含在一個易于安裝的軟件包中。在 Elasticsearch 5.0.0 之前,您必須安裝單獨的 Shield,Watcher 和 Marvel 插件才能獲得在 X-Pack 中所有的功能。
ES、Kibana 和 X-Pack 的安裝很簡單,有需要的可以參看:安裝 Elasticsearch、Kibana 和 X-Pack
HTTP REST API
在終端里訪問 REST API 的時候
| 1 | curl -XGET 'localhost:9200/_cat/health?v&pretty' |
會報錯
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | {"error": {"root_cause": [{"type": "security_exception","reason": "missing authentication token for REST request [/_cat/health?v&pretty]","header": {"WWW-Authenticate": "Basic realm=\"security\" charset=\"UTF-8\""}}],"type": "security_exception","reason": "missing authentication token for REST request [/_cat/health?v&pretty]","header": {"WWW-Authenticate": "Basic realm=\"security\" charset=\"UTF-8\""}},"status": 401 } |
解決辦法是添加上賬號密碼就好了
| 1 | curl --user elastic:changeme -XGET 'localhost:9200/_cat/health?v&pretty' |
這樣就能正常訪問了:
| 1 2 | epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent 1487747024 15:03:44 myClusterName yellow 1 1 19 19 0 0 19 0 - 50.0% |
這個賬號密碼實際上是 X-Pack 這個插件附帶的認證功能
Java API
使用 X-Pack 后,使用 Java API 獲取 Client 的時候會報一個類似這樣的錯:
| 1 2 3 4 5 | ... NoNodeAvailableException[None of the configured nodes are available: [{#transport#-1}{pyXJL2PeTtGejUwbpycDUg}{127.0.0.1}{127.0.0.1:9300}]] ... Caused by: org.elasticsearch.ElasticsearchSecurityException: missing authentication token for action [cluster:monitor/nodes/liveness] ... |
其實看到Caused by的時候基本就已經能確定是因為 X-Pack 引入的認證機制而引起的錯誤。
既然知道了錯誤原因,那么就加上用戶名和密碼唄!但是事情卻不是想的那么簡單,ES 的官方文檔里并沒有提到在哪里可以加用戶名和密碼。
那么想必 Google 一下就能解決了吧,但是這個解決的過程其實并不順利。首先 ES 的版本比較多,如果是 ES5 之前的版本是基本沒見到這個問題的,其次也不是每個人都會裝 X-Pack 的啊!最后 pass 掉了幾種過氣了的解決方案后,終于在 ES 的社區找到了個類似的問題,最終解決的辦法其實 elastic 已經寫到了它的文檔中,只不過不是 ElasticSearch 的文檔而是 X-Pack 的文檔里(唉,其實我應該早想到的 [捂臉])
解決的關鍵是要引入一個 jar 包 x-pack-transport-5.2.1.jar,在構造 TransportClient 時用這個 jar 包里的 PreBuiltXPackTransportClient 替換掉 PreBuiltTransportClient,然后就可以在 Settings 里定義xpack.security.user了。
解決步驟如下(以使用 Maven 來管理依賴為例):
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <project ...><repositories><!-- add the elasticsearch repo --><repository><id>elasticsearch-releases</id><url>https://artifacts.elastic.co/maven</url><releases><enabled>true</enabled></releases><snapshots><enabled>false</enabled></snapshots></repository>...</repositories>...<dependencies><!-- add the x-pack jar as a dependency --><dependency><groupId>org.elasticsearch.client</groupId><artifactId>x-pack-transport</artifactId><version>{version}</version></dependency>...</dependencies>...</project> |
| 1 2 3 4 5 6 7 8 9 | import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient; ...TransportClient client = new PreBuiltXPackTransportClient(Settings.builder().put("cluster.name", "myClusterName").put("xpack.security.user", "elastic:changeme")....build()).addTransportAddress(new InetSocketTransportAddress("localhost", 9300)); |
正常的話做完上邊兩步后代碼就能順利執行了。不過我因為用的 Maven 庫是公司的私服,在第一步添加依賴的時候始終加不上,而 x-pack-transport-5.2.1.jar 這個包直接以及間接依賴的包多達二十多個,一個個手動添加是不現實的,這時候只能開始處理 Maven 的配置問題。由于 Maven 平時我也只是直接使用,settings.xml 配置文件都是從前輩那里傳下來的,沒有仔細研究過,這次算是補補課了。
我的 ${HOME}/.m2/settings.xml 里之前 mirrors 節點的配置如下:
| 1 2 3 4 5 6 7 8 9 10 | <mirrors><mirror>...</mirror><mirror><id>nexus</id><mirrorOf>*</mirrorOf><url>http://my.host.com/nexus/groups/public</url></mirror> </mirrors> |
問題是由<mirrorOf>*</mirrorOf>這個配置引起的,mirrorOf的含義如下:
mirrorOf:用來表示該 mirror 是關聯的哪一個倉庫,其值為其關聯倉庫的 id。當要同時關聯多個倉庫時,這多個倉庫之間可以用逗號隔開;當要關聯所有的倉庫時,可以使用 “” 表示;當要關聯除某一個倉庫以外的其他所有倉庫時,可以表示為 “,!repositoryId”;當要關聯不是 localhost 或用 file 請求的倉庫時,可以表示為 “external:*”。
既然找到了問題所在,那么對應的改之即可,即 id 為 elasticsearch-releases 的這個 repository 不再會關聯到 nexus 這個鏡像上
| 1 2 3 4 5 6 7 8 9 10 | <mirrors><mirror>...</mirror><mirror><id>nexus</id><mirrorOf>*,!elasticsearch-releases</mirrorOf><url>http://my.host.com/nexus/groups/public</url></mirror> </mirrors> |
P.S.
You can also add an?Authorization?header to each request. If you’ve configured global authorization credentials, the?Authorization?header overrides the global authentication credentials. This is useful when an application has multiple users who access Elasticsearch using the same client. You can set the global token to a user that only has the?transport_client?role, and add the?transport_client?role to the individual users.
代碼片段如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.InetSocketTransportAddress; import org.elasticsearch.xpack.security.authc.support.SecuredString; import org.elasticsearch.xpack.client.PreBuiltXPackTransportClient;import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue; ...TransportClient client = new PreBuiltXPackTransportClient(Settings.builder().put("cluster.name", "myClusterName").put("xpack.security.user", "transport_client_user:changeme")....build()).build().addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300)).addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9301))String token = basicAuthHeaderValue("elastic", new SecuredString("changeme".toCharArray()));client.filterWithHeader(Collections.singletonMap("Authorization", token)).prepareSearch().get(); |
關于 SSL 可以參考?Java Client and Security
總結
以上是生活随笔為你收集整理的ElasticSearch 实践过程中遇到的几个小问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用JestClient操作Elasti
- 下一篇: 使用Java客户端操作elasticse