ITPub博客

首页 > 数据库 > 数据库开发技术 > 【Elasticsearch运维系列】Elasticsearch7.12.1启动指定版本JDK:你学废了吗?

【Elasticsearch运维系列】Elasticsearch7.12.1启动指定版本JDK:你学废了吗?

原创 数据库开发技术 作者:oracle_jacky 时间:2024-05-08 12:02:01 0 删除 编辑


一套生ES集群,版本为7.12.1,近期频繁告警,频繁出现索引分片异常,索引状态异常,导致应用无法正常写入ES,另外,也经常出现节点掉问题。通过分析相关ES日志,显示和当前JAVA GC有关。当前ES曾经过升级,从ES 6升级到ES 7,在ES应用服务器上除了部署ES本身,还部署运行了其它应用进程。为了方便JAVA管理,ES和其它应用都使用了相同的JDK,版本为1.8.0_202。而ES 7 在启动时会提示建议使用 JDK 11及以后版本。

因为采用JDK 1.8,GC垃圾回收还采用的是CMS方式,如下所示:

[root@localhost ~]# java -XX:+PrintFlagsFinal -version | grep Use.*GC.*=.*true     bool UseAdaptiveSizeDecayMajorGCCost           = true                                {product}     bool UseGCOverheadLimit                        = true                                {product}     bool UseMaximumCompactionOnSystemGC            = true                                {product}     bool UseParallelGC                            := true                                {product}     bool UseParallelOldGC                          = true                                {product}java version "1.8.0_202"Java(TM) SE Runtime Environment (build 1.8.0_202-b08)Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)
当前JDK 1.8的JAVA_HOME是配置在/etc/profile文件中,作为全局变量使用的,如下所示:export JAVA_HOME=/usr/java/jdk1.8.0_221export ES_JAVA_HOME=/usr/java/jdk1.8.0_221export PATH=$ES_JAVA_HOME/bin:$PATHexport PATH=$JAVA_HOME/bin:$PATHexport JAVA8_HOME=/opt/lib/jdk1.8.0_202CLASSPATH=/opt/lib/jdk1.8.0_202/libJDK_HOME=/opt/lib/jdk1.8.0_202JAVA_HOME=/opt/lib/jdk1.8.0_202PATH=/opt/lib/jdk1.8.0_202/bin:/opt/lib/jdk1.8.0_202/jre/bin:$PATHexport CLASSPATH JAVA_HOME JDK_HOME PATH

在和研发等相关人员分析沟通近期问题后,建议将ES采用自带的JDK,并将GC垃圾回收调整为 G1GC,并且对JDK的调整不能影响到当前ES服务器上的其它应用对原JDK 1.8版本的使用。

当前ES启动后信息如下:

如何调整ES使用指定的JDK版本启动呢,我查询了相关资料,显示可以修改/bin/elasticsearch文件,在该文件中加入指定的JAVA_HOME,于是按照相关文档,我在测试环境上进行了验证,测试环境版本和生产版本相同。为方便修改和管理,我将ES自带的JDK目录拷贝到了当前用户家目录下,如下所示:

cp -a /home/esuser/deploy/elasticsearch-7.12.1-9300/jdk /home/esuser/OpenJDK16
对 /home/esuser/deploy/elasticsearch-7.12.1-9300/bin/elasticsearch文件进行修改,修改后的内容如下:#!/bin/bash
#配置指定的JDKexport ES_HOME=/home/esuser/OpenJDK16export PATH=$ES_HOME/bin:$PATH
#添加对JDK的判断if [ -x "$ES_HOME/bin/java" ]; then JAVA="/home/esuser/jdk/bin/java"else JAVA=`which java`fi
source "`dirname "$0"`"/elasticsearch-env
CHECK_KEYSTORE=truepwdDAEMONIZE=falsefor option in "$@"; do case "$option" in -h|--help|-V|--version) CHECK_KEYSTORE=false ;; -d|--daemonize) DAEMONIZE=true ;; esacdone
if [ -z "$ES_TMPDIR" ]; then ES_TMPDIR=`"$JAVA" "$XSHARE" -cp "$ES_CLASSPATH" org.elasticsearch.tools.launchers.TempDirectory`fi
unset KEYSTORE_PASSWORDKEYSTORE_PASSWORD=if [[ $CHECK_KEYSTORE = true ]] \ && bin/elasticsearch-keystore has-passwd --silentthen if ! read -s -r -p "Elasticsearch keystore password: " KEYSTORE_PASSWORD ; then echo "Failed to read keystore password on console" 1>&2 exit 1 fifi
# 确保传递正确的两个参数到JvmOptionsParserES_JAVA_OPTS=`export ES_TMPDIR; "$JAVA" "$XSHARE" -cp "$ES_CLASSPATH" org.elasticsearch.tools.launchers.JvmOptionsParser "$ES_PATH_CONF" "$ES_HOME/plugins"`
# manual parsing to find out, if process should be detachedif [[ $DAEMONIZE = false ]]; then exec \ "$JAVA" \ "$XSHARE" \ $ES_JAVA_OPTS \ -Des.path.home="$ES_HOME" \ -Des.path.conf="$ES_PATH_CONF" \ -Des.distribution.flavor="$ES_DISTRIBUTION_FLAVOR" \ -Des.distribution.type="$ES_DISTRIBUTION_TYPE" \ -Des.bundled_jdk="$ES_BUNDLED_JDK" \ -cp "$ES_CLASSPATH" \ org.elasticsearch.bootstrap.Elasticsearch \ "$@" <<<"$KEYSTORE_PASSWORD"else exec \ "$JAVA" \ "$XSHARE" \ $ES_JAVA_OPTS \ -Des.path.home="$ES_HOME" \ -Des.path.conf="$ES_PATH_CONF" \ -Des.distribution.flavor="$ES_DISTRIBUTION_FLAVOR" \ -Des.distribution.type="$ES_DISTRIBUTION_TYPE" \ -Des.bundled_jdk="$ES_BUNDLED_JDK" \ -cp "$ES_CLASSPATH" \ org.elasticsearch.bootstrap.Elasticsearch \ "$@" \ <<<"$KEYSTORE_PASSWORD" & retval=$? pid=$! [ $retval -eq 0 ] || exit $retval if [ ! -z "$ES_STARTUP_SLEEP_TIME" ]; then sleep $ES_STARTUP_SLEEP_TIME fi if ! ps -p $pid > /dev/null ; then exit 1 fi exit 0fi
exit $?

修改后,我在前台测试启动elasticsearch,elasticsearch启动后,我通过ps -ef|grep java查看了ES所使用的jdk,发现并未使用/home/esuser/jdk/bin/java,而是使用了 /home/esuser/deploy/elasticsearch-7.12.1-9300/jdk/bin/java,不符合我的要求,如下所示:

[esuser@xsky-node1 ~]$ ps -ef|grep javaesuser    8570 31437 99 16:10 pts/0    00:01:21 /home/esuser/deploy/elasticsearch-7.12.1-9300/jdk/bin/java -Xshare:auto -Des.networkaddress.cache.ttl=60 -Des.networkaddress.cache.negative.ttl=10 -XX:+AlwaysPreTouch -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true -XX:-OmitStackTraceInFastThrow -XX:+ShowCodeDetailsInExceptionMessages -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true -Dio.netty.recycler.maxCapacityPerThread=0 -Dio.netty.allocator.numDirectArenas=0 -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true -Djava.locale.providers=SPI,COMPAT --add-opens=java.base/java.io=ALL-UNNAMED -Xms8g -Xmx8g -XX:+UseG1GC -Des.networkaddress.cache.ttl=60 -Des.networkaddress.cache.negative.ttl=10 -XX:+AlwaysPreTouch -Xss1m -Djava.awt.headless=true -Dfile.encoding=UTF-8 -Djna.nosys=true -XX:-OmitStackTraceInFastThrow -Dio.netty.noUnsafe=true -Dio.netty.noKeySetOptimization=true -Dio.netty.recycler.maxCapacityPerThread=0 -Dlog4j.shutdownHookEnabled=false -Dlog4j2.disable.jmx=true -Djava.io.tmpdir=/tmp/elasticsearch-1427292610172092269 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=data -XX:ErrorFile=logs/hs_err_pid%p.log -Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m -Djava.locale.providers=COMPAT -XX:UseAVX=2 -XX:MaxDirectMemorySize=4294967296 -XX:InitiatingHeapOccupancyPercent=30 -XX:G1ReservePercent=25 -Des.path.home=/home/esuser/deploy/elasticsearch-7.12.1-9300 -Des.path.conf=/home/esuser/deploy/elasticsearch-7.12.1-9300/config -Des.distribution.flavor=default -Des.distribution.type=tar -Des.bundled_jdk=true -cp /home/esuser/deploy/elasticsearch-7.12.1-9300/lib/* org.elasticsearch.bootstrap.Elasticsearch

根据脚本分析,发现是对环境变量 ES_HOME 的误用,在 Elasticsearch 中,ES_HOME 通常用来指代 Elasticsearch 的安装目录,而不是 JDK 的安装目录。应该使用 ES_JAVA_HOME 来设置 JDK 路径。这应该是导致 JDK 路径不正确的原因。


然后我对上面脚本进行了调整,使用 ES_JAVA_HOME 来设置 JDK 路径。

并确保所有引用 JDK 的地方都使用 ES_JAVA_HOME 而非 ES_HOME。

修改后的bin/elasticsearch脚本如下:#!/bin/bash
#配置指定的JDKexport ES_JAVA_HOME=/home/esuser/OpenJDK16export PATH=$ES_JAVA_HOME/bin:$PATH
#添加对JDK判断if [ -x "$ES_JAVA_HOME/bin/java" ]; then JAVA="$ES_JAVA_HOME/bin/java"else JAVA=`which java`fi
source "`dirname "$0"`"/elasticsearch-env
CHECK_KEYSTORE=trueDAEMONIZE=falsefor option in "$@"; do case "$option" in -h|--help|-V|--version) CHECK_KEYSTORE=false ;; -d|--daemonize) DAEMONIZE=true ;; esacdone
if [ -z "$ES_TMPDIR" ]; then ES_TMPDIR=`"$JAVA" "$XSHARE" -cp "$ES_CLASSPATH" org.elasticsearch.tools.launchers.TempDirectory`fi
unset KEYSTORE_PASSWORDKEYSTORE_PASSWORD=if [[ $CHECK_KEYSTORE = true ]] \ && bin/elasticsearch-keystore has-passwd --silentthen if ! read -s -r -p "Elasticsearch keystore password: " KEYSTORE_PASSWORD ; then echo "Failed to read keystore password on console" 1>&2 exit 1 fifi
# 确保传递正确的两个参数到JvmOptionsParserES_JAVA_OPTS=`export ES_TMPDIR; "$JAVA" "$XSHARE" -cp "$ES_CLASSPATH" org.elasticsearch.tools.launchers.JvmOptionsParser "$ES_PATH_CONF" "$ES_HOME/plugins"`
# manual parsing to find out, if process should be detachedif [[ $DAEMONIZE = false ]]; then exec \ "$JAVA" \ "$XSHARE" \ $ES_JAVA_OPTS \ -Des.path.home="$ES_HOME" \ -Des.path.conf="$ES_PATH_CONF" \ -Des.distribution.flavor="$ES_DISTRIBUTION_FLAVOR" \ -Des.distribution.type="$ES_DISTRIBUTION_TYPE" \ -Des.bundled_jdk="$ES_BUNDLED_JDK" \ -cp "$ES_CLASSPATH" \ org.elasticsearch.bootstrap.Elasticsearch \ "$@" <<<"$KEYSTORE_PASSWORD"else exec \ "$JAVA" \ "$XSHARE" \ $ES_JAVA_OPTS \ -Des.path.home="$ES_HOME" \ -Des.path.conf="$ES_PATH_CONF" \ -Des.distribution.flavor="$ES_DISTRIBUTION_FLAVOR" \ -Des.distribution.type="$ES_DISTRIBUTION_TYPE" \ -Des.bundled_jdk="$ES_BUNDLED_JDK" \ -cp "$ES_CLASSPATH" \ org.elasticsearch.bootstrap.Elasticsearch \ "$@" \ <<<"$KEYSTORE_PASSWORD" & retval=$? pid=$! [ $retval -eq 0 ] || exit $retval if [ ! -z "$ES_STARTUP_SLEEP_TIME" ]; then sleep $ES_STARTUP_SLEEP_TIME fi if ! ps -p $pid > /dev/null ; then exit 1 fi exit 0fi
exit $?

修改上述脚本后,我再次前台启动elasticsearch验证测试,发现这次采用了我指定的JDK目录 /home/esuser/OpenJDK16,如下所示,红色箭头指向的是其中一个ES节点使用了指定的JDK目录,另一个节点使用了/etc/profile中配置的JAVA_HOME目录,如蓝色箭头所示。

在测试过程中,我对/home/esuser/deploy/elasticsearch-7.12.1-9300/config/下的GC参赛进行了调整,修改了如下参数:# -XX:+UseConcMarkSweepGC# -XX:CMSInitiatingOccupancyFraction=75# -XX:+UseCMSInitiatingOccupancyOnly将上述参数进行了注释,然后添加 -XX:+UseG1GC
通过如下命令 /home/esuser/OpenJDK16/bin/java -XX:+PrintFlagsFinal -version | grep Use.*GC.*=.*true,查看到的信息如下:[esuser@xsky-node1 deploy]$ /home/esuser/OpenJDK16/bin/java -XX:+PrintFlagsFinal -version | grep Use.*GC.*=.*true bool UseAdaptiveSizeDecayMajorGCCost = true {product} {default} bool UseDynamicNumberOfGCThreads = true {product} {default} bool UseG1GC = true {product} {ergonomic} bool UseGCOverheadLimit = true {product} {default} bool UseMaximumCompactionOnSystemGC = true {product} {default}openjdk version "16" 2021-03-16OpenJDK Runtime Environment AdoptOpenJDK (build 16+36)OpenJDK 64-Bit Server VM AdoptOpenJDK (build 16+36, mixed mode, sharing)

和修改前对比,显示已经使用了G1GC垃圾回收,接下来就是要在生产环境上进行验证测试。

注:JAVA_HOME在 ES 7中已经不推荐,建议使用ES_JAVA_HOME。


原文作者:尚雷的驿站;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论
现供职于某上市互联网公司担任DBA,荣获 PG ACE称号,拥有 Oracle OCM、AWS等及国产数据库等产品认证。喜欢技术分享,热爱交友,也热爱健身。

注册时间:2024-01-01

  • 博文量
    68
  • 访问量
    45423