troubleshooting 解決yarn-cluster模式的JVM棧內存溢出問題

公司裏面你的機器節點通常都是虛擬機啊!因此yarn-client會有網絡激增的問題!Yarn-client模式能夠跑,可是Yarn-cluster模式不能跑,就是報那麼一個JVM永久代溢出的那麼一個問題!node

  1. spark-submit腳本提交spark application到ResourceManager
  2. 去ResourceManager申請啓動ApplicationMaster
  3. 通知一個NodeManager去啓動ApplicationMaster(Driver進程)
  4. ApplicationMaster去找ResourceManager申請Executor
  5. ResourceManager分配container,container表明你能啓動的Executor佔有的資源,包括內存+CPU返回已經啓動container的NodeManager的地址
  6. ApplicationMaster去找NodeManager在container裏面申請啓動Executor
  7. Executor進程會反過來去向Driver註冊上去
  8. 最後Driver接收到了Executor資源以後就能夠去進行咱們spark代碼的執行了
  9. 執行到某個action就觸發一個JOB
  10. DAGScheduler會劃分JOB爲一個個Stage
  11. TaskScheduler會劃分Stage爲一個個Task
  12. Task發送到Executor執行
  13. Driver就來進行Task的調度

        到這裏爲止,ApplicationMaster(Driver),就知道本身有哪些資源能夠用(executor)。而後就會去執行job、拆分stage、提交stage的task,進行task調度,分配到各個executor上面去執行。sql

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

  • yarn-client模式,driver運行在本地機器上的;
  • yarn-cluster模式,driver是運行在yarn集羣上某個nodemanager節點上面的。
  • yarn-client會致使本地機器負責spark做業的調度,因此網卡流量會激增;
  • yarn-cluster模式就沒有這個問題。
  • yarn-client的driver運行在本地,一般來講本地機器跟yarn集羣都不會在一個機房的,因此說性能可能不是特別好;
  • yarn-cluster模式下,driver是跟yarn集羣運行在一個機房內,性能上來講,也會好一些。

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

  • 有的時候,運行一些包含了spark sql的spark做業,可能會碰到yarn-client模式下,能夠正常提交運行;yarn-cluster模式下,多是沒法提交運行的,會報出JVM的PermGen(永久代)的內存溢出,OOM。JVM裏面的一個區域,就是會放Class裏面一些字符串常量這些東西的。
  • 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


如何解決這種問題?性能

  • 既然是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子句之內,是還能夠的。一般狀況下,不會報那個棧內存溢出。
相關文章
相關標籤/搜索