Docker部署ES服务时,canal全量同步导致内存爆炸,解决方案:自动关闭ES/Canal Adapter并降低CPU使用率

文章目录

  • 问题
  • 解决方案
  • 1. 对ES的限制
  • 2. 对Canal-Adapter的限制
  • 问题

    使用canal-adapter全量同步(参考Canal Adapter1.1.5版本API操作服务,手动同步数据(4))的时候

  • 小批量数据可以正常运行(几千条)
  • 只要数据量一大(上万条),就会内存、CPU双线爆炸,ES自动被docker关闭。
  • 数据量大的时候系统负荷如下所示(用宝塔监控)

    docker stats监控如下所示,很快其他容器全都变成--,完全无法提供服务

    解决方案

    1. 对ES的限制

    参考Docker部署ES(增加内存限制启动)

    最关键的一句话:启动的时候按照如下参数启动。必须得先设置single-node单节点模式,然后设置ES_JAVA_OPTS="-Xms64m -Xmx512m" 才会成功。

    docker run -d --name limit_es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e ES_JAVA_OPTS="-Xms64m -Xmx512m" elasticsearch:7.6.2
    

    ES_JAVA_OPTS的意思是设置ES中Java虚拟机环境的上下限

    discovery.type=single-node是单节点模式的意思。和集群有关的配置可以参考ElasticSearch 设置-配置(一)发现和集群形成设置

  • discovery.seed_hosts:提供集群中符合主节点条件的节点列表。也可以是以逗号分隔的单个字符串。每个节点都是host:port或者host格式。host是由DNS解析出来的任意主机名称。IPV6必须用方括号括起来。如果一个主机名通过DNS解析出来多个地址,ElasticSearch会使用所有被解析出来的地址。

  • discovery.seed_providers:指定种子主机提供程序的类型来获取用于启动发现进程的种子节点的地址。默认情况下,它是基于设置的种子主机提供程序,它从 discovery.seed_hosts 设置中获取种子节点地址。此设置以前称为 discovery.zen.hosts_provider。

  • discovery.type:指定 Elasticsearch 是否应形成多节点集群。默认情况下,Elasticsearch 在形成集群时会发现其他节点,并允许其他节点稍后加入集群。如果discovery.type 设置为single-node,Elasticsearch 会形成一个单节点集群并不支持cluster.publish.timeout 设置的超时。

  • cluster.initial_master_nodes:设置全新群集中符合条件的主节点的初始集。默认情况下,此列表为空,表示此节点希望加入已引导的集群。请参阅cluster.initial_master_nodes。

  • ES的内存占用显著小了很多,并且可以直接同步大批量数据

    2. 对Canal-Adapter的限制

    我在canal-adapter中也提了一个issue,并尝试自己解决

    我对docker canal-adapter内部的start.sh进行了修改,似乎好像解决了这个问题?但是只是本地部署没有看出问题,不知道线上如何。先记录一下修改方案

    以下修改方案基于slpcat/canal-adapter:v1.1.5-jdk8修改

    首先docker exec进入到容器内部,修改启动脚本vi bin/startup.sh

    我修改了两个地方

    1. if else判断的地方,我直接指定JAVA_OPTS为非x64系统的配置
    2. 修改了原先的-Xms-Xmx,变成了新的104m和512m (随便设置的,就想着要小一点),以及增加了新的参数-XX:MaxDirectMemorySize=128m
    #!/bin/bash
    
    current_path=`pwd`
    case "`uname`" in
        Linux)
                    bin_abs_path=$(readlink -f $(dirname $0))
                    ;;
            *)
                    bin_abs_path=`cd $(dirname $0); pwd`
                    ;;
    esac
    base=${bin_abs_path}/..
    export LANG=en_US.UTF-8
    export BASE=$base
    
    if [ -f $base/bin/adapter.pid ] ; then
            echo "found adapter.pid , Please run stop.sh first ,then startup.sh" 2>&2
        exit 1
    fi
    
    if [ ! -d $base/logs ] ; then
            mkdir -p $base/logs
    fi
    
    ## set java path
    if [ -z "$JAVA" ] ; then
      JAVA=$(which java)
    fi
    
    ALIBABA_JAVA="/usr/alibaba/java/bin/java"
    TAOBAO_JAVA="/opt/taobao/java/bin/java"
    if [ -z "$JAVA" ]; then
      if [ -f $ALIBABA_JAVA ] ; then
            JAVA=$ALIBABA_JAVA
      elif [ -f $TAOBAO_JAVA ] ; then
            JAVA=$TAOBAO_JAVA
      else
            echo "Cannot find a Java JDK. Please set either set JAVA or put java (>=1.5) in your PATH." 2>&2
        exit 1
      fi
    fi
    
    case "$#"
    in
    0 )
      ;;
    2 )
      if [ "$1" = "debug" ]; then
        DEBUG_PORT=$2
        DEBUG_SUSPEND="n"
        JAVA_DEBUG_OPT="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=$DEBUG_SUSPEND"
      fi
      ;;
    * )
      echo "THE PARAMETERS MUST BE TWO OR LESS.PLEASE CHECK AGAIN."
      exit;;
    esac
    
    str=`file -L $JAVA | grep 64-bit`
    if [ -n "$str" ]; then
            JAVA_OPTS="-server -Xms2048m -Xmx3072m -Xmn1024m -XX:SurvivorRatio=2 -Xss256k -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError"
    else
            JAVA_OPTS="-server -Xms1024m -Xmx1024m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:MaxPermSize=128m "
    fi
    ## 主要是修改了这个地方,修改了启动参数
    JAVA_OPTS="-server -Xms104m -Xmx512m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:MaxDirectMemorySize=128m -XX:MaxPermSize=128m "
    echo $JAVA_OPTS
    JAVA_OPTS=" $JAVA_OPTS -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true -Dfile.encoding=UTF-8"
    ADAPTER_OPTS="-DappName=canal-adapter"
    
    for i in $base/lib/*;
        do CLASSPATH=$i:"$CLASSPATH";
    done
    
    CLASSPATH="$base/conf:$CLASSPATH";
    
    echo "cd to $bin_abs_path for workaround relative path"
    cd $bin_abs_path
    
    echo CLASSPATH :$CLASSPATH
    exec $JAVA $JAVA_OPTS $JAVA_DEBUG_OPT $ADAPTER_OPTS -classpath .:$CLASSPATH com.alibaba.otter.canal.adapter.launcher.CanalAdapterApplication
    

    可以看到插入几万条数据后(确实也同步到ES中了),adapter的内存反而还下降了?不是很懂,只能说回想起了深度学习调参的日子

    物联沃分享整理
    物联沃-IOTWORD物联网 » Docker部署ES服务时,canal全量同步导致内存爆炸,解决方案:自动关闭ES/Canal Adapter并降低CPU使用率

    发表评论