前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住给大家分享一下。点击跳转到网站:https://www.captainai.net/dongkelun
前言
平时工作中主要用 YARN 模式,最近进行TPC测试用到了 Standalone 模式,便记录总结一下 Standalone 集群相关的配置。
集群管理类型
Spark 支持三种集群管理类型:
- Standalone - Spark附带的一个简单的集群管理器,可以轻松地设置集群。
- Apache Mesos - 一个通用的集群管理器,也可以运行HadoopMapReduce和服务应用程序。(已弃用)
- Hadoop YARN - Hadoop 3中的资源管理器。
- Kubernetes - 一个用于自动化容器化应用程序的部署、扩展和管理的开源系统。
官方文档:https://spark.apache.org/docs/latest/cluster-overview.html
官方文档
https://spark.apache.org/docs/latest/spark-standalone.html
安装包
因为TPC不支持 Spark3 ,所以用的 Spark2.4.8
https://archive.apache.org/dist/spark/spark-2.4.8/spark-2.4.8-bin-hadoop2.7.tgz
安装目录
解压到 /opt/spark2
配置
记录主要配置
slaves
配置Worker节点
1 | indata-192-168-1-1.indata.com |
spark-env.sh
1 | export JAVA_HOME=/usr/local/jdk |
start-slave.sh
修改 start-slave.sh,将1
--webui-port "$WEBUI_PORT" $PORT_FLAG $PORT_NUM $MASTER "$@"
改为1
--webui-port "$WEBUI_PORT" $PORT_FLAG $PORT_NUM $MASTER -h "${HOST_NAME}"
这样修改的原因是默认情况下读取HDFS时数据本地性(Locality Level)都是 Any。原因是Spark 中 Worker Id和Address中都使用的IP地址作为Worker的标识,而HDFS集群中一般都以hostname作为slave的标识,这样,Spark从 HDFS中获取文件的保存位置对应的是hostname,而Spark自己的Worker标识为IP地址,两者不同,因此没有将任务的Locality Level标记为NODE_LOCAL,而是ANY。
历史服务 HistoryServer
官方文档:https://spark.apache.org/docs/latest/monitoring.html
开启历史服务,可以通过UI界面监控分析已经跑完的历史任务,便于我们分析及时发现和解决性能瓶颈。(在性能测试时,我们可以先开启历史服务,当调到最优参数时,可以先把历史服务相关的配置关掉,这样也许可以提升些许性能。)
在 spark-defaults.conf 中配置
客户端(Spark应用程序)1
2spark.eventLog.dir hdfs:///spark-history/
spark.eventLog.enabled true
通过上面的两个配置,运行Spark 程序时会将UI中显示的信息进行编码然后持久化存储中,存储路径为 hdfs:///spark-history/
服务端
1 | # 只需要这一个参数即可正常使用,需要和客户端路径一致,其他参数属于调优,根据实际情况配置 |
需要提前创建文件夹 hdfs:///spark-history/
环境变量
1 | vi /etc/profile.d/spark.sh |
传输到其他节点
配置完成后将整个 spark 文件夹传输到其他节点相同目录下,保证每个节点配置相同
启动
1 | sbin/start-all.sh |
Spark master和 history server可以在不同节点。比如master的默认端口是8080,而我配置history server的端口也是8080。这是因为我们环境做了端口限制,只开放了有限的几个端口。这样利用不同节点的8080端口既可以访问master UI也可以访问 history server UI。
停止
1 | sbin/stop-all.sh |
UI 界面
UI 默认端口及其对应配置参考官网:https://spark.apache.org/docs/latest/security.html
Spark Master
Spark master UI界面 默认端口 8080,可以通过 SPARK_MASTER_WEBUI_PORT (spark-env.sh) 和 spark.master.ui.port (spark-defaults.conf)修改,其中 spark.master.ui.port 优先级最高,具体逻辑在源码:org.apache.spark.deploy.master.MasterArguments
这里对比一下上面说的数据本地性
默认启动脚本:
Worker Id和Address中都使用的IP地址作为Worker的标识
造数阶段是正常的PROCESS_LOCAL
但是读取HDFS数据阶段都是ANY
修改启动脚本后:
Worker Id和Address中改为使用hostname作为Worker的标识
读取HDFS数据时改为正常的PROCESS_LOCAL
Spark Worker
默认端口 8081,可以通过 SPARK_WORKER_WEBUI_PORT (spark-env.sh) 和 spark.worker.ui.port (spark-defaults.conf)修改,其中 spark.worker.ui.port 优先级最高,具体逻辑在源码: org.apache.spark.deploy.worker.WorkerArguments
Application
默认 4040,可以通过 spark.ui.port 修改
Spark History Server
默认端口 18080,可以通过 spark.history.ui.port 修改。(在spark-env.sh 中通过 SPARK_HISTORY_OPTS 配置,在spark-defaults.conf 配置不生效)
Standalone 对比 YARN
优点
- 1、提交时间短,在TPC测试打榜时差几秒差距就很大。
- 2、可以单独配置每个节点的CPU核数和内存大小,比较灵活。比如对于HDFS NAME NODE 节点,可能HDFS用的 CPU 和 内存相比其他节点要多,这样剩余可用资源就会少一些。我们可以单独修改对应节点上的 spark-env.sh 。比如将内存改为360G: export SPARK_WORKER_MEMORY=360G。因为我们集群配置比较充足,有22个节点,每个节点的内存有512G,分给Spark的只有400G(仅示例,非实际测试配置;测试数据量只有1T,远小于集群总内存),剩下100G给HDFS足够了, 所以不用单独配置。而对于资源不充足的集群,这样配置也许能提升性能。
不同
通过参数 spark.executor.instances 或者 --num-executors
来配置程序的 executor 的数量是不管用的。Standalone 模式下 executor的数量 是看 CPU 和 内存哪个先到上限决定的,也就是默认情况下,根据先进先出顺序,尝试使用集群所有可用的资源。
executor_num = min(SPARK_WORKER_MEMORY/spark.executor.memory, SPARK_WORKER_CORES/spark.executor.cores)。另外可以通过 spark.cores.max 配置程序的最大cpu数,即 executor_num = spark.cores.max/spark.executor.cores,严格说 executor_num = min(SPARK_WORKER_MEMORY/spark.executor.memory, min(SPARK_WORKER_CORES, spark.cores.max)/spark.executor.cores)。还可以通过 spark.deploy.defaultCores 来设置没有配置 spark.cores.max 的应用程序的默认值。
缺点
不支持kerberos认证等。
TPC测试结果
恭喜我们团队(InspurCloud Data Cloud Platform)在 TPCx-HS 1T 测评 中取得第一名的好成绩,后面还会继续进行 TPCx-BB 和 TPCx-HS 3T 的测评打榜。