在 YARN 上配置 Spark

哈布爾,你好! 昨天 專門討論 Apache Spark 的聚會來自 Rambler&Co 的人員,參與者提出了許多與配置此工具相關的問題。 我們決定跟隨祂的腳步並分享我們的經驗。 這個主題並不容易——所以我們邀請您在評論中分享您的經驗,也許我們也理解和使用了一些錯誤的地方。

簡單介紹一下我們如何使用 Spark。 我們有一個為期三個月的計劃 “大數據專家”,在整個第二個模組中,我們的參與者都在使用該工具。 因此,作為組織者,我們的任務是準備集群以供在這種情況下使用。

我們使用的特殊性在於,同時在 Spark 上工作的人數可以等於整個小組。 例如,在研討會上,每個人同時嘗試某件事並跟著老師重複。 這並不是很多——有時最多 40 人。 世界上可能沒有多少公司面臨這樣的用例。

接下來,我將告訴您我們如何以及為什麼選擇某些配置參數。

讓我們從頭開始。 Spark 有 3 個選項可以在叢集上運行:獨立、使用 Mesos 和使用 YARN。 我們決定選擇第三個選項,因為它對我們來說很有意義。 我們已經有一個hadoop叢集了。 我們的參與者已經非常熟悉它的架構。 讓我們使用紗線。

spark.master=yarn

進一步更有趣。 這 3 個部署選項中的每一個都有 2 個部署選項:客戶端和叢集。 基於 文件 以及互聯網上的各種鏈接,我們可以得出結論,客戶端適合互動式工作——例如透過jupyter筆記本,而集群更適合生產解決方案。 就我們而言,我們對互動式工作感興趣,因此:

spark.deploy-mode=client

一般來說,從現在開始,Spark 將以某種方式在 YARN 上工作,但這對我們來說還不夠。 由於我們有一個關於大數據的項目,有時參與者沒有在均勻分配資源的框架內獲得足夠的資訊。 然後我們發現了一個有趣的事情——動態資源分配。 簡而言之,重點是:如果您有一項艱鉅的任務,並且叢集空閒(例如,早上),那麼使用 Spark 這個選項可以為您提供額外的資源。 必要性是根據一個狡猾的公式計算出來的。 我們不會詳細介紹 - 它運作良好。

spark.dynamicAllocation.enabled=true

我們設定了這個參數,啟動時Spark就崩潰了,沒有啟動。 沒錯,因為我必須讀它 文件 更仔細地。 它指出,為了讓一切正常,您還需要啟用一個附加參數。

spark.shuffle.service.enabled=true

為什麼需要它? 當我們的工作不再需要這麼多資源時,Spark 應該將它們歸還給公共池。 幾乎所有 MapReduce 任務中最耗時的階段都是 Shuffle 階段。 此參數可讓您儲存此階段產生的資料並相應地釋放執行器。 而executor就是在worker上計算一切的進程。 它具有一定數量的處理器核心和一定數量的記憶體。

已新增此參數。 一切似乎都很順利。 值得注意的是,參與者實際上在需要時獲得了更多資源。 但另一個問題出現了——在某個時候其他參與者醒來也想使用 Spark,但那裡一切都很忙,他們不高興。 他們是可以理解的。 我們開始查看文檔。 事實證明,還有許多其他參數可以用來影響這個過程。 例如,如果執行器處於待機模式,那麼什麼時間後可以從中取出資源?

spark.dynamicAllocation.executorIdleTimeout=120s

在我們的例子中,如果你的執行者在兩分鐘內沒有做任何事情,那麼請將它們放回公共池中。 但這個參數並不總是足夠的。 很明顯,這個人已經很久沒有做任何事情了,資源也沒有被釋放。 原來,還有一個特殊的參數-在什麼時間之後選擇包含快取資料的執行器。 預設情況下,此參數為無窮大! 我們糾正了它。

spark.dynamicAllocation.cachedExecutorIdleTimeout=600s

也就是說,如果你的執行者在 5 分鐘內沒有做任何事情,就把它們交給公共池。 在這種模式下,大量使用者的資源釋放和發放速度變得不俗。 不滿情緒減少。 但我們決定更進一步,限制每個應用程式的最大執行者數量 - 本質上是每個程式參與者。

spark.dynamicAllocation.maxExecutors=19

當然,現在另一邊也有人不滿意——“集群閒置了,我只有19個執行者”,但你能做什麼呢?我們需要某種正確的平衡。 你不可能讓每個人都開心。

還有一個與我們案例的具體情況相關的小故事。 不知何故,有幾個人上實踐課遲到了,而且由於某種原因 Spark 沒有為他們開始。 我們查看了免費資源的數量 - 似乎就在那裡。 Spark 應該會啟動。 幸運的是,那時文件已經新增到子皮質的某個地方,我們記得啟動時,Spark 會尋找要啟動的連接埠。 如果該範圍內的第一個連接埠繁忙,它將按順序移動到下一個連接埠。 如果它是免費的,它就會捕獲。 並且有一個參數指示最大嘗試次數。 預設是16人,這個數字比我們班上課的人數少。 於是,試了16次後,Spark放棄了,說我無法啟動。 我們已更正此設定。

spark.port.maxRetries=50

接下來我會告訴你一些與我們案例的具體情況不太相關的設定。

為了更快地啟動 Spark,建議將 SPARK_HOME 主目錄中的 jars 資料夾存檔並將其放在 HDFS 上。 這樣他就不會浪費時間讓工人裝載這些jarniks。

spark.yarn.archive=hdfs:///tmp/spark-archive.zip

也建議使用 kryo 作為序列化器以實現更快的操作。 它比預設的更優化。

spark.serializer=org.apache.spark.serializer.KryoSerializer

Spark 還有一個長期存在的問題,就是經常從記憶體中崩潰。 這種情況通常發生在工作人員計算完所有內容並將結果發送給司機的時刻。 我們自己把這個參數調大了。 預設是1GB,我們設為3。

spark.driver.maxResultSize=3072

最後,作為甜點。 如何在 HortonWorks 發行版 - HDP 2.1 上將 Spark 更新至版本 2.5.3.0。 這個版本的 HDP 包含預先安裝的 2.0 版本,但我們曾經自己決定 Spark 正在非常積極地開發,每個新版本都會修復一些錯誤並提供額外的功能,包括針對 python API 的功能,所以我們決定,需要什麼完成是更新。

從官方網站下載了Hadoop 2.7的版本。 解壓縮並放入HDP資料夾中。 我們根據需要安裝了符號連結。 我們啟動它 - 它沒有啟動。 寫了一個很奇怪的錯誤。

java.lang.NoClassDefFoundError: com/sun/jersey/api/client/config/ClientConfig

經過谷歌,我們發現Spark決定不再等到Hadoop誕生,而決定使用新版的球衣。 他們自己在 JIRA 中就這個主題互相爭論。 解決辦法是下載 球衣版本1.17.1。 將其放入 SPARK_HOME 的 jars 資料夾中,再次壓縮並上傳到 HDFS。

我們解決了這個錯誤,但又出現了一個新的、相當精簡的錯誤。

org.apache.spark.SparkException: Yarn application has already ended! It might have been killed or unable to launch application master

同時,我們嘗試運行2.0版本——一切正常。 嘗試猜測發生了什麼事。 我們查看了該應用程式的日誌並看到了類似以下內容:

/usr/hdp/${hdp.version}/hadoop/lib/hadoop-lzo-0.6.0.${hdp.version}.jar

一般來說,由於某種原因 hdp.version 沒有解析。 經過谷歌搜索,我們找到了解決方案。 您需要前往 Ambari 中的 YARN 設定並將參數新增至自訂紗線站點:

hdp.version=2.5.3.0-37

這個魔法起了作用,Spark 起飛了。 我們測試了幾台 jupyter 筆記型電腦。 一切正常。 我們已經準備好週六(明天)的第一節 Spark 課程了!

UPD。 上課的時候,又發現了一個問題。 在某個時候,YARN 停止為 Spark 提供容器。 在 YARN 中,需要修正參數,預設為 0.2:

yarn.scheduler.capacity.maximum-am-resource-percent=0.8

即只有20%的資源參與了資源的分配。 更改參數後,我們重新載入 YARN。 問題已解決,其餘參與者也能夠運行 Spark 上下文。

來源: www.habr.com

添加評論