1. 程式人生 > >在叢集上執行Spark

在叢集上執行Spark

在分散式環境下, Spark 叢集採用的是主 / 從結構。在一個 Spark 叢集中,有一個節點負責中央協調, 排程各個分散式工作節點。

  • 這個中央協調節點被稱為驅動器(Driver) 節點。
  • 工作節點被稱為執行器(executor) 節點。
    這裡寫圖片描述

驅動器節點

Spark 驅動器是執行你的程式中的 main() 方法的程序。它執行使用者編寫的用來建立
SparkContext、建立 RDD,以及進行 RDD 的轉化操作和行動操作的程式碼。

把使用者程式轉為任務

Spark 驅動器程式負責把使用者程式轉為多個物理執行的單元, 這些單元也被稱為任務(task)。Spark 程式其實是隱式地創建出了一個由操作組成的邏輯上的有向無環圖(Directed Acyclic Graph,簡稱 DAG)。當驅動器程式執行時,它會把這個圖轉為物理執行計劃。

Spark 會對邏輯執行計劃作一些優化,比如將連續的對映轉為流水線化執行,將多個操作合併到一個步驟中等。 這樣 Spark 就把邏輯計劃轉為一系列步驟(stage)。而每個步驟又由多個任務組成。這些任務會被打包並送到叢集中。

任務是 Spark 中最小的工單元,使用者程式通常要啟動成百上千的獨立任務。

為執行器節點排程任務

Spark 驅動器程式必須在各執行器程序間協調任務的排程。執行器程序啟動後,會向驅動器程序註冊自己。因此,驅動器程序始終對應用中所有的執行器節點有完整的記錄。

Spark 驅動器程式會根據當前的執行器節點集合, 嘗試把所有任務基於資料所在位置分配給合適的執行器程序。

執行器節點

Spark 執行器節點是一種工作程序,負責在 Spark 作業中執行任務,任務間相互獨立。Spark 應用啟動時, 執行器節點就被同時啟動,並且始終伴隨著整個 Spark 應用的生命週期而存在。

執行器的兩大作用:
1. 負責執行組成 Spark 應用的任務,並將結果返回給驅動器程序;
2. 它們通過自身的塊管理器(Block Manager)為使用者程式中要求快取的 RDD 提供記憶體式儲存。

叢集管理器

Spark 依賴於叢集管理器來啟動執行器節點,而在某些特殊情況下,也依賴叢集管理器來啟動驅動器節點。

Spark 文件中始終使用驅動器節點和執行器節點的概念來描述執行 Spark
應用的程序。

主節點(master)和工作節點(worker)的概念則被用來分別表述叢集管理器中的中心化的部分和分散式的部分。

Spark在叢集上執行的步驟

  1. 使用者通過 spark-submit 指令碼提交應用。
  2. spark-submit 指令碼啟動驅動器程式,呼叫使用者定義的 main() 方法。
  3. 驅動器程式與叢集管理器通訊,申請資源以啟動執行器節點。
  4. 叢集管理器為驅動器程式啟動執行器節點。
  5. 驅動器程序執行使用者應用中的操作。 根據程式中所定義的對 RDD 的轉化操作和行動操作,驅動器節點把工作以任務的形式傳送到執行器程序。
  6. 任務在執行器程式中進行計算並儲存結果。
  7. 如果驅動器程式的 main() 方法退出,或者呼叫了 SparkContext.stop(),驅動器程式會終止執行器程序,並且通過叢集管理器釋放資源。

Spark-submit的使用

可以使用spark-submit來提交程式執行,一個簡單的示例:

> bin/spark-submit --master spark://host:7077 --executor-memory 10g my_script.py
描述
spark://host:port 連線到指定埠的 Spark 獨立叢集上。預設情況下 Spark 獨立主節點使用7077埠
mesos://host:port 連線到指定埠的 Mesos 叢集上。預設情況下 Mesos 主節點監聽 5050 埠
yarn 連線到一個 YARN 叢集。當在 YARN 上執行時,需要設定環境變數 HADOOP_CONF_DIR 指向 Hadoop 配置目錄,以獲取叢集資訊
local 執行本地模式,使用單核
local[N] 執行本地模式,使用 N 個核心
local[*] 執行本地模式,使用盡可能多的核心

spark-submit 還提供了各種選項,主要分兩類:
1. 排程資訊,比如為作業申請資源量等
2. 執行時的依賴,比如庫和檔案

標準格式:

> bin/spark-submit [options] <app jar | python file> [app options]
  1. [options] 是要傳給 spark-submit 的標記列表,spark-submit –help 列出所有

spark-submit的一些常見標記

標記 描述
–master 表示要連線的叢集管理器
–deploy-mode 選擇在本地(客戶端“client”)啟動驅動器程式,還是在叢集中的一臺工作節點機器(叢集“cluster”)上啟動。在客戶端模式下, spark-submit 會將驅動器程式執行在spark-submit 被呼叫的這臺機器上。在叢集模式下,驅動器程式會被傳輸並執行於叢集的一個工作節點上。預設是本地模式
–class 執行 Java 或 Scala 程式時應用的主類
–name 應用的顯示名,會顯示在 Spark 的網頁使用者介面中
–jars 需要上傳並放到應用的 CLASSPATH 中的 JAR 包的列表。如果應用依賴於少量第三方的 JAR 包,可以把它們放在這個引數裡
–files 需要放到應用工作目錄中的檔案的列表。這個引數一般用來放需要分發到各節點的資料檔案
–py-files 需要新增到 PYTHONPATH 中的檔案的列表。其中可以包含 .py、 .egg 以及 .zip檔案
–executor-memory 執行器程序使用的記憶體量,以位元組為單位。可以使用字尾指定更大的單位,比如“512m”(512 MB)或“15g”(15 GB)
–driver-memory 驅動器程序使用的記憶體量,以位元組為單位。可以使用字尾指定更大的單位,比如“512m”(512 MB)或“15g”(15 GB)

打包程式碼與依賴

如果程式需要依賴第三方庫,並且該庫既不在 org.apache.spark 包內,也不屬於語言執行時的庫,則需要確保所有的依賴在該 Spark 應用執行時都能被找到。

PySpark 使用工作節點機器上已有的 Python 環境,所以可以直接使用pip安裝依賴庫。也可以使用 –py-Files 引數提交獨立的庫,這樣它們也會被新增到 Python 直譯器的路徑中。

Java 和 Scala 中使用最廣泛的構建工具是 Maven 和 sbt。它們都可以用於這兩種語言,不過 Maven 通常用於 Java 工程,而 sbt 則一般用於 Scala 工程。

Spark應用內與應用間排程

如果兩個使用者都啟動了希望使用整個叢集所有資源的應用,該如何處理呢? Spark 有一系列排程策略來保障資源不會被過度使用,還允許工作負載設定優先順序。

在排程多使用者叢集時, Spark 主要依賴叢集管理器來在 Spark 應用間共享資源。當 Spark 應用向叢集管理器申請執行器節點時, 應用收到的執行器節點個數可能比它申請的更多或者更少,這取決於叢集的可用性與爭用。

許多叢集管理器支援佇列,可以為佇列定義不同優先順序或容量限制, 這樣 Spark 就可以把作業提交到相應的佇列中。

Spark 應用有一種特殊情況, 就是那些長期執行(long lived)的應用。這意味著這些應用從不主動退出。 Spark SQL 中的 JDBC 伺服器就是一個長期執行的 Spark 應用。當 JDBC伺服器啟動後,它會從叢集管理器獲得一系列執行器節點, 然後就成為使用者提交 SQL 查詢的永久入口。

Spark 提供了一種用來配置應用內排程策略的機制。 Spark 內部的公平排程器(Fair Scheduler)會讓長期執行的應用定義排程任務的優先順序佇列。

叢集管理器介紹

Spark 可以執行在各種叢集管理器上,並通過叢集管理器訪問叢集中的機器。

如果只想在一堆機器上執行 Spark, 那麼自帶的獨立模式是部署該叢集最簡單的方法。如果你有一個需要與別的分散式應用共享的叢集(比如既可以執行 Spark 作業又可以執行Hadoop MapReduce 作業),那麼可以使用HadoopYARN 或者 Apache Mesos。

獨立叢集管理器

Spark 獨立叢集管理器提供在叢集上執行應用的簡單方法。這種叢集管理器由一個主節點和幾個工作節點組成,各自都分配有一定量的記憶體和 CPU 核心。

啟動叢集

要使用叢集啟動指令碼,需要如下步驟:
1. 將編譯好的 Spark 複製到所有機器的一個相同的目錄下,比如 /home/yourname/spark
2. 設定好從主節點機器到其他機器的 SSH 無密碼登陸
3. 編輯主節點的 conf/slaves 檔案並填上所有工作節點的主機名
4. 在主節點上執行 sbin/start-all.sh 來啟動叢集
5. 要停止叢集,在主節點上執行 sbin/stop-all.sh

提交應用

要向獨立叢集管理器提交應用, 需要把 spark://masternode:7077 作為主節點引數傳給spark-submit。

> spark-submit --master spark://masternode:7077 yourapp

要確保主機名和埠號的一致性,一個簡單的方法是從主節點的使用者介面(位於 http://masternode:8080)中直接複製貼上 URL

你可以使用 –master 引數以同樣的方式啟動 spark-shell 或 pyspark,來連線到該叢集上:

> spark-shell --master spark://masternode:7077
> pyspark --master spark://masternode:7077

注:阻礙應用執行的一個常見陷阱是為執行器程序申請的記憶體(spark-submit 的 –executor-memory 標記傳遞的值)超過了叢集所能提供的記憶體總量。

獨立叢集管理器支援兩種部署模式:
1. 在客戶端模式中(–deploy-mode client),驅動器程式會執行在你執行 spark-submit 的機器上,是 spark-submit 命令的一部分。
2. 在叢集模式下(–deploy-mode cluster),驅動器程式會作為某個工作節點上一個獨立的程序執行在獨立叢集管理器內部。它也會連線主節點來申請執行器節點。

配置資源用量

  1. 執行器程序記憶體:–executor-memory 引數來配置此項。
  2. 佔用核心總數的最大值:這是一個應用中所有執行器程序所佔用的核心總數,–total-executorcores 引數設定這個值。
  3. 分散的執行器程序:假設你有一個 20 個物理節點的叢集,每個物理節點是一個四核的機器,然後你使用–executor-memory 1G 和 –total-executor-cores 8 提交應用,這樣 Spark 就會在不同機器上啟動 8 個執行器程序, 每個 1 GB 記憶體。 可以通過設定配置屬性 spark.deploy.spreadOut 為 false 來要求 Spark 把執行器程序合併到儘量少的工作節點中。在這樣的情況下,前面那個應用就只會得到兩個執行器節點, 每個有 1 GB 記憶體和 4 個核心。這一設定會影響執行在獨立模式叢集上的所有應用,並且必須在啟動獨立叢集管理器之前設定好。

高度可用性

獨立模式能夠很好地支援工作節點的故障。如果你想讓叢集的主節點也擁有高度可用性, Spark 還支援使用 Apache ZooKeeper來維護多個備用的主節點, 並在一個主節點失敗時切換到新的主節點上。

Hadoop YARN

YARN 是在 Hadoop 2.0 中引入的叢集管理器,它可以讓多種資料處理框架執行在一個共享的資源池上, 並且通常安裝在與 Hadoop 檔案系統(簡稱 HDFS)相同的物理節點上。在這樣配置的 YARN 叢集上執行 Spark 是很有意義的,它可以讓 Spark 在儲存資料的物理節點上執行,以快速訪問 HDFS 中的資料。

> spark-submit --master yarn yourapp

有兩種將應用連線到叢集的模式:
1. 在客戶端模式下應用的驅動器程式執行在提交應用的機器上
2. 在叢集模式下, 驅動器程式也執行在一個 YARN 容器內部

配置資源用量

  1. 設定執行器節點(預設是2):–num-executors
  2. 設定每個執行器的記憶體:–executor-memory
  3. 設定每個執行器程序從 YARN 中佔用的核心數目: –executor-cores

Apache Mesos

Apache Mesos 是一個通用叢集管理器,既可以執行分析型工作負載又可以執行長期執行的服務。要在 Mesos 上使用 Spark,需要把一個 mesos:// 的URI 傳給 spark-submit:

> spark-submit --master mesos://masternode:5050 yourapp

在執行多個主節點時,你可以使用 ZooKeeper 來為 Mesos 叢集選出一個主節點。在這種情況下,應該使用 mesos://zk:// 的 URI 來指向一個 ZooKeeper 節點列表。

比如,你有三個ZooKeeper 節點(node1、 node2 和 node3),並且 ZooKeeper 分別執行在三臺機器的2181 埠上時,你應該使用如下 URI:

> mesos://zk://node1:2181/mesos,node2:2181/mesos,node3:2181/mesos

Mesos排程模式

Mesos 提供了兩種模式來在一個叢集內的執行器程序間共享資源。
1. 在“細粒度”模式(預設)中,執行器程序佔用的 CPU 核心數會在它們執行任務時動態變化,因此一臺運行了多個執行器程序的機器可以動態共享 CPU 資源。
2. 在“粗粒度”模式中, Spark 提前為每個執行器程序分配固定數量的 CPU 數目,並且在應用結束前絕不釋放這些資源。

通過 spark-submit 傳遞 –conf spark.mesos.coarse=true 來開啟粗粒度模式。

當多使用者共享的叢集執行時, 由於應用會在它們不工作時降低它們所佔用的核心數, 以允許別的使用者程式使用叢集,所以這種情況下細粒度模式顯得非常合適。然而,在細粒度模式下排程任務會帶來更多的延遲(這樣的話,一些像 SparkStreaming 這樣需要低延遲的應用就會表現很差)。

配置資源用量

  1. 設定每個執行器程序的記憶體:–executor-memory
  2. 所有執行器節點佔用的總核心數:–total-executor-cores

選擇合適的叢集管理器

  • 如果是從零開始, 可以先選擇獨立叢集管理器。獨立模式安裝起來最簡單,而且如果你只是使用 Spark 的話,獨立叢集管理器提供與其他叢集管理器完全一樣的全部功能。
  • 如果你要在使用 Spark 的同時使用其他應用,或者是要用到更豐富的資源排程功能(例如佇列),那麼 YARN 和 Mesos 都能滿足你的需求。而在這兩者中,對於大多數Hadoop 發行版來說,一般 YARN 已經預裝好了。
  • Mesos 相對於 YARN 和獨立模式的一大優點在於其細粒度共享的選項,該選項可以將類似 Spark shell 這樣的互動式應用中的不同命令分配到不同的 CPU 上。因此這對於多使用者同時執行互動式 shell 的用例更有用處。
  • 在任何時候, 最好把 Spark 執行在執行 HDFS 的節點上,這樣能快速訪問儲存。你可以自行在同樣的節點上安裝 Mesos 或獨立叢集管理器。如果使用 YARN 的話,大多數發行版已經把 YARN 和 HDFS 安裝在了一起。