本篇继续讲解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架构社区微信群共同探讨技术