Spark開發-WordCount詳細講解

Xlucas發表於2017-09-15

核心
詳細講解spark中wordcount的執行
環境
idea 2017.1.5
java 1.7
scala 2.10
spark 1.6

程式編寫

package com.xlucas

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

/**
  * Created by xlucas on 2017/9/14.
  */
object WordCount {
  def main(args: Array[String]): Unit = {
    /**
      第一步:建立spark的配置物件sparkconf,設定spark程式的執行時的配置資訊,例如說通過setMaster來設定程式
      連結spark叢集的master的URL,如果設定為local,則代表spark程式在本地執行,
     */
    val conf=new SparkConf();//建立SparkConf物件
    conf.setAppName("WordCount")//設定應用程式的名稱,在程式執行的監控介面可以看到這個名字
    //conf.setMaster("local")//此時,程式在本地執行,不需要安裝spark叢集
    //conf.setMaster("spark://192.168.18.140:7077")//指定spark執行是叢集模式 一般我們不在程式碼中指定,我們在提交的時候指定
    /*
    第二步:建立SparkContext物件,
    SparkContext是spark程式所有功能的唯一入口,無論是採用Scala,Java,Python,R等都必須有一個SparkContext
    SparkContext核心作用:初始化spark應用程式執行時候所需要的核心元件,包括DAGScheduler,TaskScheduler,SchedulerBackend
    同時還會負責Spark程式往Master註冊程式等
    SparkContext是整個spark應用程式中最為至關重要的一個物件
     */
    val sc=new SparkContext(conf)//建立SparkContext物件,通過傳入SparkContext例項來定製Spark執行的具體引數和配置資訊
    /*
    第3步:根據具體的資料來源 (HDFS,HBase,Local等)通過SparkContext來建立RDD
    RDD的建立有3種方式,外部的資料來源,根據scala集合,由其他的RDD操作
    資料會被RDD劃分成為一系列的Partitions,分配到每個Partition的資料屬於一個Task的處理範疇
     */
    //val line=sc.textFile("E://data//LICENSE.txt",1) //讀取本地的一個檔案並且設定為1個partition
      val line =sc.textFile("hdfs://192.168.18.140:9000/input/LICENSE.txt") //指定HDFS的路徑,這個也可以到時候在引數傳入
    /*
    第4步:對初始的RDD進行Transformation級別的處理,例如Map、filter等高階函式等的程式設計來進行具體的資料計算
     在對每一行的字串拆分成單個單詞
     在單詞的拆分的基礎上對每個單詞例項計算為1,也就是word=>(word,1)
     在對每個單詞例項計數為1基礎上統計每個單詞在檔案中出現的總次數
     */
    val words=line.flatMap(_.split(" "))
    val pairs=words.map(word=>(word,1))
    val wordcounts=pairs.reduceByKey(_+_)
    //wordcounts.foreach(wordNum=>println(wordNum._1+":"+wordNum._2)) 本地模式用這個列印,
    wordcounts.collect().foreach(wordNum=>println(wordNum._1+":"+wordNum._2))
    sc.stop()
  }
}

在idea裡面執行的結果, 這個是local模式
這裡寫圖片描述

在spark叢集執行的結果,這個叢集模式
通過下面命令提交

./spark-submit --class com.xlucas.WordCount --master spark://192.168.18.140:7077 /root/data/ScalaSpark.jar 

這裡寫圖片描述

執行過程遇到的錯誤和解決方法

17/09/15 23:08:22 ERROR Shell: Failed to locate the winutils binary in the hadoop binary path
java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries.
    at org.apache.hadoop.util.Shell.getQualifiedBinPath(Shell.java:355)
    at org.apache.hadoop.util.Shell.getWinUtilsPath(Shell.java:370)
    at org.apache.hadoop.util.Shell.<clinit>(Shell.java:363)
    at org.apache.hadoop.util.StringUtils.<clinit>(StringUtils.java:79)
    at org.apache.hadoop.security.Groups.parseStaticMapping(Groups.java:104)
    at org.apache.hadoop.security.Groups.<init>(Groups.java:86)
    at org.apache.hadoop.security.Groups.<init>(Groups.java:66)
    at org.apache.hadoop.security.Groups.getUserToGroupsMappingService(Groups.java:280)
    at org.apache.hadoop.security.UserGroupInformation.initialize(UserGroupInformation.java:271)
    at org.apache.hadoop.security.UserGroupInformation.ensureInitialized(UserGroupInformation.java:248)
    at org.apache.hadoop.security.UserGroupInformation.loginUserFromSubject(UserGroupInformation.java:763)
    at org.apache.hadoop.security.UserGroupInformation.getLoginUser(UserGroupInformation.java:748)
    at org.apache.hadoop.security.UserGroupInformation.getCurrentUser(UserGroupInformation.java:621)
    at org.apache.spark.util.Utils$$anonfun$getCurrentUserName$1.apply(Utils.scala:2214)
	at org.apache.spark.util.Utils$$anonfun$getCurrentUserName$1.apply(Utils.scala:2214)
    at scala.Option.getOrElse(Option.scala:120)
    at org.apache.spark.util.Utils$.getCurrentUserName(Utils.scala:2214)
    at org.apache.spark.SparkContext.<init>(SparkContext.scala:322)
    at com.xlucas.WordCount$.main(WordCount.scala:24)
    at com.xlucas.WordCount.main(WordCount.scala)

由於執行的spark是基於Hadoop編譯的,這個需要依賴Hadoop的資訊,如果是基於local模式,這個錯誤可以忽略了

Exception in thread "main" java.lang.NoSuchMethodError: scala.collection.immutable.HashSet$.empty()Lscala/collection/immutable/HashSet;
    at akka.actor.ActorCell$.<init>(ActorCell.scala:336)
    at akka.actor.ActorCell$.<clinit>(ActorCell.scala)
    at akka.actor.RootActorPath.$div(ActorPath.scala:185)
    at akka.actor.LocalActorRefProvider.<init>(ActorRefProvider.scala:465)
    at akka.remote.RemoteActorRefProvider.<init>(RemoteActorRefProvider.scala:124)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at akka.actor.ReflectiveDynamicAccess$$anonfun$createInstanceFor$2.apply(DynamicAccess.scala:78)
	at scala.util.Try$.apply(Try.scala:191)
	at akka.actor.ReflectiveDynamicAccess.createInstanceFor(DynamicAccess.scala:73)
	at akka.actor.ReflectiveDynamicAccess$$anonfun$createInstanceFor$3.apply(DynamicAccess.scala:84)
    at akka.actor.ReflectiveDynamicAccess$$anonfun$createInstanceFor$3.apply(DynamicAccess.scala:84)
    at scala.util.Success.flatMap(Try.scala:230)
    at akka.actor.ReflectiveDynamicAccess.createInstanceFor(DynamicAccess.scala:84)
    at akka.actor.ActorSystemImpl.liftedTree1$1(ActorSystem.scala:585)
    at akka.actor.ActorSystemImpl.<init>(ActorSystem.scala:578)
    at akka.actor.ActorSystem$.apply(ActorSystem.scala:142)
    at akka.actor.ActorSystem$.apply(ActorSystem.scala:119)

這個是Scala的版本不匹配的問題,我這邊剛開始用的是Scala2.11後來修改成Scala2.10就可以了

相關文章