天天看點

(四十)troubleshooting之解決yarn-cluster模式的JVM記憶體溢出無法執行問題

(四十)troubleshooting之解決yarn-cluster模式的JVM記憶體溢出無法執行問題

總結一下yarn-client和yarn-cluster模式的不同之處:

  1. yarn-client模式,driver運作在本地機器上的; yarn-cluster模式,driver是運作在yarn叢集上某個nodemanager節點上面的。
  2. yarn-client會導緻本地機器負責spark作業的排程,是以網卡流量會激增;yarn-cluster模式就沒有這個問題。
  3. yarn-client的driver運作在本地,通常來說本地機器跟yarn叢集都不會在一個機房的,是以說性能可能不是特别好;yarn-cluster模式下,driver是跟yarn叢集運作在一個機房内,性能上來說,也會好一些。

實踐經驗,碰到的yarn-cluster的問題:

有的時候,運作一些包含了spark sql的spark作業,可能會碰到yarn-client模式下,可以正常送出運作;
yarn-cluster模式下,可能是無法送出運作的,會報出JVM的PermGen(永久代)的記憶體溢出,OOM。
           
  • yarn-client模式下,driver是運作在本地機器上的,spark使用的JVM的PermGen的配置,是本地的spark-class檔案(spark用戶端是預設有配置的),JVM的永久代的大小是128M,這個是沒有問題的;
  • yarn-cluster模式下,driver是運作在yarn叢集的某個節點上的,使用的是沒有經過配置的預設設定(PermGen永久代大小),82M。

spark-sql,它的内部是要進行很複雜的SQL的語義解析、文法樹的轉換等等,特别複雜,在這種複雜的情況下,如果說你的sql本身特别複雜的話,很可能會比較導緻性能的消耗,記憶體的消耗。可能對PermGen永久代的占用會比較大。

是以,此時,如果對永久代的占用需求,超過了82M的話,但是呢又在128M以内;就會出現如上所述的問題,yarn-client模式下,預設是128M,這個還能運作;如果在yarn-cluster模式下,預設是82M,就有問題了。會報出PermGen Out of Memory error log。

如何解決這種問題?

既然是JVM的PermGen永久代記憶體溢出,那麼就是記憶體不夠用。咱們呢,就給yarn-cluster模式下的,driver的PermGen多設定一些。

spark-submit腳本中,加入以下配置即可:

–conf spark.driver.extraJavaOptions="-XX:PermSize=128M -XX:MaxPermSize=256M"

這個就設定了driver永久代的大小,預設是128M,最大是256M。那麼,這樣的話,就可以基本保證你的spark作業不會出現上述的yarn-cluster模式導緻的永久代記憶體溢出的問題。

spark sql,sql,要注意,一個問題

sql,有大量的or語句。比如where keywords='' or keywords='' or keywords=''
當達到or語句,有成百上千的時候,此時可能就會出現一個driver端的jvm stack overflow,JVM棧記憶體溢出的問題
           

JVM棧記憶體溢出,基本上就是由于調用的方法層級過多,因為産生了大量的,非常深的,超出了JVM棧深度限制的,遞歸。遞歸方法。我們的猜測,spark sql,有大量or語句的時候,spark sql内部源碼中,在解析sql,比如轉換成文法樹,或者進行執行計劃的生成的時候,對or的處理是遞歸。or特别多的話,就會發生大量的遞歸。

JVM Stack Memory Overflow,棧記憶體溢出。

這種時候,建議不要搞那麼複雜的spark sql語句。采用替代方案:将一條sql語句,拆解成多條sql語句來執行。每條sql語句,就隻有100個or子句以内;一條一條SQL語句來執行。根據生産環境經驗的測試,一條sql語句,100個or子句以内,是還可以的。通常情況下,不會報那個棧記憶體溢出。

繼續閱讀