H2O多节点集群资源分配及多应用并行作业配置问题求助
我运行着两个Docker容器,分别承载Web应用和机器学习应用,二者均使用H2O。最初我让两个应用都调用h2o.init()指向同一个IP:PORT,因此初始化了仅含一个节点的单H2O集群。
我已有一个训练完成的模型,现在正在训练第二个模型。训练过程中如果Web应用向H2O集群发起请求(例如请求用第一个模型做预测),会意外终止训练进程,报错信息如下:
错误信息
Job request failed Server error java.lang.IllegalArgumentException: Error: Job is missing Request: GET /3/Jobs/$0301c0a8f00232d4ffffffff$_911222b9c2e4404c31191c0d3ffd44c6, will retry after 3s.
我尝试给两个应用配置不同的端口,但问题依旧存在。我本以为配置两个不同端口会初始化两个独立集群,从而支持两个作业同时运行,不理解为何失败。
因此我将H2O单独部署在一个容器中,尝试搭建多节点集群让每个应用运行在独立节点上。我使用的Dockerfile和entrypoint.sh如下:
Dockerfile
######################################################################## # Dockerfile for Oracle JDK 8 on Ubuntu 16.04 ######################################################################## # pull base image FROM ubuntu:16.04 RUN \ echo 'DPkg::Post-Invoke {"/bin/rm -f /var/cache/apt/archives/*.deb || true";};' | tee /etc/apt/apt.conf.d/no-cache && \ echo "deb http://mirror.math.princeton.edu/pub/ubuntu xenial main universe" >> /etc/apt/sources.list && \ apt-get update -q -y && \ apt-get dist-upgrade -y && \ apt-get clean && \ rm -rf /var/cache/apt/* && \ DEBIAN_FRONTEND=noninteractive apt-get install -y wget unzip openjdk-8-jdk python-pip python-sklearn python-pandas python-numpy python-matplotlib software-properties-common python-software-properties && \ apt-get clean # Fetch h2o ENV H2O_RELEASE rel-zipf ENV H2O_VERSION 3.32.1.7 RUN \ wget http://h2o-release.s3.amazonaws.com/h2o/${H2O_RELEASE}/$(echo $H2O_VERSION | cut -d "." -f4)/h2o-${H2O_VERSION}.zip -O /opt/h2o.zip && \ unzip -d /opt /opt/h2o.zip && \ rm /opt/h2o.zip && \ cd /opt && \ cd `find . -name 'h2o.jar' | sed 's/.\///;s/\/h2o.jar//g'` && \ cp h2o.jar /opt && \ /usr/bin/pip install `find . -name "*.whl"` # Define the working directory WORKDIR \ /home/h2o EXPOSE 54321-54326 # Define entrypoint COPY ./bin/entrypoint.sh ./entrypoint.sh RUN chmod +x entrypoint.sh ENTRYPOINT ["./entrypoint.sh"]
entrypoint.sh
#!/bin/bash # Entrypoint script. set -e d=`dirname $0` # Use 90% of RAM for H2O, 30% for each node. memTotalKb=`cat /proc/meminfo | grep MemTotal | sed 's/MemTotal:[ \t]*//' | sed 's/ kB//'` memTotalMb=$[ $memTotalKb / 1024 ] tmp=$[ $memTotalMb * 30 ] xmxMb=$[ $tmp / 100 ] # Use all 36 cores for H2O, 12 for each node. totalCores=`lscpu | grep "^CPU(s)" | sed 's/CPU(s):[ \t]*//'` nthreads=$[ $totalCores / 3 ] # First try running java. java -version # Start 2 H2O nodes in the background nohup java -Xmx${xmxMb}m -jar /opt/h2o.jar -nthreads ${nthreads} -name ${H2O_CLUSTER_NAME} -port ${H2O_NODE_2_PORT} & nohup java -Xmx${xmxMb}m -jar /opt/h2o.jar -nthreads ${nthreads} -name ${H2O_CLUSTER_NAME} -port ${H2O_NODE_3_PORT} & # Start the 3rd node. java -Xmx${xmxMb}m -jar /opt/h2o.jar -nthreads ${nthreads} -name ${H2O_CLUSTER_NAME} -port ${H2O_NODE_1_PORT}
我共启动了3个节点(适配Web应用最多同时发起2个操作的需求),每个节点使用不同端口(端口分别为54321、54323、54325,IP相同),我配置每个节点使用总内存的30%、总CPU核心(共36核)的1/3即12核。集群可以正常启动3个节点,但不符合预期的是,每个节点识别到的核心数都是36核,总核心数显示为108,因此还是出现之前的错误。
我查阅了相关技术帖子和H2O官方文档都没有找到可行方案,请问如何配置H2O才能支持多个应用同时运行作业?
1. 解决不同端口仍共享集群的问题
你之前配置不同端口但集群依然合并,是因为H2O默认会自动发现同一网络下、集群名称相同的节点并合并集群,所以哪怕端口不同,只要-name参数指定的集群名一致,就会变成同一个集群,任务依然会冲突。
要实现两个完全隔离的独立H2O实例,除了配置不同端口,还要满足以下两个条件:
- 两个实例启动时指定完全不同的集群名称
- 加上
-no_auto_discover参数关闭节点自动发现,彻底避免跨集群合并
2. 解决CPU核心数识别错误的问题
-nthreads参数仅控制H2O作业实际使用的线程数,不会限制JVM识别到的CPU核心总数,H2O默认会读取宿主机全部核心数作为节点核心数,所以才会出现每个节点都显示36核的问题。
要限制JVM识别的CPU核心数,需要在Java启动参数中加上-XX:ActiveProcessorCount=12,强制JVM认为当前环境只有12个可用核心,H2O读取到的节点核心数就会变为12。
3. 推荐部署方案
H2O的多节点集群设计目标是加速单个大型训练任务,而非并行运行多个独立任务,你之前搭建多节点集群的思路不符合H2O的设计逻辑,优先选择两个独立单节点集群的方案:
修改后的启动命令示例:
# 启动Web应用专属H2O实例 java -Xmx${xmxMb}m -XX:ActiveProcessorCount=12 -jar /opt/h2o.jar -nthreads 12 -name h2o_web -port 54321 -no_auto_discover # 启动机器学习训练专属H2O实例 java -Xmx${xmxMb}m -XX:ActiveProcessorCount=12 -jar /opt/h2o.jar -nthreads 12 -name h2o_ml -port 54323 -no_auto_discover
两个实例完全隔离,互不干扰,不会再出现训练任务被预测请求终止的问题。
4. 备选方案:单集群开启任务队列
如果资源有限需要共用同一个集群,可以开启H2O的任务队列功能,设置h2o.task.max_concurrent=2,限制集群同时运行的任务数为2,任务会自动排队执行,不会出现前面的任务被顶掉的情况,启动参数示例:
java -Xmx90% -jar /opt/h2o.jar -name h2o_shared -port 54321 -nthreads 36 -h2o.task.max_concurrent=2
额外建议
你当前使用的H2O 3.32.1.7版本较老,存在多个任务并发调度的已知bug,建议升级到最新稳定版,可进一步降低并发冲突概率。
内容的提问来源于stack exchange,提问作者Arthur Matta

