Spark版本:1.1.1
本文系從官方文檔翻譯而來,轉載請尊重譯者的工作,注明以下鏈接:
http://www.cnblogs.com/zhangningbo/p/4135905.html
目錄
- 概述
- 不同應用程序間的資源調度
- 同一應用程序內的資源調度
- Fair調度池
- 調度池的默認行為
- 調度池的屬性配置
概述
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。
同一應用程序內的資源調度
在Spark應用程序(即SparkContext實例)內部,如果多個作業分別由單獨的線程提交,那么它們就可以同時並行執行。在本節,我們所說的“job”指的是Spark action(如save、collect等)以及需要執行該action的任何任務(task)。Spark調度器是完全線程安全的,而且支持這種特性能讓應用程序響應多個服務請求(比如為多個用戶提供查詢服務)。
默認情況下,spark調度器以FIFO方式運行作業。每個作業被分成若干個“stage”(比如map和reduce階段),同時,當第一個作業中的stage有任務(task)要啟動時,那么該作業優先獲得所有可用資源,接着是第二個作業獲得優先權,依次類推。如果隊列首位的作業不需要占用集群上的所有資源,那么后續的作業就可以立即啟動,但是如果隊列首位的作業規模很大,那么后續作業的執行會顯著地延遲。
從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)。