为什么需要动态?
- Spark默认情况下粗粒度的,先分配好资源再计算。而Spark Streaming有高峰值和低峰值,但是他们需要的资源是不一样的,如果按照高峰值的角度的话,就会有大量的资源浪费。
- Spark Streaming不断的运行,对资源消耗和管理也是我们要考虑的因素。
- Spark Streaming资源动态调整的时候会面临挑战:Spark Streaming是按照Batch Duration运行的,上一次Batch Duration需要很多资源但下一次Batch Duration就不一定不需要那么多资源了,调整资源的时候还没调整完成Batch Duration运行就已经过期了。这样的调整是无意义的 场景:
- 数据量变大,资源很少
- 数据量变小,资源很多 直接源码入手: 一 , Spark Streaming资源动态申请 spark.dynamicAllocation.enabled 表示是否开启资源的动态申请
spark.dynamicAllocation.minExecutors spark.dynamicAllocation.maxExecutors spark.dynamicAllocation.initialExecutors
定时线程以固定频率来不断的扫描Executor,正在运行的Scheduler是要运行在不同的Executor中,需要动态的增加Executor或者减少Executor ,例如判断一个60秒为时间间隔的Executor一个任务都没有运行,就会把Executor删除掉。怎么会减少Executor,是因为当前应用程序中运行的Executor在Driver中会有数据结构对其保持引用,每次任务调度的时候都会循环遍历Executor的列表,然后查询列表的可用资源,根据这个类中的时钟会不断循环查看是否满足添加或者删除Executor的条件,如果满足添加或者删除的条件就触发Executor进行添加与删除。
从Spark Streaming的角度考虑,Spark Streaming要处理的动态资源调整就是Executor的资源动态调整,其最大的挑战是什么? Spark Streaming是按照BachDuration的方式运行的,可能这个BachDuration需要很多资源,下一个又不用那么多资源,当前BachDuration的资源还没有等调整完成其运行已经过期了。 二、动态控制消费速率: 实际生产环境下,动态资源分配可能要自己做好定制。 Spark Streaming的动态调整的复杂之处在于,即使在batch duration内刚做了调整,但可能本batch duration马上就会过期。 你可以考虑改变执行周期(intervalMills),来动态调整。在一个batch duration中要对数据分片,可以算一下已拥有闲置的core,如果不够,则可以申请增加Executor,从而把任务分配到新增的Executor。 也可以考量针对上一个batch duration的资源需求情况,因为峰值出现时,往往会延续在多个连续的batch duration中。考量上一个batch duration的情况,用某种算法来动态调整后续的batch duration的资源。修改Spark Streaming可以设计StreamingContext的新子类。 其实前面的动态资源分配的定制方式做起来不容易,可能仍不太合适。
Spark Streaming中已经有自动的动态控制数据流进来的速度的方式。配置项是spark.streaming.backpressure.enabled。详见论文dynamic_batching.pdf。 强烈建议设为true。