Spark 集羣

Spark集羣部署模式
    1.local
    2.standalone
    3.mesos
    4.yarn

Spark閉包處理  
    分區列表,function,dep Option(分區類, Pair[Key,Value]),首選位置。
    運行job時,spark將rdd打碎變換成task,每個task由一個executor執行。執行    之前,spark會進行task的閉包(closure)計算。閉包是指針對executor可見的變量和方法,以備在rdd的foreach中進行計算。閉包就是串行化後併發送給每個executor.
    
    local模式下,所有spark程序運行在同一JVM中,共享對象,counter是可以累加的。
    原因是所有executor指向的是同一個引用。

    cluster模式下,不可以,counter是閉包處理的。每個節點對driver上的counter是不可見的。只能看到自己內部串行化的counter副本。
    

Spark的應用的部署模式
    格式:   spark-submit --class xxx xx.jar --deploy-mode (client | cluster)
    --deploy-mode指定是否部署driver程序在worker節點上還是在client主機上。

    [client]
    driver運行在client主機上。client可以不在cluster中。
    
    [cluster]
    driver程序提交給spark cluster的某個worker節點來執行。
    worker是cluster中的一員。
    導出的jar需要放置到所有worker節點都可見的位置(如hdfs)纔可以。

    不論哪種方式,rdd的運算都在worker執行
    

部署模式驗證

1.啓動spark集羣

2.編寫測試類:

package com.mao.scala.scala.deployMode

import java.net.{InetAddress, Socket}

import org.apache.spark.{SparkConf, SparkContext}

object DeployModeTest {

  /**
    * 運行時將數據發送至某個服務器
    * @param str
    */
  def printInfo(str : String): Unit ={
    val ip = InetAddress.getLocalHost.getHostAddress
    val sock = new Socket("192.168.247.205", 8888)
    val out = sock.getOutputStream
    out.write((ip + " : " + str + "\r\n").getBytes)
    out.flush()
    sock.close()
  }

  def main(args: Array[String]): Unit = {
    val conf = new SparkConf()
    conf.setAppName("deploy")
    //conf.setMaster("local[4]")  //本地模式
    //conf.setMaster("spark://s201:7077")  //spark集羣模式
    conf.setMaster("yarn")    //yarn集羣模式
    val sc  = new SparkContext(conf)
    printInfo("hello world");

    val  rdd1 = sc.parallelize(1 to 10,3)
    val rdd2 = rdd1.map(e =>{
      printInfo("rdd1 map: "+e)
      e * 2
    })
    val rdd3 = rdd2.repartition(2)
    val rdd4 = rdd3.map(e =>{
      printInfo("rdd3 map: "+e)
      e
    })
    val res = rdd4.reduce((a,b)=>{
      printInfo("rdd4 reduce : "+a+","+b)
      a+b
    })
    printInfo("driver : " + res + "")
  }
}

3.打包
        jar
        對於cluster部署模式,必須要將jar放置到所有worker都能夠看到的地方纔可以,例如hdfs。

4.將jar包上傳到spark master服務器

5.提交job到spark集羣

#客戶端模式運行
spark-submit --class com.mao.scala.scala.deployMode.DeployModeTest --master  spark://s201:7077 --deploy-mode client scalaDemo-1.0-SNAPSHOT.jar

#分發jar到所有節點的相同目錄下,在spark集羣運行
spark-submit --class com.mao.scala.scala.deployMode.DeployModeTest --master  spark://s201:7077 --deploy-mode cluster scalaDemo-1.0-SNAPSHOT.jar

#上傳jar到hdfs,使用hdfs上的文件運行
hdfs dfs -put  scalaDemo-1.0-SNAPSHOT.jar /user/admin/
spark-submit --class com.mao.scala.scala.deployMode.DeployModeTest --master  spark://s201:7077 --deploy-mode cluster hdfs://s201:8020/user/admin/scalaDemo-1.0-SNAPSHOT.jar

 

spark集羣的運行方式

主要是cluster manager的區別。

    local
    [standalone]
        使用SparkMaster進程作爲管理節點.

    [mesos]
        使用mesos的master作爲管理節點。

    [yarn]
        使用hadoop的ResourceManager作爲master節點。不用spark的master.
        不需要啓動spark-master節點。也不需要。
        
        確保HADOOP_CONF_DIR和YARN_CONF_DIR環境變量指向了包含了hadoop配置文件的目錄。
        這些文件確保向hdfs寫入數據並且連接到yarn的resourcemanager.這些配置分發到yarn集羣,
        確保所有節點的配置是一致的。配置中設置的所有屬性確保所有節點都能找到。

        在yarn上運行spark應用,可以採用兩種部署模式。cluster:driver運行在appmaster進程中。
        client:driver運行在client進程中,AppMaster只用於請求資源。

        yarn模式    :--master yarn(yarn-site.xml)
        standalone    : --master spark://s2001:7077
        mesos        : --master mesos//xxx:xxx

spark job 提交到yarn 集羣

1.從hadoop/etc/hadoop 複製core-site.xml yarn-site.xml 到spark/conf

2.修改/soft/sparl/conf/spark-env.sh

export HADOOP_CONF_DIR=/soft/hadoop/etc/hadoop
export SPARK_EXECUTOR_INSTANCES=3
export SPARK_EXECUTOR_CORES=1

3.將spark的jars文件放到hdfs上(減少job運行時間)

hdfs dfs -mkdir -p /user/centos/spark/jars
hdfs dfs -put  /soft/spark/jars/*  /user/centos/spark/jars

 4.配置spark屬性文件

[/spark/conf/spark-default.conf]
spark.yarn.jars hdfs://mycluster/user/centos/spark/jars/*

 5.提交

#yarn + cluster模式(此模式與spark集羣無關)
spark-submit --class com.mao.scala.scala.deployMode.DeployModeTest --master yarn --deploy-mode cluster  hdfs://mycluster/user/admin/scalaDemo-1.0-SNAPSHOT.jar
#yarn + client 模式(此模式與spark集羣無關)
spark-submit --class com.mao.scala.scala.deployMode.DeployModeTest --master yarn --deploy-mode client scalaDemo-1.0-SNAPSHOT.jar

 yarn + client 模式異常記錄:

Exception in thread "main" org.apache.spark.SparkException: Yarn application has already ended! It might have been killed or unable to launch application master.
	at org.apache.spark.scheduler.cluster.YarnClientSchedulerBackend.waitForApplication(YarnClientSchedulerBackend.scala:89)
	at org.apache.spark.scheduler.cluster.YarnClientSchedulerBackend.start(YarnClientSchedulerBackend.scala:63)
	at org.apache.spark.scheduler.TaskSchedulerImpl.start(TaskSchedulerImpl.scala:164)
	at org.apache.spark.SparkContext.<init>(SparkContext.scala:500)
	at com.mao.scala.scala.deployMode.DeployModeTest$.main(DeployModeTest.scala:23)
	at com.mao.scala.scala.deployMode.DeployModeTest.main(DeployModeTest.scala)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.spark.deploy.JavaMainApplication.start(SparkApplication.scala:52)
	at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:894)
	at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:198)
	at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:228)
	at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:137)
	at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)

原因: 虛擬內存的實際值超過了設置的值,即虛擬內存超限,contrainer被結束,容器沒有了,肯定失敗

解決辦法:停止yarn集羣,在hadoop的yarn-site.xml文件增加如下配置,然後重啓yarn集羣

<!--以下爲解決spark-shell 以yarn client模式運行報錯問題而增加的配置,估計spark-summit也會有這個問題。2個配置只用配置一個即可解決問題,當然都配置也沒問題-->
<!--虛擬內存設置是否生效,若實際虛擬內存大於設置值 ,spark 以client模式運行可能會報錯,"Yarn application has already ended! It might have been killed or unable to l"-->
<property>
    <name>yarn.nodemanager.vmem-check-enabled</name>
    <value>false</value>
    <description>Whether virtual memory limits will be enforced for containers</description>
</property>
<!--配置虛擬內存/物理內存的值,默認爲2.1,物理內存默認應該是1g,所以虛擬內存是2.1g-->
<property>
    <name>yarn.nodemanager.vmem-pmem-ratio</name>
    <value>4</value>
    <description>Ratio between virtual memory to physical memory when setting memory limits for containers</description>
</property>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章