elasticsearch 大集群最基本,也是最重要的两个配置gc和指针压缩
本来不想写这篇的,因为实在太过基础,但就是在线上生产环境的es集群上出现了这种类问题,这两个配置也适于于所有的jvm栈服务
公司规模也不算小,因为工作分工,把一部分es集群的日常维护和搭建和升级交给平台组做了,平台组保证es的日常稳定,但并不会主动作业务层相关的优化,高负载影响业务排查时,实在不敢相信,会碰到这两个问题。
- 1 gc
简直离谱,不想吐槽,都2020年了es还在用cms,改为g1,性能提升近50%,测试环境也就算了,生产环境在cms上跑了近一年,敢信?
- 2 指针压缩
某个集群,指针压缩未生效的情况下,集群跑了近2年
不过这个虽然离谱,倒也能理解,网上找个的'最佳实践',未结合执行环境,就可能会出现这个问题
https://www.elastic.co/guide/en/elasticsearch/reference/7.2/heap-size.html
查看线上es,jvm heap配置的是 -Xms32700m -Xmx32700m
ps -ef |grep elasticsearch
elastic+ 20033 1 99 Apr10 ? 615-02:04:15 /bin/java -XX:+UseG1GC -XX:InitiatingHeapOccupancyPercent=35 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=400 -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -server -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true -Djdk.io.permissionsUseCanonicalPath=true -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true -Dio.netty.recycler.maxCapacityPerThread=0 -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true -Dlog4j.skipJansi=true -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintClassHistogram -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime -XX:GCLogFileSize=10M -XX:NumberOfGCLogFiles=10 -Xloggc:/var/log/elasticsearch/datanode/gc.log -Xms32700m -Xmx32700m -Des.path.home=/ssd/elastic_app/elasticsearch-datanode-5.3.0 -cp /ssd/elastic_app/elasticsearch-datanode-5.3.0/lib/elasticsearch-5.3.0.jar:/ssd/elastic_app/elasticsearch-datanode-5.3.0/lib/* org.elasticsearch.bootstrap.Elasticsearch -d
按es官方的介绍执行
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode -Xms32700m -Xmx32700m -version
Protected page at the reserved heap base: 0x00007f953d200000 / 2097152 bytes
heap address: 0x00007f953d400000, size: 32700 MB, Compressed Oops mode: Non-zero based:0x00007f953d3ff000, Oop shift amount: 3
Narrow klass base: 0x00007f9444220000, Narrow klass shift: 0
Compressed class space size: 1073741824 Address: 0x00007f9444220000 Req Addr: 0x00007f9d39000000
openjdk version "1.8.0_144"
OpenJDK Runtime Environment (build 1.8.0_144-b01)
主要看这行 Compressed Oops mode: Non-zero
heap address: 0x00007f953d400000, size: 32700 MB, Compressed Oops mode: Non-zero
based:0x00007f953d3ff000, Oop shift amount: 3
显然没有应用指针压缩
多次测试,发现os指针压缩的临界点是30700m Compressed Oops mode: Zero based
指针压缩,但非零址压缩,会多一步偏移量的计算过程
因此必须做到零址压缩,即Compressed Oops mode: Zero based
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode -Xms30700m -Xmx30700m -version
heap address: 0x0000000081400000, size: 30700 MB, Compressed Oops mode: Zero based, Oop shift amount: 3
30800m Compressed Oops mode: Non-zero
java -XX:+UnlockDiagnosticVMOptions -XX:+PrintCompressedOopsMode -Xms30800m -Xmx30800m -version
heap address: 0x00007f2e10000000, size: 30800 MB, Compressed Oops mode: Non-zero based:0x00007f2e0ffff000, Oop shift amount: 3
记得以前看过的一个压测报告,使用0址压缩的32G mem = 未使用指针压缩的45G mem
指针压缩未生效,保守估计,内存浪费了(45-32)/32=40%,cpu不好定量,在20%到50%之间
整体性能损失30%左右
这个0址压缩的阈值在不同os下是不同的,相同os不同版本可能也会有少许的区别,不作验证,直接抄着用,就可能出现指针压缩未生效的问题
如果在云环境更要小心,部分云服务厂商提供的os不是标准的发行版,linux内核很可能是定制过的,更需要做实际测试,之前帮算法部门解决装cuda显卡驱动的问题,就是因为azure定制内核导致的