Spark提供了一种机制,使它可以根据工作负载动态调整应用程序占用的资源。这意味着,如果不再使用资源,应用程序可能会将资源返回给集群,并在稍后需要时再次请求资源。如果多个应用程序共享Spark集群中的资源,该特性尤其有用。
默认情况下禁用此功能,并在所有粗粒度集群管理器上可用,即 standalone mode, YARN mode, and Mesos coarse-grained mode.
配置和启动
使用此特性有两个要求。首先,应用程序必须设置spark.dynamicAllocation.enable为true。其次,必须在同一集群中的每个工作节点上设置一个external shuffle service ,并设置spark.shuffle.service.eanble 为true。external shuffle service的目的是在不删除由executors产生的shuffle文件的情况下删除executors(更多细节将在下面描述)。不同的集群资设置此服务的方式不同:
- standalone 启动worker的时候使用参数spark.shuffle.service.enabled=true
- Mesos coarse-grained 模式下,所有的slave 节点,启动$SPARK_HOME/sbin/start-mesos-shuffle-service.sh,并且启动任务时候使用参数spark.shuffle.service.enabled = true
- yarn模式 参考here.
spark.dynamicAllocation.* and spark.shuffle.service.* 下以及其他的一些配置是可选的,可以参考配置configurations page.
资源分配策略
在高的层次上讲,spark应该在不再使用executor的时候释放executors,在需要的时候去获取executors。由于目前没有比较权威的方法来判定是否一个要被释放的executor是否会运行一个新的task,或者是否有一个新加入的executor是否会空闲。需要一系列启发式的粗略去决定是请求还是释放executor。
请求策略
当一个具有动态分配功能的Spark应用程序有等待调度的挂起任务时,它会请求额外的executor。这一条件也就意味着现有的executors不足以同时满足所有已提交但尚未完成的任务。
spark会以轮询的方式请求executors,如果pending的task 超过时间 spark.dynamicAllocation.schedulerBacklogTimeout 秒,则会触发请求。如果以后仍然有pending的task,每隔spark.dynamicAllocation.sustainedSchedulerBacklogTimeout 秒,会再次触发。每次请求的executors的数量会成指数增长,举个例子,第一次请求是1,然后是2,4,8,以此类推。
指数增长的目标有两个:第一:一个application应该比较小心的请求executors,因为有可能很少的executors的数量就够了。第二:这与TCP慢启动的理由相呼应。其次,应用程序应该能够及时增加其资源使用,以防实际需要许多executors。
释放策略
释放executors的策略要简单得多。当执行程序空闲超过spark.dynamicAllocation.executorIdleTimeout ,Spark应用程序释放执行程序。注意,在大多数情况下,这个条件与请求条件是互斥的,如果仍然有待调度的任务,执行器就不应该空闲。
网友评论