原文链接:

 http://jprante.github.com/2012/11/28/Elasticsearch-Java-Virtual-Machine-settings-explained.html

         从2006年的java6 到现在java7无论是性能或其它方面都有了很大的改进,我们没有理由不在使用Java7,我个人也认为java7在内存方面比java6优秀.

         这使我有对java6和java7及es在jvm设置有了很大的趣兴,因此写一篇博文一探其中之道。

         Es已经预先为我们的JVM进行了一些设置,而且这些设置都是比较好的,现在这方面的设置也非常小心,因此你不需要关心jvm的设置就可以马上使用ES,这大概就是所谓的开箱即使吧。

         但我们也可能jvm进行一些自己的设置,以使其能被监测或是改善你的ES Cluster中的node的一些性能。

         这篇博文试图阐明ES中的预配置和讨论最常见的一些调整,最后给出如何进行调优。

ES JVM 设置

JVM参数

ES默认值

环境变量名

-Xms

256m

 

-Xmx

1g

 

-Xms   and –Xmx

 

 

-Xmn

 

 

-XX:MaxDirectMemorySize

 

 

-Xss

256k

 

-XX:UseParNewGC

+

 

-XX:UseConcMarkSweepGC

+

 

  
   

   

  

   

-XX:CMSInitiatingOccupancyFraction

   

   

75

   

 

75

 

-XX:UseCMSInitiatingOccupancyOnly

 

 

-XX:UseCondCardMark

 

 

 

         我们可以注意到ES JVM Heap内存设置为在256M在1GB之间.

         这个设置是为在开发和示范环境中使用的,开发人员可以通过简单地安装ES就可以使用了,但是这样的内存设置在很多情况下都是不够用的,我在需要设置更大的值。

         

云计算平台(检索篇)-Elasticsearch-JVM设置篇(译)

             

(JVM)

         ES_MIN_MEM/ES_MAX_MEM 用于控制jvm的堆内存,另外还有ES_HEAP_SEIZ,这样我可以设置更多的堆内存用于ES,另外建议不在启动内存堆平衡,因为这样会浪费很大的性能。

         ES_HEAP_NEWSIZE这个参数用于控制堆内存的子集,即新生代堆控制

         ES_DIRECT_SIZE,我们可以对应到Direct Memory Size这个参数,在JVM管理数据中使用的是NIO,本机内存可以映射到虚拟地址空间,在X64的架构上更有效,在ES中没有选择进行设置,但是有一个问题,本机直接内存的分配不会受到Java堆大小的限制,但是即然是内存那肯定还是要受到本机物理内存(包括SWAP区或者Windows虚拟内存)的限制的,一般服务器管理员配置JVM参数时,会根据实际内存设置-Xmx等参数信息,但经常忽略掉直接内存,使得各个内存区域总和大于物理内存限制(包括物理的和操作系统级的限制),而导致动态扩展时出现OutOfMemoryError异常。

         下面例出一些JVM参数设置

JVM parameter                                    Garbage collector

-XX:+UseSerialGC                                serial collector

-XX:+UseParallelGC                             parallel collector

-XX:+UseParallelOldGC                      Parallel compacting collector

-XX:+UseConcMarkSweepGC         Concurrent-Mark-Sweep ( CMS ) collector

-XX:+UseG1GC         Garbage-First                   collector (G1)

UseParNewGC和UseConcMarkSweepGC是结并并行和行发性的垃圾回收机制,在JAVA6中将默认为UserParNewGC和UseGoncMarkSweepGC并禁用串行收集器.

         CMSInitiatingOccupancyFraction  垃圾回收,这个75是指,到heap占用到75%时开发进行清理,我们知道堆分为新生代和老年代两块可新生代一块为老年代的两倍,也许在没有达到75%时也可能进行垃圾回收。

       UseCondCardMark  将在在高度并发的情况下,将些值注释掉

总结:

       1、修改MAX 和MIN Heap大小设置。

         2、设置垃圾回收百分比

         3、如果在JAVA7中禁用默认的G1垃圾回收机制。

JVM进程的内存结构

 

云计算平台(检索篇)-Elasticsearch-JVM设置篇(译)

JVM内存分为如下几段:

         JVM CODE用于内部代码存放

         Noe-heap memory用于加载类

         Stack memory 用于存放本地变量和线程操作数

         Heap memory 存放引用类型对象

         Direct Buffer,缓冲输入,输出数据   

         Heap memory大小设置是非常重要的,因为java的运行取决于一个合理的heap的大小,如果设置太小,在许多垃圾回收或是高性能的情况下就会出现OutOfMemory异常。如果堆太大,垃圾回收将需要更大的数据,该算法将要面对更高数量的存活堆,这样操作系统也会面对较大的压力。

         Non-heap内存分配是由java应用程序自动设置的,没有办法控制这个参数,因为它是由JAVA应用程序代码决定的。

垃圾回收与Lucene

        在ES中的垃圾回收器是集用的CMS垃圾回收,这种回收器不是提高敢回收的效率可是降低了回收的次数,但是面对比较大的数据集合时,这种回收可能需要的时间更长。

         而这种大的数据集合主要是在Lucene的索引中,因些可以将索引的段进行一行调优工作,提高GC的效率。

index.merge.policy.segments_per_tier

减少分页

         在大堆内存的情况下,如果内存不足时会与操作系统的SWAP空间进行分页数据的交换,但是这种交换是非常慢的,这种会降低整体性能。

垃圾回收器的选择

JAVA 7中的默认是G1垃圾回收器,这种回收器和CMS回收相对,他在于处理吞吐量,但是如果在大堆的情况下CMS回收器在性能上将超过G1.

性能调优策略

1、  收集日志

2、  对日志进行分析

3、  选择你要优化的目标

4、  计划优化

5、  应用新有设置

6、  监控程序在新设置后的运行情况

7、  反复试尝

ES 垃圾回收日志格式

将日志等级调用警告在垃圾回收时你能看到如下信息:

[2012-11-26 18:13:53,166][WARN ][monitor.jvm              ] [Ectokid] [gc][ParNew][1135087][11248] duration [2.6m], collections [1]/[2.7m], total [2.6m]/[6.8m], memory [2.4gb]->[2.3gb]/[3.8gb], all_pools {[Code Cache] [13.7mb]->[13.7mb]/[48mb]}{[Par Eden Space] [109.6mb]->[15.4mb]/[1gb]}{[Par Survivor Space] [136.5mb]->[0b]/[136.5mb]}{[CMS Old Gen] [2.1gb]->[2.3gb]/[2.6gb]}{[CMS Perm Gen] [35.1mb]->[34.9mb]/[82mb]}

LogFile

说明

Gc

垃圾回收运行

ParNew

新生代垃圾回收器

duration 2.6m

垃圾回收花费时间

collections [1]/[2.7m]

一个收集器运行花费2.7M

memory [2.4gb]

预设2.4GB

[2.3gb]/[3.8gb]

现在使用2.3GB/总共3.8GB

Code Cache [13.7mb]->[13.7mb]/[48mb]

代码缓存

Par Eden Space [109.6mb]->[15.4mb]/[1gb]

Par   Eden Space使用空间

Par Survivor Space[136.5mb]->[0b]/[136.5mb]

Par   Survivor Space

CMS Old Gen [2.1gb]->[2.3gb]/[2.6gb]

CMS Old Gen

CMS Perm Gen [35.1mb]->[34.9mb]/[82mb]

CMS Perm Gen

 

建议:

1、ES不要运行在6U22之前因之多版本的JDK存在许多的bug,尽量使用Sun/Oracle比较最出的JDK6-7因为里面修复很多bug.

         如果在JAVA7正式发布的情况下最好使用JDK7(不过要到2013了)

2、考虑到ES是一个比较新的软件,利用最先的技术来获取性能,尽量从JVM中来挤压性能,另外检索您的操作系统是否是最新版的,尽量使用最新版的操作系统。

3、做好随时更新JAVA版本和ES的版本的情况,因为每季度或是每年都会有新的版本出来。所以在做好版本更新的准备

4、测试从小到大,因为ES的强在多个节点的部署,一个节点是不足以测试出其性能,一个生产系统至少在三个节点以上。

5、测试JVM

6、如果索引有更新请记住对索引段的操作(index.merge.policy.segments_per_tier)

7、在性能调优之前,请先确定系统的最大性能和最大吞吐量

8、启用日志记录对JAVA垃圾回怍机制,有助于更好的诊断,以至于来调整你的系统

9、提高CMS垃圾收集器,您可以添加一个合理的- xx:CMSWaitDuration参数

10、如果堆大小趣过6-8GB,请选择使用CMS