Spark入門篇

子清.發表於2020-11-04

第1章 Spark概述

1.1 什麼是Spark

Spark是一種基於記憶體的快速、通用、可擴充套件的大資料分析計算引擎

1.2 Spark框架

1、Hadoop MR框架

從資料來源獲取資料,經過分析計算後,將結果輸出到指定位置,核心是一次計算,不適合迭代計算。

image-20201102111430426

2、Spark框架

支援迭代式計算,圖形計算

Spark框架計算比MR快的原因是:中間結果不落盤。注意Spark的Shuffle也是落盤的。

image-20201102111505561

1.3 Spark內建模組

image-20201102111547084

Spark Core:實現了Spark的基本功能,包含任務排程、記憶體管理、錯誤恢復、與儲存系統互動等模組。Spark Core中還包含了對彈性分散式資料集(Resilient Distributed DataSet,簡稱RDD)的API定義。

Spark SQL:是Spark用來操作結構化資料的程式包。通過Spark SQL,我們可以使用 SQL或者Apache Hive版本的HQL來查詢資料。Spark SQL支援多種資料來源,比如Hive表、Parquet以及JSON等。

Spark Streaming:是Spark提供的對實時資料進行流式計算的元件。提供了用來運算元據流的API,並且與Spark Core中的 RDD API高度對應。

Spark MLlib:提供常見的機器學習功能的程式庫。包括分類、迴歸、聚類、協同過濾等,還提供了模型評估、資料 匯入等額外的支援功能。

Spark GraphX:主要用於圖形平行計算和圖挖掘系統的元件。

叢集管理器:Spark設計為可以高效地在一個計算節點到數千個計算節點之間伸縮計算。為了實現這樣的要求,同時獲得最大靈活性,Spark支援在各種叢集管理器(Cluster Manager)上執行,包括Hadoop YARN、Apache Mesos,以及Spark自帶的一個簡易排程器,叫作獨立排程器。

1.4 Spark特點

1):與Hadoop的MapReduce相比,Spark基於記憶體的運算要快100倍以上,基於硬碟的運算也要快10倍以上。Spark實現了高效的DAG執行引擎,可以通過基於記憶體來高效處理資料流。計算的中間結果是存在於記憶體中的。

2)易用:Spark支援Java、Python和Scala的API,還支援超過80種高階演算法,使使用者可以快速構建不同的應用。而且Spark支援互動式的Python和Scala的Shell,可以非常方便地在這些Shell中使用Spark叢集來驗證解決問題的方法。

3)通用:Spark提供了統一的解決方案。Spark可以用於,互動式查詢(Spark SQL)、實時流處理(Spark Streaming)、機器學習(Spark MLlib)和圖計算(GraphX)。這些不同型別的處理都可以在同一個應用中無縫使用。減少了開發和維護的人力成本和部署平臺的物力成本。

4)相容性:Spark可以非常方便地與其他的開源產品進行融合。比如,Spark可以使用Hadoop的YARN和Apache Mesos作為它的資源管理和排程器,並且可以處理所有Hadoop支援的資料,包括HDFS、HBase等。這對於已經部署Hadoop叢集的使用者特別重要,因為不需要做任何資料遷移就可以使用Spark的強大處理能力。

第2章 Spark執行模式

部署Spark叢集大體上分為兩種模式:單機模式與叢集模式
大多數分散式框架都支援單機模式,方便開發者除錯框架的執行環境。但是在生產環境中,並不會使用單機模式。因此,後續直接按照叢集模式部署Spark叢集。

下面詳細列舉了Spark目前支援的部署模式。

1)Local模式:在本地部署單個Spark服務

2)Standalone模式:Spark自帶的任務排程模式。(國內常用)

3)YARN模式:Spark使用Hadoop的YARN元件進行資源與任務排程。(國內常用)

4)Mesos模式:Spark使用Mesos平臺進行資源與任務的排程。

2.1 Spark安裝地址

下載地址:https://spark.apache.org/downloads.html

2.2 Local模式

Local模式就是執行在一臺計算機上的模式,通常就是用於在本機上練手和測試。

2.2.1 安裝使用

1)上傳並解壓Spark安裝包

tar -zxvf spark-2.4.5-bin-hadoop2.6.tgz
mv spark-2.4.5-bin-hadoop2.6 spark245

2)新增環境變數

export SPARK_HOME=/opt/spark245
export PATH=$PATH:$SPARK_HOME/bin
source /etc/profile

3)配置檔案

進入配置資料夾

cd /opt/spark245/conf/

複製一份配置檔案,並修改

 cp spark-env.sh.template spark-env.sh

在末尾新增

export JAVA_HOME=/opt/jdk1.8.0_221
export SCALA_HOME=/opt/scala
export SPARK_HOME=/opt/spark245
export SPARK_MASTER_IP=192.168.83.100
export SPARK_EXECUTOP_MEMORY=1G

再次複製

cp slaves.template slaves

在配置叢集時,需要將全部機器新增到這裡

image-20201102115849684

4)官方求PI案例

bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master local[2] \
./examples/jars/spark-examples_2.11-2.4.5.jar \
10

–class:表示要執行程式的主類;

–master local[2]

(1)local: 沒有指定執行緒數,則所有計算都執行在一個執行緒當中,沒有任何平行計算

(2)local[K]:指定使用K個Core來執行計算,比如local[2]就是執行2個Core來執行

(3)local[*]: 自動幫你按照CPU最多核來設定執行緒數。比如CPU有4核,Spark幫你自動設定4個執行緒計算。

  • spark-examples_2.11-2.4.5.jar:要執行的程式;
  • 10:要執行程式的輸入引數(計算圓周率π的次數,計算次數越多,準確率越高);

5)結果展示

該演算法是利用蒙特·卡羅演算法求PI

image-20201102120239893

2.2.2 官方WordCount案例

1)需求:讀取多個輸入檔案,統計每個單詞出現的總次數。

2)需求分析:過對單詞的分割統計進行計數

3)程式碼實現:

(1)準備檔案

mkdir input

在input下建立2個檔案1.txt和2.txt,並輸入以下內容

hello scala
hello spark
hello world
hello java
hello python

(2)啟動spark-shell

spark-shell

image-20201102121144614

注意:sc是SparkCore程式的入口;spark是SparkSQL程式入口;master = local[*]表示本地模式執行。

(3)再開啟一個hadoop001遠端連線視窗,發現了一個SparkSubmit程式

image-20201102121334468

執行任務方式說明:spark-submit,是將jar上傳到叢集,執行Spark任務;spark-shell,相當於命令列工具,本身也是一個Application。

(4)登入hadoop001:4040,檢視程式執行情況(注意:spark-shell視窗關閉掉,則hadoop001:4040頁面關閉

image-20201102121458951

說明:本地模式下,預設的排程器為FIFO。

(5)執行WordCount程式

scala> sc.textFile("/root/input").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).collect
res4: Array[(String, Int)] = Array((scala,2), (python,2), (hello,10), (java,2), (world,2), (spark,2))

注意:只有collect開始執行時,才會載入資料。

可登入hadoop001:4040檢視程式執行結果

image-20201102122729755

2.3 叢集角色

2.3.1 Master和Worker

image-20201102160009378

2.3.2 Driver和Executor

image-20201102160031889

2.3.3 通用執行流程

總結:Master和Worker是Spark的守護程式,即Spark在特定模式下正常執行所必須的程式。Driver和Executor是臨時程式,當有具體任務提交到Spark叢集才會開啟的程式。

2.4 Standalone模式

Standalone模式是Spark自帶的資源調動引擎,構建一個由Master + Slave構成的Spark叢集,Spark執行在叢集中。

這個要和Hadoop中的Standalone區別開來。這裡的Standalone是指只用Spark來搭建一個叢集,不需要藉助其他的框架。是相對於Yarn和Mesos來說的。

2.4.1 安裝使用

1)叢集規劃

hadoop001hadoop002hadoop003
SparkMasterWorkerWorkerWorker

2)再解壓一份Spark安裝包,並修改解壓後的資料夾名稱為spark-standalone

tar -zxvf spark-2.4.5-bin-hadoop2.6.tgz
mv spark-2.4.5-bin-hadoop2.6 spark-standalone

image-20201102160808380

3)進入Spark的配置目錄/opt/spark-standalone/conf

cd /opt/spark-standalone/conf/

4)修改slave檔案,新增work節點

mv slaves.template slaves
vi slaves

image-20201102164105169

5)修改spark-env.sh檔案,新增master節點

mv spark-env.sh.template spark-env.sh
vi spark-env.sh

新增

export JAVA_HOME=/opt/jdk1.8.0_221
export SCALA_HOME=/opt/scala
export SPARK_HOME=/opt/spark-standalone
export SPARK_MASTER_IP=192.168.83.101
export SPARK_MASTER_PORT=7077
export SPARK_EXECUTOP_MEMORY=1G

6)分發spark-standalone包

scp -r spark-standalone/ root@hadoop002:/opt
scp -r spark-standalone/ root@hadoop003:/opt

7)啟動spark叢集

這裡最好先取消掉之前單機配置的環境變數,不然容易產生衝突,另外不能直接start-all.sh,會與之前配置的hadoop命令衝突

sbin/start-all.sh

image-20201102164204311

注意:如果遇到 “JAVA_HOME not set” 異常,可以在sbin目錄下的spark-config.sh 檔案中加入如下配置:

export JAVA_HOME=XXXX

8)網頁檢視:192.168.83.101:8080(master web的埠,相當於hadoop的50070埠)

image-20201102164417388

9)官方求PI案例

bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://hadoop001:7077 \
./examples/jars/spark-examples_2.11-2.4.5.jar \
10

引數:–master spark://hadoop001:7077指定要連線的叢集的master

10)頁面檢視http://hadoop001:8080/,發現執行本次任務,預設採用三臺伺服器節點的總核數3核,每個節點記憶體1024M

8080:master的webUI

4040:application的webUI的埠號

image-20201102165813882

2.4.2 引數說明

1)配置Executor可用記憶體為2G,使用CPU核數為2個

bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://hadoop001:7077 \
--executor-memory 2G \
--total-executor-cores 2 \
./examples/jars/spark-examples_2.11-2.4.5.jar \
10

2)頁面檢視http://hadoop001:8080/

image-20201102170624352

3)基本語法

bin/spark-submit \
--class <main-class>
--master <master-url> \
... # other options
<application-jar> \
[application-arguments]

4)引數說明

引數解釋可選值舉例
–classSpark程式中包含主函式的類
–masterSpark程式執行的模式本地模式:local[*]、spark://hadoop001:7077、Yarn
–executor-memory 1G指定每個executor可用記憶體為1G符合叢集記憶體配置即可,具體情況具體分析。
–total-executor-cores 2指定****所有****executor使用的cpu核數為2個
application-jar打包好的應用jar,包含依賴。這個URL在叢集中全域性可見。 比如hdfs:// 共享儲存系統,如果是file:// path,那麼所有的節點的path都包含同樣的jar
application-arguments傳給main()方法的引數

2.4.3 配置歷史服務

注意埠區別!

hadoop2.7.x80209870
hadoop3.1.x900050070

由於spark-shell停止掉後,hadoop101:4040頁面就看不到歷史任務的執行情況,所以開發時都配置歷史伺服器記錄任務執行情況。

1)修改spark-default.conf.template名稱

mv spark-defaults.conf.template spark-defaults.conf

2)修改spark-default.conf檔案,配置日誌儲存路徑,並分發

vi spark-defaults.conf

image-20201102172433005

注意:需要啟動Hadoop叢集,HDFS上的目錄需要提前存在。

hadoop fs -mkdir /directory

3)修改spark-env.sh檔案,新增如下配置:

export SPARK_HISTORY_OPTS="
-Dspark.history.ui.port=18080 
-Dspark.history.fs.logDirectory=hdfs://hadoop001:9000/directory 
-Dspark.history.retainedApplications=30"

# 引數1含義:WEBUI訪問的埠號為18080

# 引數2含義:指定歷史伺服器日誌儲存路徑

# 引數3含義:指定儲存Application歷史記錄的個數,如果超過這個值,舊的應用程式資訊將被刪除,這個是記憶體中的應用數,而不是頁面上顯示的應用數。

4)分發配置檔案

scp spark-env.sh root@hadoop002:$PWD
scp spark-env.sh root@hadoop003:$PWD

5)啟動歷史服務

sbin/start-history-server.sh

image-20201103152819665

6)再次執行任務

bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://hadoop001:7077 \
--executor-memory 2G \
--total-executor-cores 2 \
./examples/jars/spark-examples_2.11-2.4.5.jar \
10

7)檢視Spark歷史服務地址:hadoop001:18080

image-20201103152201210

2.4.4 配置高可用(HA)

1)高可用原理

image-20201103152500907

2)配置高可用

(0)停止叢集

sbin/stop-all.sh

(1)Zookeeper正常安裝並啟動

https://blog.csdn.net/zmzdmx/article/details/108470867

image-20201103154850194

(2)修改spark-env.sh檔案新增如下配置:

註釋掉如下內容:
#SPARK_MASTER_HOST=hadoop001
#SPARK_MASTER_PORT=7077

新增上如下內容。配置由Zookeeper管理Master,在Zookeeper節點中自動建立/spark目錄,用於管理:
export SPARK_DAEMON_JAVA_OPTS="
-Dspark.deploy.recoveryMode=ZOOKEEPER 
-Dspark.deploy.zookeeper.url=hadoop001,hadoop002,hadoop003
-Dspark.deploy.zookeeper.dir=/spark"

新增如下程式碼
Zookeeper3.5的AdminServer預設埠是8080,和Spark的WebUI衝突
export SPARK_MASTER_WEBUI_PORT=8989

(3)分發配置檔案

scp spark-env.sh root@hadoop002:$PWD
scp spark-env.sh root@hadoop003:$PWD

(4)在hadoop001上啟動全部節點

sbin/start-all.sh

(5)在hadoop002上單獨啟動master節點

sbin/start-master.sh

image-20201103160420403

hadoop002作為備胎master,在hadoop001掛掉後開始作為master執行程式

(6)在啟動一個hadoop001視窗,將input資料上傳到hadoop叢集的/input目錄

hdfs dfs -put input/ /input

(7)Spark HA叢集訪問

bin/spark-shell \
--master spark://hadoop001:7077,hadoop002:7077 \
--executor-memory 2g \
--total-executor-cores 2

引數:–master spark://hadoop001:7077,hadoop002:7077指定要連線的叢集的master

(8)執行WordCount程式

scala> sc.textFile("hdfs://hadoop001:9000/input/input").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).collect
res1: Array[(String, Int)] = Array((scala,2), (python,2), (hello,10), (java,2), (world,2), (spark,2))

3)高可用測試

​ (1)檢視hadoop001的master程式

13280 NameNode
15904 Jps
15029 Master
13403 DataNode
14715 QuorumPeerMain
15116 Worker
14237 HistoryServer

(2)Kill掉hadoop001的master程式,頁面中觀察http://hadoop002:8080/的狀態是否切換為active。

image-20201103162012776

(3)再啟動hadoop001的master程式

sbin/start-master.sh

2.4.5 執行流程

Spark有standalone-client和standalone-cluster兩種模式,主要區別在於:Driver程式的執行節點

1)客戶端模式

bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://hadoop001:7077,hadoop002:7077 \
--executor-memory 1G \
--total-executor-cores 2 \
--deploy-mode client \
./examples/jars/spark-examples_2.11-2.4.5.jar \
10

–deploy-mode client,表示Driver程式執行在本地客戶端

image-20201103163127678

2)叢集模式模式

bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://hadoop001:7077,hadoop002:7077 \
--executor-memory 1G \
--total-executor-cores 2 \
--deploy-mode cluster \
./examples/jars/spark-examples_2.11-2.4.5.jar \
10

–deploy-mode cluster,表示Driver程式執行在叢集

image-20201103163936094

​ (1)檢視http://hadoop002:8080/頁面,點選Completed Drivers裡面的Worker

image-20201103164118762

​ (2)跳轉到Spark Worker頁面,點選Finished Drivers中Logs下面的stdout

image-20201103164203187

​ (3)最終列印結果如下

image-20201103172227818

2.5 Yarn模式(重點)

Spark客戶端直接連線Yarn,不需要額外構建Spark叢集。

2.5.1 安裝使用

0)停止Standalone模式下的spark叢集

sbin/stop-all.sh

hadoop002

sbin/stop-master.sh

1)為了防止和Standalone模式衝突,再單獨解壓一份spark

tar -zxvf spark-2.4.5-bin-hadoop2.6.tgz

2)修改名稱為spark-yarn

mv spark-2.4.5-bin-hadoop2.6 spark-yarn

3)修改hadoop配置檔案"/opt/hadoop/etc/hadoop/yarn-env.sh",新增如下內容

因為測試環境虛擬機器記憶體較少,防止執行過程進行被意外殺死,做如下配置

<!--是否啟動一個執行緒檢查每個任務正使用的實體記憶體量,如果任務超出分配值,則直接將其殺掉,預設是true -->
<property>
     <name>yarn.nodemanager.pmem-check-enabled</name>
     <value>false</value>
</property>

<!--是否啟動一個執行緒檢查每個任務正使用的虛擬記憶體量,如果任務超出分配值,則直接將其殺掉,預設是true -->
<property>
     <name>yarn.nodemanager.vmem-check-enabled</name>
     <value>false</value>
</property>

4)分發配置檔案

5)修改"/opt/spark-yarn/conf/spark-env.sh",新增YARN_CONF_DIR配置,保證後續執行任務的路徑都變成叢集路徑

 mv spark-env.sh.template spark-env.sh

新增如下內容

YARN_CONF_DIR=/opt/hadoop/etc/hadoop

image-20201103194947833

6)分發spark-yarn

7)啟動HDFS以及YARN叢集

start-all.sh

8)執行一個程式

bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
./examples/jars/spark-examples_2.11-2.4.5.jar \
10

引數:–master yarn,表示Yarn方式執行;–deploy-mod表示客戶端方式執行程式

9)如果執行的時候,丟擲如下異常

ClassNotFoundException:com.sun.jersey.api.client.config.ClientConfig

-原因分析
	Spark2中jersey版本是2.22,但是yarn中還需要依賴1.9,版本不相容
-解決方式
在yarn-site.xml中,新增
	<property>
	    <name>yarn.timeline-service.enabled</name>
		<value>false</value>
</property>	

10)檢視hadoop002:8088頁面,點選History,檢視歷史頁面image-20201103200156315

2.5.2 配置歷史服務

由於是重新解壓的Spark壓縮檔案,所以需要針對Yarn模式,再次配置一下歷史伺服器。

1)修改spark-default.conf.template名稱

mv spark-defaults.conf.template spark-defaults.conf

2)修改spark-default.conf檔案,配置日誌儲存路徑,並分發

spark.eventLog.enabled          true
spark.eventLog.dir               hdfs://hadoop001:9000/directory

3)修改spark-env.sh檔案,新增如下配置:

export SPARK_HISTORY_OPTS="
-Dspark.history.ui.port=18080 
-Dspark.history.fs.logDirectory=hdfs://hadoop001:9000/directory 
-Dspark.history.retainedApplications=30"

# 引數1含義:WEBUI訪問的埠號為18080

# 引數2含義:指定歷史伺服器日誌儲存路徑

# 引數3含義:指定儲存Application歷史記錄的個數,如果超過這個值,舊的應用程式資訊將被刪除,這個是記憶體中的應用數,而不是頁面上顯示的應用數。

4)分發配置檔案

2.5.3 配置檢視歷史日誌

為了從Yarn上關聯到Spark歷史伺服器,需要配置關聯路徑。

1)修改配置檔案"/opt/spark-yarn/conf/spark-defaults.conf"

新增如下內容:

spark.yarn.historyServer.address=hadoop001:18080
spark.history.ui.port=18080

2)同步spark-defaults.conf配置檔案

3)重啟Spark歷史服務

sbin/stop-history-server.sh
sbin/start-history-server.sh

4)提交任務到Yarn執行

bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
./examples/jars/spark-examples_2.11-2.4.5.jar \
10

5)Web頁面檢視日誌:http://hadoop002:8088/cluster

2.5.4 執行流程

Spark有yarn-client和yarn-cluster兩種模式,主要區別在於:Driver程式的執行節點

yarn-client:Driver程式執行在客戶端,適用於互動、除錯,希望立即看到app的輸出。

yarn-cluster:Driver程式執行在由ResourceManager啟動的APPMaster適用於生產環境。

1)客戶端模式(預設)

bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode client \
./examples/jars/spark-examples_2.11-2.4.5.jar \
10

image-20201104142508653

2)叢集模式

bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode cluster \
./examples/jars/spark-examples_2.11-2.4.5.jar \
10

(1)檢視http://hadoop002:8088/cluster頁面,點選History按鈕,跳轉到歷史詳情頁面

image-20201104142622864

(2)點選Executors->點選driver中的stdout

image-20201104142641728

image-20201104142656559

*可能碰到的問題:*

如果在 yarn 日誌端無法檢視到具體的日誌, 則在yarn-site.xml中新增如下配置並啟動Yarn歷史伺服器

image-20201104142733160

<property>
    <name>yarn.log.server.url</name>
    <value>http://hadoop003:19888/jobhistory/logs</value>
</property>

注意:hadoop歷史伺服器也要啟動 mr-jobhistory-daemon.sh start historyserver

image-20201104142833644

2.6 Mesos模式(瞭解)

Spark客戶端直接連線Mesos;不需要額外構建Spark叢集。國內應用比較少,更多的是運用Yarn排程。

2.7 幾種模式對比

模式Spark安裝機器數需啟動的程式所屬者
Local1Spark
Standalone3Master及WorkerSpark
Yarn1Yarn及HDFSHadoop

2.8 埠號總結

1)Spark歷史伺服器埠號:18080 (類比於Hadoop歷史伺服器埠號:19888)

2)Spark Master Web埠號:8080(類比於Hadoop的NameNode Web埠號:9870(50070))

3)Spark Master內部通訊服務埠號:7077 (類比於Hadoop的8020(9000)埠)

4)Spark檢視當前Spark-shell執行任務情況埠號:4040

5)Hadoop YARN任務執行情況檢視埠號:8088

第3章 WordCount案例實操

Spark Shell僅在測試和驗證我們的程式時使用的較多,在生產環境中,通常會在IDE中編制程式,然後打成Jar包,然後提交到叢集,最常用的是建立一個Maven專案,利用Maven來管理Jar包的依賴。

3.1 編寫程式

1)建立一個Maven專案WordCount

2)輸入資料夾準備:在新建的WordCount專案名稱上右鍵=》新建input資料夾=》在input資料夾上右鍵=》分別新建1.txt和2.txt。每個檔案裡面準備一些word單詞。

3)匯入專案依賴

<dependency>
      <groupId>org.scala-lang</groupId>
      <artifactId>scala-library</artifactId>
      <version>2.11.8</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.apache.spark/spark-sql -->
    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-sql_2.11</artifactId>
      <version>2.1.1</version>
    </dependency>


    <dependency>
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-core_2.11</artifactId>
      <version>2.1.1</version>
    </dependency>

    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>

    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.7.21</version>
    </dependency>

4)建立伴生物件WordCount,編寫程式碼

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

object WordCount {

    def main(args: Array[String]): Unit = {

        //1.建立SparkConf並設定App名稱
        val conf = new SparkConf().setAppName("WC").setMaster("local[*]")

        //2.建立SparkContext,該物件是提交Spark App的入口
        val sc: SparkContext = SparkContext.getOrCreate(conf)

        //3.讀取指定位置檔案:hello atguigu atguigu
        val lineRdd: RDD[String] = sc.textFile("input")

        //4.讀取的一行一行的資料分解成一個一個的單詞(扁平化)
        val wordRdd: RDD[String] = lineRdd.flatMap(line => line.split(" "))

        //5. 將資料轉換結構
        val wordToOneRdd: RDD[(String, Int)] = wordRdd.map(word => (word, 1))

        //6.將轉換結構後的資料進行聚合處理
        val wordToSumRdd: RDD[(String, Int)] = wordToOneRdd.reduceByKey((v1, v2) => v1 + v2)

        //7.將統計結果採集到控制檯列印
        val wordToCountArray: Array[(String, Int)] = wordToSumRdd.collect()
        wordToCountArray.foreach(println)

        //一行搞定
        //sc.textFile(args(0)).flatMap(_.split(" ")).map((_, 1)).reduceByKey(_ + _).saveAsTextFile(args(1))

        //8.關閉連線
        sc.stop()
    }
}

5)打包外掛

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
        <archive>
            <manifest>
                <mainClass>c這裡寫main函式的全類名</mainClass>
            </manifest>
        </archive>
        <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
        </descriptorRefs>
    </configuration>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
</plugin>

6)打包到叢集測試

​ (1)點選package打包,然後,檢視打完後的jar包

image-20201103234737577

image-20201103234802095

(2)將wc.jar上傳到linux目錄

(3)在HDFS上建立,儲存輸入檔案的路徑/input

hadoop fs -mkdir /input

(4)上傳輸入檔案到/input路徑

hadoop fs -put /input/1.txt /input

(5)執行任務

bin/spark-submit \
--class nj.WordCount \
--master yarn \
wc.jar \
/input \
/output

注意:input和ouput都是HDFS上的叢集路徑。

(6)查詢執行結果

hadoop fs -cat /output/*

注意:如果執行發生壓縮類沒找到,可以參考如下方案解決

https://blog.csdn.net/dkcgx/article/details/44833425

3.2 本地除錯

本地Spark程式除錯需要使用Local提交模式,即將本機當做執行環境,Master和Worker都為本機。執行時直接加斷點除錯即可。如下:

object WordCount {

    def main(args: Array[String]): Unit = {

        //1.建立SparkConf並設定App名稱,設定本地模式執行
        val conf = new SparkConf().setAppName("WC").setMaster("local[*]")

        //2.建立SparkContext,該物件是提交Spark App的入口
        val sc = new SparkContext(conf)

        //3.使用sc建立RDD,輸入和輸出路徑都是本地路徑
        sc.textFile("input").flatMap(_.split(" ")).map((_, 1)).reduceByKey(_ + _).saveAsTextFile("output")

        //4.關閉連線
        sc.stop()
    }
}

3.3 關聯原始碼

1)按住ctrl鍵,點選RDD

image-20201104142108079

2)提示下載或者繫結原始碼

image-20201104142127082

3.4 異常處理

如果本機作業系統是Windows,如果在程式中使用了Hadoop相關的東西,比如寫入檔案到HDFS,則會遇到如下異常:

image-20201104142205695

出現這個問題的原因,並不是程式的錯誤,而是用到了hadoop相關的服務,解決辦法

  1. 配置HADOOP_HOME環境變數

  2. 在IDEA中配置Run Configuration,新增HADOOP_HOME變數

相關文章