2015年9月30日 星期三

使用Scale IDE with Eclipse 開發第一個Spark JAVA程式

隨著前一篇練習我們可以利用 Maven 直接建立出一個簡單的呼叫Spark API的範例程式
但是往往不容易知道萬一程式內容有誤怎辦?(直接在Eclipse用Maven不在此限)
這邊簡單介紹使用Scale IDE 整合了 Eclipse 來建立第一支JAVA範例程式

首先至 Scale IDE Download 下載最新的 Scala IDE,之後解壓縮後會出現Eclipse的目錄
點擊2下後,建立一個新的專案(Java Project)名為SparkTestApp後,如圖
接著我們在 eclipse complier時需要使用到 spark-assembly-1.5.0.hadoop2.6.0.jar
該檔案是會在您安裝Spark的 /lib路徑下(隨著安裝版本的不同檔名也不同)

由於我之前 Spark 環境 跟 Windows Eclipse環境是分開安裝的,所以一樣利用WinSCP工具將在Linux環境下的 spark-assembly-1.5.0.hadoop2.6.0.jar 複製至 Windows環境

複製完畢後在剛才建立的Project 專案名稱按右鍵-->properties-->Java Bulid Path-->add External jars-->選擇你剛才複製的jar檔

 現在我們可以建立 java class 了
在src按右鍵建立 class 取名為 SimpleApp.java
程式碼如下:
/* SimpleApp.java */
import org.apache.spark.api.java.*;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.function.Function;

public class SimpleApp {
  public static void main(String[] args) {
    String logFile = "/opt/SparkLogFile.log"; // Should be some file on your system
    SparkConf conf = new SparkConf().setAppName("Simple Application");
    JavaSparkContext sc = new JavaSparkContext(conf);
    JavaRDD<String> logData = sc.textFile(logFile).cache();

    long numAs = logData.filter(new Function<String, Boolean>() {
      public Boolean call(String s) { return s.contains("a"); }
    }).count();

    long numBs = logData.filter(new Function<String, Boolean>() {
      public Boolean call(String s) { return s.contains("b"); }
    }).count();

    System.out.println("Lines with a: " + numAs + ", lines with b: " + numBs + " version 2.0");
  }
}

程式碼與之前相同,接著我們在專案名稱按右鍵-->Export 
選擇 Export JAR file
取名 SimpleAppV2
按下 Finish 後 ,至你建立專案的 WorkSpace下取得 SimpleAppV2.jar
同上一個範例將其檔案複製至 Spark Linux 環境下
執行命令 
#spark-submit --class "SimpleApp" SimpleAppV2.jar
執行結果如下:


恭喜剛才在Eclipse建立的範例程式也可成功運行嘍!






2015年9月29日 星期二

Using Spark API with Java and Maven-使用 Maven 建置 java application 呼叫 Spark API

Spark Shell 本來就提供了 2種 shell 模式,一種是 scala 另一種是 python
雖然 Spark本身也支援 Java開發,但是要使用 java lib 則需用 scala or python call java library
這個練習目的是 單純使用 java 語法呼叫 Spark API 利用 Maven build jar
之後使用 spark-submit 來執行程式

首先當然需要安裝 Maven,我是將 Maven 安裝在我的 Windows環境(可對外),原因是我的Spark環境不可連網, Maven請至 這裡 Download , 因為 Maven build jar 會利用到 JDK 所以也請您事先安裝好 JDK 版本,都安裝好後請使用 mvn --version 來確認是否安裝完成

這邊建議您的JDK版本不要太新,我先前使用了1.8.0.51的版本,發現我使用 mvn package時會失敗,而且記得設定 JAVA_HOME至環境變數
待會我們將在Windows環境利用 Maven 建置 java jar,之後利用 WinSCP將檔案傳至 Spark Linux 環境後執行程式

首先我在桌面建置了名為Spark的目錄,接著再建立了一個名為 java_source的目錄,此時使用記事本建立一個檔名為 pom.xml 的檔案(maven 建置時所使用的檔案)
檔案內容如下:

<project>
  <groupId>edu.berkeley</groupId>
  <artifactId>simple-project</artifactId>
  <modelVersion>4.0.0</modelVersion>
  <name>Simple Project</name>
  <packaging>jar</packaging>
  <version>1.0</version>
  <dependencies>
    <dependency> <!-- Spark dependency -->
      <groupId>org.apache.spark</groupId>
      <artifactId>spark-core_2.10</artifactId>
      <version>1.5.1</version>
    </dependency>
  </dependencies>
</project>

然後依目錄結構 依序建立了 3個目錄 /src,/src/main,/src/main/java
在最後的java目錄下建立了一個檔案名為 SimpleApp.java
檔案內容如下:
/* SimpleApp.java */
import org.apache.spark.api.java.*;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.function.Function;

public class SimpleApp {
  public static void main(String[] args) {
    String logFile = "/opt/SparkLogFile.log"; // Should be some file on your system
    SparkConf conf = new SparkConf().setAppName("Simple Application");
    JavaSparkContext sc = new JavaSparkContext(conf);
    JavaRDD<String> logData = sc.textFile(logFile).cache();

    long numAs = logData.filter(new Function<String, Boolean>() {
      public Boolean call(String s) { return s.contains("a"); }
    }).count();

    long numBs = logData.filter(new Function<String, Boolean>() {
      public Boolean call(String s) { return s.contains("b"); }
    }).count();

    System.out.println("Lines with a: " + numAs + ", lines with b: " + numBs);
  }
}

注意一下內容 /opt/SparkLogFile.log 是我在 Linux 環境所要測試的資料目錄,請記得修改成您的檔案路徑,此程式主要是調用 Spark API 並計算文件中包含字母"a"和"b"的行數各有幾行

接著請在命令提示字元,至java_source目錄下(pom.xml所在)執行指令  mvn package
結果如下
這時會發現與 src同一層的目錄中出現了一個名為  target 的目錄點連去就有建立好的 simple-project-1.0.jar了,該檔案就是待會要在 Spark 環境中執行的 jar 檔


接著請該檔案複製至 Spark Linux環境(我是使用WinSCP工具)
我將該檔案複製至我在Linux上已事先建立的目錄/install_source/java_source下
在執行 Spark-submit之前,如果您還記得程式內容的話,我們必須指定一個file讓Spark來分析
因此我們必須依照程式所設定的路徑/opt下建立一個名為 SparkLogFile.log,我的範例內容如下
如果您上述工作都沒問題的話,就可以執行 spark-submit嘍! 本來應該要至你安裝Spark的bin目錄下執行指令,但是參考前面文章我們已經先將執行目錄設在 Path 了
於是 執行指令看看吧! (請切換至jar所在目錄)
#spark-submit --class simpleApp simple-project-1.0.jar
結果如下圖
#還記得嗎?先前的文章已經在spark-env.sh中預設了我們要執行的instance為2個,所以假設您的環境想run在4個instance下的話,可執行(記得至 spark-env.sh將 worker-instance mark掉,除非您之前尚未預設)
#spark-submit --class simpleApp  --master local[4] simple-project-1.0.jar

我的環境執行結果如下

你會發現計算結果已經出現 在 SparkLogFile.log中 含有"a"的有9行,"b"的只有1行

恭喜成功嘍XD







2015年9月25日 星期五

Spark on Oracle RedHat5.8 Standalone cluster running 第一支程式

這次Spark的環境是在RedHat5.8,至Apache_Spark1.50_Hadoop2.6 download pre-built的版本
相關的建置請參考 Spark 離線安裝 on Ubuntu 只是這次是使用 RedHat環境 與 JDK版本為x64的
JDK download網址在 JAVA Download
需要的工作如下
(1)Set JAVA_HOME and Config Spark PATH
跟 Ubuntu一樣需要做,但是編輯不同檔案 請使用 vi ~/.bashrc,內容如下圖
(2)
在啟動 standalone cluster之前我發生了一件神奇的事,我把 Hostname改名成 Spark_RedHat58
修改的方式請參考 設定RedHat hostname,其它執行的步驟如前一篇教學 Spark Standalone Cluster
但是我的 Slave 卻一直無法 connect spark://Spark_RedHat58:7077 一直出現 invalid master uri
直至我把 Hostname改成 RedHat58才行,(Linux Hostname 無法support 底線)估計有可能是該cmd的 bug,因為在uri中出現2次 Spark的關係
#################################################################################
假定已經可以順利啟動了,那麼你的Master WebUI(理論上是8080 port,詳見logs)應該可以順利的觀察到你的worker了(如圖)
我在conf/spark_env.sh 設定為 instance 為 2
(3)
執行cmd  Master=spark://RedHat58:7077 spark-shell
(4)執行以下範例程式碼
/* throwing darts and examining coordinates */
val NUM_SAMPLES = 100000
val count = sc.parallelize(1 to NUM_SAMPLES).map{i =>
  val x = Math.random * 2 - 1
  val y = Math.random * 2 - 1
  if (x * x + y * y < 1) 1.0 else 0.0
}.reduce(_ + _)

println("Pi is roughly " + 4 * count / NUM_SAMPLES)

成功畫面如下
這其實就跟執行範例程式是一樣的喔! 此時回到你的WebUI你會發現,Running Application 的項目裡面已經有東西嘍^^" ,如果想了解更多可以切換到  4040 port 觀察更 detail的內容喔!




2015年9月23日 星期三

Spark Standalone Cluster 練習

承接上次架設的Spark環境,這次想試試 Spark Cluster, Spark Cluster事實上有分3種模式,但我目前只有單機,所以選擇了了Standalone的方式,以下就是這次的練習。
This is reference link
http://mbonaci.github.io/mbo-spark/

首先找到上次安裝Spark的目錄,是在usr/lib下



接著進入到/sbin的目錄下,因為執行的指令是放在這裡,而不是bin喔

執行指令 ./start-master.sh
接著根據上面的訊息,我們去打開 log file看看
你可以試著在瀏覽器打開會發現如下你會發現已經啟動了一個WebUI在port 8081 (我8080有tomcat)
請注意畫面上7077 port是 sparkMaster的 service port跟WebUI的port是不同的
接著理論上我們應該回到/sbin下執行 ./start-slave.sh指令
但是 我們接著要先做2件事
(1)為了要讓 Master可以管理到 slave,必須透過 ssh-keygen 來達到 trust
(2)假設每次要啟動 slave 都要執行一次執行,那要4台的話就得執行4次有點麻煩,因為可透過config一個檔案後,只需執行1次就可以產生4台 slave

步驟(1)
由於需要使用ssh,所以事先得先安裝好openssh,執行指令 ssh-keygen後
再執行 ssh-copy-id 將檔案複製你的本機下(username@localhost name),如圖
(2)至 /conf目錄下執行 cp spark-env.sh.template spark-env.sh 指令
將範例設定檔複製並更改檔名為 spark-env.sh,這個檔案一般來說執行 spark指令後會先來找此檔案的設定,接著新增一個設定至該檔案執行export SPARK_WORKER_INSTANCES=4指令 如圖



自己可以試著 cat 看看 是否已將設定配置好在 spark-env.sh

########################################################
完成上述的前置作業後,我們可以回到/sbin下準備執行 ./start-slave 指令了,執行該指令必須指定一個 Spark-master service的位置,所以我們執行如下圖
此時回到剛才 master 的 WebUI 重新整理一下 看是否已經可以 monitor到 slave了
#注意一下 剛才指令是使用 ubuntu-i386-2 而不是使用 localhost或是IP,是因為剛才 keygen我是指定這個名稱,這個很重要,否則master會無法看到上面的畫面

#恭喜,此時已經成功建置了一個 Standalone cluster




2015年9月15日 星期二

Spark on Ubuntu 離線安裝(第一次就上手)

日前老闆告訴我客戶有Big Data的需求,想使用Spark...
於是乎我就開始了我第一個學習的旅程
首先 由於客戶的環境是封閉的 也就是說我想安裝的軟體都必須「離線」安裝
參考了一些教學 發現大多數的作業系統是採用 Ubuntu
所以我使用 Ubuntu15.04版,以下是安裝的幾個重點我是使用VM的方式
我自己的電腦是Windows

1.安裝OS的過程中,會出現請你config network,這邊可以先設定好你的static ip,gateway等等

這樣系統啟動的時候你就已經設定好ip了
如果不幸的你略過了這些設定或者設定錯了,你可以參考下面網址
Ubuntu網路設定 或是 Red Hat網路設定 這2個網站的主要是打開2個檔案更改設定
更改完使用 sudo /etc/init.d/networking restart 指令 重新啟動網路服務 就會吃到設定
#如果不幸仍未能成功請重啟OS看看
1.1Ubuntu安裝至後面會請你選要安裝的軟體,請把 OpenSSH勾選安裝起來,如果有需要FTP也可裝,主要是我們需要使用OpenSSH連線及傳送檔案

2.至Spark官網 download 較新的Spark ,Type選 per-built的版本,可以省時間

3.由於 Spark需要使用到JDK,所以可至Download JAVA官方download至自己的電腦(Windows)
#其實OS裝完裡面已有內建的OpenJDK了,但習慣上還是Oracle的據說Complier比較不易出錯
4.使用你的root user登入Ubuntu後建立一個目錄放我們要傳過去的檔案(Spark&JDK),我使用
#傳送檔案我是使用WinSCP工具(可自己搜尋download)

以下是我的一連串的指令


cd /
sudo mkdir install_source
cd install_source
# tar -zxvf spark-1.4.0-bin-hadoop2.6.tgz
# sudo mv spark-1.4.0-bin-hadoop2.6 /usr/lib
tar -zxvf jre1.8.0_60.gz
# sudo mv jre_1.80_60 /usr/lib
# vi /etc/bash.bashrc

最後重新連線

試著
# echo $JAVA_HOME
# java -version
如果不幸的 home是正常的但version仍是採用內建的OpenSDK

最後試著執行 #Spark-shell 看是否可正常啟動 Spark
啟動後如下圖

恭喜至此你已經安裝成功了

既然已經安裝成功,於是我們想要試著執行第一支範例程式
首先我們先離開spark-shell採用指令
# exit
接著執行指令
#run-example SparkPi 4
如下圖會出現Spark內建的範例程式,計算圓周率以及啟動一個WebUI在4040 port



至於真正的範例程式在
/usr/lib/spark-1.4.0-bin-hadoop2.6/examples/src/main/scala/org/apache/spark/examples
路徑下 檔案 SparkPi.scala
有興趣的可以 vi 一下,觀察裡面的 code你會發現 Spark的寫法比起 Hadoop寫法精簡許多喔!

恭喜你已經完成了第一個 Spark 範例程式的執行嘍^^