【Spark學習】Apache Spark做業調度機制

Spark版本:1.1.1html

本文系從官方文檔翻譯而來,轉載請尊重譯者的工做,註明如下連接:shell

http://www.cnblogs.com/zhangningbo/p/4135905.htmlapache

 

 

目錄


  • 概述
  • 不一樣應用程序間的資源調度
  • 同一應用程序內的資源調度
  1. Fair調度池
  2. 調度池的默認行爲
  3. 調度池的屬性配置

 

 

概述


      Spark有幾個功能用於在做業之間(譯者注:做業包含兩類:1)不一樣應用程序所執行的做業;2)同一應用程序內的不一樣做業所執行的做業。不管哪一種做業,Spark均可以完成做業之間的資源調度。)調度資源。首先,回顧一下集羣模式概述一節所講的內容,每一個Spark應用程序(SparkContext實例)都運行着一組獨立的executor進程,而應用程序之間的資源調度工做由Spark所採用的集羣管理器來提供。其次,在每一個Spark應用程序內部,若是多個做業分別是由不一樣的線程提交的,那麼,它們可能會併發執行。要是你的應用程序經過網絡提供訪問請求,那麼這種多個做業併發執行的狀況就會很常見。例如,Shark服務器就是以這種方式工做的。Spark使用fair scheduler在每一個SparkContext內部調度資源。安全

 

不一樣應用程序間的資源調度


      當Spark應用程序在集羣上執行時,它會得到一組獨立的executor JVM只用來爲本身運行任務(task)及保存數據。若是多個用戶須要共享集羣,那麼能夠經過不一樣的選項來管理資源的分配方式。這取決於集羣管理器的類型。服務器

在全部集羣管理器上均可用的最簡單的選項,就是靜態資源分區。利用這種方法,每一個應用程序均可以設置其所用資源的最大數量,並在其整個執行週期內佔有這些資源。這正是Spark在Standalone、YARN和coarse-grained Mesos模式下所採用的方案。集羣上的資源分配方式配置以下(依據不一樣的集羣類型):網絡

  • Standalone集羣模式:默認狀況下,提交給Standalone集羣的應用程序以FIFO(first in, first out)順序執行,同時,每一個應用程序都會嘗試使用全部可用的節點。你能夠經過設置屬性spark.cores.max來限制應用程序能使用的節點數目,或者,對於那些未設置該屬性的應用程序,還能夠經過設置屬性spark.deploy.defaultCores來改變默認的資源分配方式(即每一個應用使用全部可用節點)。最後,除了控制CPU核數外,每一個應用程序能夠經過屬性spark.executor.memory來控制其內存用量。
  • Mesos集羣模式:要在Mesos集羣上使用靜態資源分區,將屬性spark.mesos.coarse配置爲true便可,還能夠根據須要設置屬性spark.cores.max來限制每一個應用程序所佔用的資源,如同在Standalone集羣模式下所作的配置同樣。你還應當設置屬性spark.executor.memor來控制executor的內存佔用量。
  • YARN集羣模式:用於Spark YARN客戶端的命令行選項--num-executors控制着應用程序要在集羣上分配多少個executor來執行做業,而選項--executor-memory和--executor-cores則分別控制着每一個executor所用的內存量和CPU核數。

      在Mesos集羣上還有一個可用選項,就是動態共享CPU核數。在這種模式下,雖然每一個spark應用程序仍然有其固定且獨立的內存分配方式(由屬性spark.executor.memory設置),可是當一個應用程序沒有運行任務(task)的時候,其餘應用程序就會佔用該應用程序的CPU核來運行他們本身的任務(task)。這種模式在那些有着大量的須要間斷執行的應用程序的場合很是有用,好比,來自多個用戶的shell會話。然而,該模式也伴隨着一個風險——不可預測的延遲,由於當一個應用程序有任務執行時,它想再次得到那些CPU核可能就須要等待一些時間。要想使用這種模式,能夠簡單地用 mesos://URL而無需設置屬性spark.mesos.coarse爲true。併發

      須要注意的是以上模式中,當前尚未一個提供不一樣應用程序間的內存共享。若是你想用這種方式來共享數據,咱們推薦運行一個單服務器應用程序,讓它能夠經過查詢相同的RDD來響應多個服務請求。例如,Shark JDBC服務器就是以這種方式來作SQL查詢的。在將來的Spark版本中,內存存儲系統(如Tachyon)將提供另外一種途徑來共享RDD。oop

 

同一應用程序內的資源調度


      在Spark應用程序(即SparkContext實例)內部,若是多個做業分別由單獨的線程提交,那麼它們就能夠同時並行執行。在本節,咱們所說的「job」指的是Spark action(如save、collect等)以及須要執行該action的任何任務(task)。Spark調度器是徹底線程安全的,並且支持這種特性能讓應用程序響應多個服務請求(好比爲多個用戶提供查詢服務)。性能

      默認狀況下,spark調度器以FIFO方式運行做業。每一個做業被分紅若干個「stage」(好比map和reduce階段),同時,當第一個做業中的stage有任務(task)要啓動時,那麼該做業優先得到全部可用資源,接着是第二個做業得到優先權,依次類推。若是隊列首位的做業不須要佔用集羣上的全部資源,那麼後續的做業就能夠當即啓動,可是若是隊列首位的做業規模很大,那麼後續做業的執行會顯著地延遲。spa

      從Spark 0.8版開始,經過配置咱們就可讓各個做業公平地共享資源。在公平資源共享模式下,spark以輪轉(round robin)方式在各個做業(job)之間分配任務(task),以便全部做業都能大體平等地共享集羣資源。這就意味着,在長期做業正在運行時提交的短時間做業能夠當即得到資源並獲得良好的響應時間,而無需等待長期做業執行完畢。該模式對於多用戶環境是最佳的。

      要使能這種公平調度器(fair scheduler),能夠在配置SparkContext時簡單地將屬性spark.scheduler.mode設置爲FAIR便可:

val conf = new SparkConf().setMaster(...).setAppName(...)
conf.set("spark.scheduler.mode", "FAIR")
val sc = new SparkContext(conf)

 

Fair調度池

      fair scheduler調度器還支持把做業分組放入調度池(pool)裏,併爲每一個調度池設置不一樣的調度選項(如權重weight)。這個功能是頗有用的,例如,對於那些更重要的做業設置優先級,或者把每一個用戶的做業分別合併爲一組,不管他們各自有多少個併發做業,都讓其平等地共享資源,而不是讓每一個做業平等地共享資源。這種方法是基於Hadoop Fair Scheduler來實現的。

      無需任何干預,新提交的做業會進入默認調度池,可是做業所屬的調度池也是能夠設置的,即在提交做業的那個線程內,向SparkContext中添加本地屬性(local property)spark.scheduler.pool就能實現。方法以下:

// Assuming sc is your SparkContext variable
sc.setLocalProperty("spark.scheduler.pool", "pool1")

      設置了該本地屬性以後,此線程中提交的全部做業(在此線程中調用RDD.save,count,collect等)都將使用這個調度池名稱。這個設置是每一個線程中都有一個,便於讓一個線程以同一用戶的名義運行多個做業。若是你想清空與該線程關聯的調度池,能夠簡單地調用:

sc.setLocalProperty("spark.scheduler.pool", null)

 

調度池的默認行爲

      默認狀況下,每一個調度池都會平等地共享集羣資源(在默認調度池內的每一個做業也都是平等地共享資源) ,但在每一個調度池內,各個做業以FIFO順序運行。例如,若是你爲每一個用戶各建立一個調度池,也就意味着每一個用戶都將平等地共享集羣資源,且每一個用戶的查詢做業將按順序運行,而不是後續的查詢做業搶佔該用戶以前的查詢做業已經得到的資源。

 

調度池的屬性配置

      對於特定的調度池,其屬性也能夠經過配置文件來修改。每一個調度池都支持如下三個屬性:

  • schedulingMode:該屬性能夠設爲FIFO或FAIR,用來控制調度池內的各個做業是按照排隊順序執行(默認行爲),仍是平等地共享該調度池的資源。
  • weight:該屬性控制一個調度池與其餘調度池共享集羣資源的方式。默認狀況下,全部調度池的權重均爲1。舉例來講,若是你將某個調度池的權重設爲2,那麼,它得到的資源將是其餘調度池的兩倍。設置一個較高的權重(好比1000)還可能實現調度池之間的優先級——基本上,權重爲1000的調度池不管什麼時候有活動的做業,它都老是優先執行其任務(task)。
  • minShare:除了設定調度池的整體權重外,每一個調度池均可以設置共享資源的最小數量(如CPU核數)。在根據權重從新分發額外的資源以前,fair scheduler調度器老是嘗試去知足全部活躍調度池所需的共享資源的最小數量。所以,minShare屬性就成了確保調度池在無需設置高優先級的狀況下就能快速得到定量資源(如10個CPU核)的又一種方法。默認狀況下,每一個調度池的minShare屬性值爲0.

      調度池的屬性能夠經過建立一個XML文件(相似於conf/fairscheduler.xml.template)並在你的SparkContext中設定屬性spark.scheduler.allocation.file來配置。

conf.set("spark.scheduler.allocation.file", "/path/to/file")

      這個XML文件的格式很簡單,就是每一個調度池一個<pool>元素,該元素內部含有不一樣的子元素用於設置各個屬性。例如:

<?xml version="1.0"?>
<allocations>
  <pool name="production">
    <schedulingMode>FAIR</schedulingMode>
    <weight>1</weight>
    <minShare>2</minShare>
  </pool>
  <pool name="test">
    <schedulingMode>FIFO</schedulingMode>
    <weight>2</weight>
    <minShare>3</minShare>
  </pool>
</allocations>

 

      文件conf/fairscheduler.xml.template也能夠做爲一個完整的示例。須要注意的是任何一個未在XML文件中配置過的調度池都會簡單地設置爲默認值(即schedulingMode爲FIFO,weight爲1,minShare爲0)。

相關文章
相關標籤/搜索