本篇繼續講解Elasticsearch集羣部署的細節問題java
若是咱們的Elasticsearch集羣作了一些離線的維護操做時,如擴容磁盤,升級版本等,須要對集羣進行啓動,節點數較多時,從第一個節點開始啓動,到最後一個節點啓動完成,耗時可能較長,有時候還可能出現某幾個節點因故障沒法啓動,排查問題、修復故障後才能加入到集羣中,此時集羣會幹什麼呢?node
假設10個節點的集羣,每一個節點有1個shard,升級後重啓節點,結果有3臺節點因故障未能啓動,須要耗費時間排查故障,以下圖所示:bootstrap
整個過程步驟以下:vim
這個過程能夠發現,多作了四次IO操做,shard複製,shard首次移動,shard本地刪除,shard再次移動,這樣憑空形成大量的IO壓力,若是數據量是TB級別的,那費時費力不討好。緩存
出現此類問題的緣由是節點啓動的間隔時間不能肯定,而且節點越多,這個問題越容易出現,若是能夠設置集羣等待多少個節點啓動後,再決定是否對shard進行移動,這樣IO壓力就能小不少。服務器
針對這個問題,咱們有下面幾個參數:微信
如上面的案例,咱們能夠這樣設置:數據結構
gateway.recover_after_nodes: 8 gateway.expected_nodes: 10 gateway.recover_after_time: 5m
這三個參數的含義:集羣總共有10個節點,必需要有8個節點加入集羣時,才容許執行shard恢復操做,若是10個節點未所有啓動成功,最長的等待時間爲5分鐘。架構
這幾個參數的值能夠根據實際的集羣規模來設置,而且只能在elasticsearch.yml
文件裏設置,沒有動態修改的入口。併發
上面的參數設置合理的狀況,集羣啓動是沒有shard移動的現象,這樣集羣啓動的時候就能夠由以前的幾小時,變成幾秒鐘。
一提到JVM的調優,你們都有手癢的感受,好幾百個JVM參數,說不定開啓了正確的按鈕,今後ES踏上高性能、高吞吐量的道路。現實狀況多是咱們想多了,ES的大部分參數是通過反覆論證的,基本上不用我們太操心。
Elasticsearch默認使用的垃圾回收器是CMS。
## GC configuration -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly
CMS回收器是併發式的回收器,可以跟應用程序工做線程併發工做,最大程度減小垃圾回收時的服務停頓時間。
CMS仍是會有兩個停頓階段,同時在回收特別大的heap時也會有一些問題。儘管有一些缺點,可是CMS對於要求低延時請求響應的軟件來講,仍是最佳的垃圾回收器,所以官方的推薦就是使用CMS垃圾回收器。
有一種最新的垃圾回收器叫作G1。G1回收器能夠比CMS提供更少的回收停頓時間,並且可以這對大heap有更好的回收表現。它會將heap劃分爲多個region,而後自動預測哪一個region會有最多能夠回收的空間。經過回收那些region,就能夠最小化停頓時長,並且能夠針對大heap進行回收。
聽起來還挺好的,只是G1仍是比較年輕的一種垃圾回收器,並且常常會發現一些新的bug,這些bug可能會致使jvm掛掉。穩定起見,暫時不用G1,等G1成熟後ES官方推薦後再用不遲。
咱們開發Java應用系統時,對系統調優的一個常見手段就是調整線程池,但在ES中,默認的threadpool設置是很是合理的,對於全部的threadpool來講,除了搜索的線程池,都是線程數量設置的跟cpu core同樣多的。若是咱們有8個cpu core,那麼就能夠並行運行8個線程。那麼對於大部分的線程池來講,分配8個線程就是最合理的數量。
搜索會有一個更加大的threadpool,線程數量通常被配置爲:cpu core * 3 / 2 + 1。
Elasticsearch的線程池分紅兩種:接受請求的線程和處理磁盤IO操做的線程,前面那種由ES管理,後一種由Lucene管理,它們之間會進行協做,ES的線程不會由於IO操做而block住,因此ES的線程設置跟CPU核數同樣或略大於CPU核數便可。
服務器的計算能力是很是有限的,線程池的數量過大會致使上下文頻繁切換,更費資源,若是threadpool大小設置爲50,100,甚至500,會致使CPU資源利用率很低,性能反而降低。
只須要記住:用默認的線程池,若是真要修改,以CPU核數爲準。
Elasticsearch默認的jvm heap內存大小是2G,若是是研發環境,我會改爲512MB,但在生產環境2GB有點少。
在config/jvm.options文件下,能夠看到heap的設置:
# Xms represents the initial size of total heap space # Xmx represents the maximum size of total heap space -Xms2g -Xmx2g
Elasticsearch使用內存主要有兩個大戶:jvm heap和lucene,前者ES用來存放不少數據結構來提供更快的操做性能,後者使用os cache緩存索引文件,包括倒排索引、正排索引,os cache內存是否充足,直接影響查詢檢索的性能。
通常的分配規則是:jvm heap佔用小於一半的內存,剩下的全歸lucene使用。
若是單臺機器總內存64GB,那麼heap頂格內存分配爲32GB,由於32GB內存如下,jvm會使用compressed oops來解決object pointer耗費過大空間的問題,超過32GB後,jvm的compressed oops功能關閉,這樣就只能使用64位的object pointer,會耗費更多的空間,過大的object pointer還會在cpu,main memory和LLC、L1等多級緩存間移動數據的時候,吃掉更多的帶寬。最終的結果多是50GB內存的效果和32GB同樣,白白浪費了十幾GB內存。
這裏涉及到jvm的object pointer指針壓縮技術,有興趣能夠單獨瞭解一下。
若是單臺機器總內存小於64GB,通常heap分配爲總內存的一半便可,具體要看預估的數據量是多少。
若是使用超級機器,1TB內存的那種,官網不建議上那麼牛逼的機器,建議分配4-32GB內存給heap,其餘的所有用來作os cache,這樣數據量所有緩存在內存中,不落盤查詢,性能槓槓滴。
[node-1] heap size [1007.3mb], compressed ordinary object pointers [true]
字樣出現。heap address: 0x00000000e0000000, size: 27648 MB, Compressed Oops mode: 32-bit
字樣,而不是heap address: 0x00000000f4000000, size: 28672 MB, Compressed Oops with base: 0x00000000f3ff0000
字樣。部署Elasticsearch的服務儘量關閉到swap,若是內存緩存到磁盤上,那查詢效率會由微秒級降到毫秒級,會形成性能急劇降低的隱患。
關閉辦法:
swapoff -a
關閉swap,或在/etc/fstab文件中配置。bootstrap.mlockall: true
鎖住本身的內存不被swap到磁盤上。使用命令 GET _nodes?filter_path=**.mlockall
能夠查看是否開啓mlockall
響應信息:
{ "nodes": { "A1s1uus7TpuDSiT4xFLOoQ": { "process": { "mlockall": true } } } }
若是你用root用戶啓動Elasticsearch的實例,將獲得以下的錯誤提示:
org.elasticsearch.bootstrap.StartupException: java.lang.RuntimeException: can not run elasticsearch as root at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:140) ~[elasticsearch-6.3.1.jar:6.3.1] at org.elasticsearch.bootstrap.Elasticsearch.execute(Elasticsearch.java:127) ~[elasticsearch-6.3.1.jar:6.3.1] at org.elasticsearch.cli.EnvironmentAwareCommand.execute(EnvironmentAwareCommand.java:86) ~[elasticsearch-6.3.1.jar:6.3.1] at org.elasticsearch.cli.Command.mainWithoutErrorHandling(Command.java:124) ~[elasticsearch-cli-6.3.1.jar:6.3.1] at org.elasticsearch.cli.Command.main(Command.java:90) ~[elasticsearch-cli-6.3.1.jar:6.3.1] at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:93) ~[elasticsearch-6.3.1.jar:6.3.1] at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:86) ~[elasticsearch-6.3.1.jar:6.3.1] Caused by: java.lang.RuntimeException: can not run elasticsearch as root at org.elasticsearch.bootstrap.Bootstrap.initializeNatives(Bootstrap.java:104) ~[elasticsearch-6.3.1.jar:6.3.1] at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:171) ~[elasticsearch-6.3.1.jar:6.3.1] at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:326) ~[elasticsearch-6.3.1.jar:6.3.1] at org.elasticsearch.bootstrap.Elasticsearch.init(Elasticsearch.java:136) ~[elasticsearch-6.3.1.jar:6.3.1] ... 6 more
無它,創建一個用戶,專門用來啓動Elasticsearch的,如esuser,相應的系統目錄和數據存儲目錄都賦予esuser帳戶爲歸屬者。
完整的提示信息:
max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536] memory locking requested for elasticsearch process but memory is not locked
解決辦法:設置系統參數,命令行中的esuser爲創建的Linux用戶。
[root@elasticsearch01 bin]# vi /etc/security/limits.conf # 在文件最後添加 esuser hard nofile 65536 esuser soft nofile 65536 esuser soft memlock unlimited esuser hard memlock unlimited
設置完成後,能夠經過命令查看結果:
# 請求命令 GET _nodes/stats/process?filter_path=**.max_file_descriptors # 響應結果 { "nodes": { "A1s1uus7TpuDSiT4xFLOoQ": { "process": { "max_file_descriptors": 65536 } } } }
完整的提示信息:
max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
解決辦法:添加vm.max_map_count
配置項
臨時設置:sysctl -w vm.max_map_count=262144
永久修改:修改vim /etc/sysctl.conf
文件,添加vm.max_map_count
設置
[root@elasticsearch01 bin]# vim /etc/sysctl.conf # 在文件最後添加 vm.max_map_count=262144 # 執行命令 [root@elasticsearch01 bin]# sysctl -p
實例通常使用後臺啓動的方式,在ES的bin目錄下執行命令:
[esuser@elasticsearch01 bin]$ nohup ./elasticsearch & [1] 15544 [esuser@elasticsearch01 bin]$ nohup: 忽略輸入並把輸出追加到"nohup.out"
這個elasticsearch沒有stop參數,中止時使用kill pid
命令。
[esuser@elasticsearch01 bin]$ jps | grep Elasticsearch 15544 Elasticsearch [esuser@elasticsearch01 bin]$ kill -SIGTERM 15544
發送一個SIGTERM信號給elasticsearch進程,能夠優雅的關閉實例。
本篇接着上篇的內容,講解了集羣重啓時要注意的問題,JVM Heap設置的最佳實踐,以及Elasticsearch實例啓動時常見的問題解決辦法,最後是Elasticsearch優雅關閉的命令。
專一Java高併發、分佈式架構,更多技術乾貨分享與心得,請關注公衆號:Java架構社區
能夠掃左邊二維碼添加好友,邀請你加入Java架構社區微信羣共同探討技術