如果使用SparkThrfitServer结合Hive来做即席查询,那么会遇到这样的问题,一个数据量很大的查询SQL把所有的资源全占了,导致后面的SQL都等待,尽管在等待的SQL只需要1秒就能完成,这种情况肯定是你不想看到的。
Spark默认的调度策略为FIFO,即先进先出,只要是我先来,那么必须等我执行完后,你才能执行。如下图,前面提交了一个需要几千个资源的任务在执行,后面提交的只需要22个资源的任务就得一直等。
如果你解决过Hadoop的多用户资源分配问题,那么肯定对FAIR(公平调度器)不陌生,Spark为了解决多用户的这种问题,也提供了FAIR的调度策略。
本文介绍如何在SparkThriftServer&Beeline&JDBC中配置和使用该策略。
如果你知道FAIR,那么肯定对fairscheduler.xml 配置文件不陌生。
cd $SPARK_HOME/conf
cp fairscheduler.xml.template fairscheduler.xml
vi fairscheduler.xml
<allocations> <pool name="pool1"> <schedulingMode>FAIR</schedulingMode> <weight>5</weight> <minShare>3</minShare> </pool> </allocations>
在fairscheduler.xml 中,配置添加了一个资源池pool1,其中,
schedulingMode 指定为FAIR;
weight 相当于资源池权重,默认为1,这里指定了5,表示这个资源池可以比默认资源池多获得5倍的资源;
minShare 给每个调度池指定一个最小的shares值(也就是CPU的核数目)。公平调度器通过权重重新分配资源之前总是试图满足所有活动调度池的最小share。在没有给定一个高优先级的其他集群中,minShare属性是另外的一种方式来确保调度池能够迅速的获得一定数量的资源(例如10核CPU),默认情况下,每个调度池的minShare值都为0
配置了资源池,还需要在spark-defaults.conf 中指定下面两个参数:
spark.scheduler.mode FAIR
spark.scheduler.allocation.file /opt/spark/current/conf/fairscheduler.xml
配置好了,启动SparkThriftServer(On Yarn):
cd $SPARK_HOME/sbin ./start-thriftserver.sh --master yarn --conf spark.driver.memory=3G --executor-memory 1G --num-executors 10 --hiveconf hive.server2.thrift.port=10003
启动后,会在WEB界面看到资源池配置:
使用beeline链接,先提交那个大的SQL:
可以看到,该任务被提交到默认资源池(default)中。
另外启动一个beeline,连接后,先指定资源池pool1:
SET spark.sql.thriftserver.scheduler.pool=pool1;
然后,再提交小的SQL。
可以看到,小的SQL被提交到pool1中,因为pool1的优先级高,因此它能优先被执行。
JDBC中同样可以先指定资源池,再执行SQL:
Statement stmt = con.createStatement(); stmt.execute("SET spark.sql.thriftserver.scheduler.pool=pool1"); String sql = "select count(1) from xxx"; ResultSet res = stmt.executeQuery(sql);
当然,你可以在fairscheduler.xml 中多配置几个资源池,设置不同的优先级,供用户使用。
但是,Spark的公平调度器资源池,使用时候只能显示的指定,无法像Hadoop那样,根据用户、用户组来自动选择资源池,当然,你可以修改源码,比如:根据需要的executor数量,少的,就让它到优先级高的资源池很快执行完,多的,就让它到优先级低的资源池慢慢执行。
以上,希望对大家在实际使用中有所帮助。
如果觉得本博客对您有帮助,请 赞助作者 。