# 測試運行 - 面向 .NET 開發者的 Spark 簡介
作者?[James McCaffrey](https://msdn.microsoft.com/zh-cn/magazine/mt149362?author=James+McCaffrey)?| 2015 年 12 月

Spark 是一種適用于大數據的開放源代碼計算框架,且越來越流行,特別是在機器學習方案中。在本文中,我將介紹如何在運行 Windows 操作系統的計算機上安裝 Spark,并將從 .NET 開發者的角度介紹 Spark 的基本功能。
了解本文所述觀點的最佳方式是查看圖 1?中的交互會話演示。從采用管理模式運行的 Windows 命令行界面中,我通過發出 spark-shell 命令,創建了 Spark 環境。
?
圖 1:Spark 的運作方式
spark-shell 命令會創建在 shell 中運行的 Scala 解釋器,進而發出 Scala 提示 (scala>)。Scala 是一種基于 Java 的腳本語言。我們還可以通過其他方法與 Spark 交互,但最常用的方法還是使用 Scala 解釋器,原因之一是 Spark 框架主要通過 Scala 進行編寫。您還可以使用 Python 語言命令或編寫 Java 程序,與 Spark 進行交互。
請注意圖 1?中的多條警告消息。當您運行 Spark 時,這些消息很常見,因為 Spark 有許多可選組件會生成警告(如果未找到的話)。通常情況下,對于簡單方案,可以忽略警告消息。
演示會話中輸入的第一個命令是:
~~~
scala> val f = sc.textFile("README.md")
~~~
這可以大致理解為:“將 README.md 文件的內容存儲到名為 f 的不可變 RDD 對象中。” Scala 對象可聲明為 val 或 var。聲明為 val 的對象不可變且無法更改。
Scala 解釋器內置名為 sc 的 Spark 上下文對象,用于使用 Spark 功能。textFile 函數將文本文件的內容加載到名為“彈性分布數據集 (RDD)”的 Spark 數據結構中。RDD 是 Spark 中主要使用的編程抽象。您可以將 RDD 看成是存儲在多臺計算機的 RAM 上的 .NET 集合。
文本文件 README.md(.md 擴展名代表 markdown 文檔)位于 Spark 根目錄“C:\spark_1_4_1”中。如果您的目標文件位于其他位置,則您可以提供完整路徑(如“C:\\Data\\ReadMeToo.txt”)。
演示會話中輸入的第二個命令是:
~~~
scala> val ff = f.filter(line => line.contains("Spark"))
~~~
這可以理解為:“僅將對象 f 中含有‘Spark’一詞的多行內容存儲到名為 ff 的不可變 RDD 對象中。” 篩選器函數接受所謂的閉合。您可以將閉合看成是匿名函數。在這里,閉合接受名為 line 的虛擬字符串輸入參數,并在 line 中含有“Spark”時返回 true(反之,則會返回 false)。
由于“line”僅僅是參數名稱,因此我可以在閉合中使用其他任何名稱,例如:
~~~
ln => ln.contains("Spark")
~~~
由于 Spark 區分大小寫,因此以下命令會生成錯誤:
~~~
ln => ln.Contains("Spark")
~~~
Scala 具有一些函數編程語言特征,所以可以撰寫多個命令。例如,前兩個命令可以合并成一個命令:
~~~
val ff = sc.textFile("README.md").filter(line => lne.contains("Spark"))
~~~
演示會話中最后輸入的三個命令是:
~~~
scala> val ct = ff.count()
scala> println(ct)
scala> :q
~~~
計數函數返回 RDD 中的項目數,在此示例中,即返回 README.md 文件中包含 Spark 一詞的行數。行數有 19 行。若要退出 Spark Scala 會話,您可以鍵入 :q 命令。
## 在 Windows 計算機上安裝 Spark
在 Windows 計算機上安裝 Spark 主要分為四步。第一步,安裝 Java 開發工具包 (JDK) 和 Java Runtime Environment (JRE)。第二步,安裝 Scala 語言。第三步,安裝 Spark 框架。第四步,配置主機系統變量。
Spark 分發的格式為壓縮的 .tar,因此您需要使用實用工具解壓 Spark 文件。我建議您在開始前先安裝開放源代碼的 7-Zip 程序。
盡管并不是所有 Windows 操作系統版本都正式支持 Spark 及其組件,但我已經在運行 Windows 7、8、10、Server 2008 和 2012 的計算機上成功安裝了 Spark。圖 1?中的演示就是在 Windows 8.1 計算機上運行。
您可以運行自解壓可執行文件(通過 Internet 搜索即可找到)來安裝 JDK。我使用的版本是 jdk-8u60-windows-x64.exe。
如果您安裝的是 64 位版本 JDK,則默認安裝目錄是 C:\Program Files\Java\jdkx.x.x_xx\(如圖 2?所示)。我建議您不要更改默認位置。
?
圖 2:默認 JDK 位置
安裝 JDK 的同時也會安裝相關的 JRE。安裝完成后,默認的 Java 父目錄會同時包含 JDK 目錄和相關的 JRE 目錄(如圖 3?所示)。
?
圖 3:安裝至 C:\Program Files\Java\ 的 Java JDK 和 JRE
請注意,您的計算機上可能有一個 Java 目錄,其中包含的一個或多個 32 位 JRE 目錄位于 C:\Program Files (x86) 中。計算機上同時包含 32 位和 64 位版本的 JRE 是沒有問題的,但我建議您僅使用 64 位版本的 Java JDK。
## 安裝 Scala
下一步是安裝 Scala 語言,但在安裝前,您必須先前往 Spark 下載站點(本文的下一部分將予以介紹),然后確定要安裝的 Scala 版本。Scala 版本必須與您將在下一步中安裝的 Spark 版本兼容。
很遺憾,關于 Scala-Spark 版本兼容性的信息非常少。當我安裝 Spark 組件時(距離您閱讀本文已過去相當一段時間),Spark 的當前版本是 1.5.0,但我找不到任何信息可說明哪個 Scala 版本與此版本的 Spark 兼容。因此,我以舊版 Spark ( 1.4.1) 為目標,在開發者討論網站上找到了一些信息,這些信息表明第 2.10.4 版 Scala 可能與第 1.4.1 版 Spark 兼容。
安裝 Scala 很容易。安裝流程僅涉及運行 .msi 安裝程序文件。
Scala 安裝向導會逐步指導您完成整個流程。有趣的是,Scala 的默認安裝目錄位于 32 位目錄 C:\Program Files (x86)\ 中,而不是位于 64 位目錄 C:\Program Files\ 中(請參閱圖 4)。
?
圖 4:Scala 安裝至 C:\Program Files (x86)\scala\
如果您打算通過編寫 Java 程序(而不是使用 Scala 命令)與 Spark 交互,您需要另外安裝一項名為 Scala Simple Build Tool (SBT) 的工具。通過編譯的 Java 程序與 Spark 進行交互比使用交互 Scala 困難得多。
## 安裝 Spark
下一步是安裝 Spark 框架。不過,首先,請確保您擁有可解壓 .tar 格式文件的實用工具(如 7-Zip)。Spark 安裝流程需手動操作,即您需要將壓縮文件夾下載到本地計算機中,解壓壓縮文件,然后將文件復制到根目錄中。也就是說,如果您希望卸載 Spark,只需刪除 Spark 文件即可。
Spark 站點網址為 spark.apache.org。在下載頁上,您可以選擇版本和包類型。Spark 是一種計算框架,需要使用分布式文件系統 (DFS)。迄今為止,Spark 框架最常用的 DFS 是 Hadoop 分布式文件系統 (HDFS)。出于測試和實驗目的(如圖 1?中的演示會話),您可以在沒有 DFS 的系統上安裝 Spark。在這種情況下,Spark 會使用本地文件系統。
如果您之前沒有解壓過 .tar 文件,則可能會對這個過程感到些許困惑,因為您通常需要解壓兩次。首先,將 .tar 文件(我的文件命名為 spark-1.4.1-bin-hadoop2.6.tar)下載到任意臨時目錄(我使用的是 C:\Temp)。接下來,右鍵單擊 .tar 文件,然后從上下文菜單中選擇“解壓文件”,將它解壓到臨時目錄內的新目錄。
首次解壓過程會新建一個不含文件擴展名的壓縮文件(我的是 spark-1.4.1-bin-hadoop2.6)。接下來,右鍵單擊這個新建的文件,然后從上下文菜單中再次選擇“解壓文件”,將它解壓到其他目錄。第二次解壓會生成 Spark 框架文件。
為 Spark 框架文件創建一個目錄。通用約定是創建名為 C:\spark_x_x_x 的目錄,其中 x 值表示版本。根據此約定,我創建了 C:\spark_1_4_1 目錄,并將解壓的文件復制到此目錄中(如圖 5?所示)。

圖 5:手動將解壓的 Spark 文件復制到 C:\spark_x_x_x\
## 配置計算機
在安裝 Java、Scala 和 Spark 之后,最后一步是配置主機。此過程涉及下載 Windows 所需的特殊實用工具文件、設置三個用戶定義的系統環境變量、設置系統 Path 變量,以及視需要選擇修改 Spark 配置文件。
若要在 Windows 上運行 Spark,本地目錄(名為 C:\hadoop)中必須有特殊的實用工具文件(名為 winutils.exe)。通過 Internet 搜索,您可以在多處找到此文件。我創建了目錄 C:\hadoop,然后在[http://public-repo-1.hortonworks.com/hdp-win-alpha/winutils.exe](http://http/public-repo-1.hortonworks.com/hdp-win-alpha/winutils.exe)?找到了 winutils.exe 的副本,并將此文件下載到所創建的目錄中。
接下來,創建和設置三個用戶定義的系統環境變量,并修改系統 Path 變量。轉到“控制面板 | 系統 | 高級系統設置 | 高級 | 環境變量”。在“用戶變量”部分中,新建三個具有下列名稱和值的變量:
~~~
JAVA_HOME???? C:\Program Files\Java\jdk1.8.0_60
SCALA_HOME??? C:\Program Files (x86)\scala
HADOOP_HOME?? C:\hadoop
~~~
然后,在“系統變量”中,添加 Spark 二進制文件的位置 (C:\spark_1_4_1\bin),編輯 Path 變量。請謹慎操作,您一定不想在 Path 變量中丟失任何值。請注意,Scala 安裝進程已經為您添加了 Scala 二進制文件的位置(請參閱圖 6)。

圖 6:配置系統
在您設置系統變量后,我建議您修改 Spark 配置文件。轉到根目錄 C:\spark_1_4_1\config,然后復制 log4j.properties.template 文件。通過刪除 .template 擴展名來重命名此副本。編輯 log4j.rootCategory=INFO 和 log4j.rootCategory=WARN 之間的第一個配置條目。
即,默認情況下,Spark 會發出各種各樣的信息性消息。將日志記錄級別從 INFO 更改為 WARN 會大大地減少消息的數量,并且可以方便您更有條不紊地與 Spark 交互。
## Spark 的 Hello World 示例
分布式計算示例 Hello World 旨在計算數據源中的不同字詞數量。圖 7?展示了使用 Spark 的字數統計示例。

圖 7:使用 Spark 的字數統計示例
Scala shell 有時被稱為讀取、求值、打印、循環 (REPL) shell。您可以按 CTRL+L 來清除 Scala REPL。如上文所解釋,圖 7?中的第一個命令將 README.md 文件的內容加載到名為 f 的 RDD 中。在實際情況中,您的數據源可以是跨數百臺計算機分布的大型文件,也可以位于分布式數據庫(如 Cassandra)中。
下一個命令是:
~~~
scala> val fm = f.flatMap(line => line.split(" "))
~~~
flatMap 函數調用在空白空格字符處對 f RDD 對象中的每一行進行拆分,生成的 RDD 對象 fm 會包含一個集合,其中有文件中的所有字詞。從開發者的角度來看,您可以將 fm 看成是 .NET List 集合。
下一個命令是:
~~~
scala> val m = fm.map(word => (word, 1))
~~~
映射函數會創建一個保留項目對的 RDD 對象,其中每對都包含一個字詞和整數值 1。如果您發出 m.take(5) 命令,則可以看得更清楚。您會看到 README.md 文件中的前五個字詞,以及每個字詞旁邊的值 1。從開發者的角度來看,m 大致是一個 List 集合,其中每個 Pair 對象都包含一個字符串和一個整數。字符串(README.md 中的一個字詞)是鍵,而整數則是值,但與 Microsoft .NET Framework 中的許多鍵值對不同的是,Spark 中允許重復的鍵值。保留鍵值對的 RDD 對象有時被稱為 RDD 對,以便于與普通的 RDD 區分開來。
下一個命令是:
~~~
scala> val cts = m.reduceByKey((a,b) => a + b)
~~~
reduceByKey 函數通過添加與相等鍵值相關聯的整數值,在對象 m 中合并各個項目。如果您運行 cts.take(10),則會看到 README.md 中的 10 個字詞,后跟每個字詞在此文件中的出現次數。您可能還會注意到,對象 cts 中的字詞并沒有特定的排列順序。
reduceByKey 函數接受閉合。您可以使用替代的 Scala 快捷符號:
~~~
scala> val cts = m.reduceByKey(_ + _)
~~~
下劃線是參數通配符,所以語法可以解析為“添加任意兩個收到的值”。
請注意,此字數統計示例先使用映射函數,然后使用 reduceByKey 函數。這就是 MapReduce 范例。
下一個命令是:
~~~
scala> val sorted =
???? cts.sortBy(item => item._2, false)
~~~
此命令根據項目的第二個值(整數計數),對 cts RDD 中的項目進行排序。自變量 false 表示按降序排序,即從最高計數到最低計數。排序命令的 Scala 快捷語法形式是:
~~~
scala> val sorted = cts.sortBy(_._2, false)
~~~
因為 Scala 具有很多函數語言特征,并且使用很多符號(而不是關鍵字),因此編寫的 Scala 代碼會非常不直觀。
Hello World 示例中的最后一個命令用于顯示結果:
~~~
scala> sorted.take(5).foreach(println)
~~~
可解釋為:“提取名為 sorted 的 RDD 對象中的前五個對象,并對此集合進行循環訪問,同時對每個項目應用 println 函數。” 結果是:
~~~
(,66)
(the,21)
(Spark,14)
(to,14)
(for,11)
~~~
也就是說,README.md 中出現了 66 次空/null 字詞,“the”一詞出現了 21 次,“Spark”一詞出現了 14 次等。
## 總結
如果您想在 Windows 計算機上試用 Spark,請參閱本文,其中提供的信息旨在幫助您快速掌握如何開始使用和運行 Spark。Spark 是一項相對較新的技術(2009 年始于加州大學柏克萊分校),但在過去的幾個月中,對 Spark 感興趣的人明顯增多,至少我的同事們就非常感興趣。
在 2014 年的大數據處理框架爭奪戰中,Spark 創造了新的性能記錄,很輕松地就打破了 Hadoop 系統在前一年創造的記錄。Spark 具有出色的性能,因此非常適合與機器學習系統結合使用。Spark 支持名為 MLib 的機器學習算法開放源代碼庫。
* * *
Dr.James McCaffrey?*供職于華盛頓地區雷蒙德市沃什灣的 Microsoft Research。他參與過多個 Microsoft 產品的工作,包括 Internet Explorer 和 Bing。Scripto可通過?[jammc@microsoft.com](mailto:jammc@microsoft.com)?與 McCaffrey 取得聯系。*
- 介紹
- Visual Studio - 用于 Web 開發的新式工具: Grunt 和 Gulp
- 新員工 - 放長錢釣大魚
- Microsoft Azure - Azure Service Fabric 和微服務體系結構
- 數據點 - Aurelia 與 DocumentDB 結合: 結合之旅(第 2 部分)
- 游戲開發 - Babylon.js: 構建 Web 基本游戲
- 測試運行 - 面向 .NET 開發者的 Spark 簡介
- Xamarin - 使用 Xamarin.Forms 構建跨平臺用戶體驗
- 孜孜不倦的程序員 - 如何成為 MEAN: 快速輸入
- Microsoft Azure - Azure、Web API 和 Redis 如何有助于加快數據交付
- 必備 .NET - 設計 C# 7
- 新式應用 - 需要了解的 Windows 10 應用開發概念
- 別讓我打開話匣子 - 重構高等教育
- 編者注 - 再見 Kenny