Spark版本:1.1.1html
本文系從官方文檔翻譯而來,轉載請尊重譯者的工做,註明如下連接:shell
http://www.cnblogs.com/zhangningbo/p/4135905.htmlapache
Spark有幾個功能用於在做業之間(譯者注:做業包含兩類:1)不一樣應用程序所執行的做業;2)同一應用程序內的不一樣做業所執行的做業。不管哪一種做業,Spark均可以完成做業之間的資源調度。)調度資源。首先,回顧一下集羣模式概述一節所講的內容,每一個Spark應用程序(SparkContext實例)都運行着一組獨立的executor進程,而應用程序之間的資源調度工做由Spark所採用的集羣管理器來提供。其次,在每一個Spark應用程序內部,若是多個做業分別是由不一樣的線程提交的,那麼,它們可能會併發執行。要是你的應用程序經過網絡提供訪問請求,那麼這種多個做業併發執行的狀況就會很常見。例如,Shark服務器就是以這種方式工做的。Spark使用fair scheduler在每一個SparkContext內部調度資源。安全
當Spark應用程序在集羣上執行時,它會得到一組獨立的executor JVM只用來爲本身運行任務(task)及保存數據。若是多個用戶須要共享集羣,那麼能夠經過不一樣的選項來管理資源的分配方式。這取決於集羣管理器的類型。服務器
在全部集羣管理器上均可用的最簡單的選項,就是靜態資源分區。利用這種方法,每一個應用程序均可以設置其所用資源的最大數量,並在其整個執行週期內佔有這些資源。這正是Spark在Standalone、YARN和coarse-grained Mesos模式下所採用的方案。集羣上的資源分配方式配置以下(依據不一樣的集羣類型):網絡
在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 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順序運行。例如,若是你爲每一個用戶各建立一個調度池,也就意味着每一個用戶都將平等地共享集羣資源,且每一個用戶的查詢做業將按順序運行,而不是後續的查詢做業搶佔該用戶以前的查詢做業已經得到的資源。
對於特定的調度池,其屬性也能夠經過配置文件來修改。每一個調度池都支持如下三個屬性:
調度池的屬性能夠經過建立一個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)。