Oozie 調用 Spark on Yarn:傻瓜教程從編譯,配置安裝到運行

安裝前準備:

安裝hadoop,可參考文章:https://blog.csdn.net/lucylove3943/article/details/80589422

安裝spark,可參考文章:https://blog.csdn.net/lucylove3943/article/details/96477861

我當前電腦安裝的hadoop版本是2.9.2,spark的版本是2.4.4,和上面博客中稍有不同,不過安裝配置方法很類似,可直接參考。

安裝Maven,Mysql,可參考這篇oozie安裝文章:https://blog.csdn.net/lucylove3943/article/details/80673962

Mysql建立數據庫啥的,在上篇文章都有,這裏就直接使用了。

其實整體上這篇文章和上一篇oozie安裝文章類似,只是oozie對spark2的支持有點不一樣,對於spark的jar包和配置要額外弄。

所以仔細看的話,兩篇文章有很多一模一樣的內容。

 

如果oozie在使用過程中,Mysql報時區錯誤可以可參考這篇文章解決:https://blog.csdn.net/lucylove3943/article/details/80994379

下載編譯oozie需要的包:

        我看到網上很多下載都需要積分,我打包了所有我自己單獨下載的包,傳了一份到百度網盤。

        鏈接: https://pan.baidu.com/s/1BImAWQeWIyrPjiiLupE6OQ 密碼: 1m7p

        這裏面一共有5個包,其中mysql-connector-java-8.0.11.jar和ext-2.2.zip是之後oozie要用到的,之後再說怎麼用。

        另外三個包:網上有人建議把這三個包放在maven裏面,後面oozie才能編譯成功。我也不太確定我是否真的用上了,不過爲了以防萬一,我就這麼辦了。簡單來說,就是把這三個包放在目錄:apache-maven-3.5.3/lib/目錄下。

 

 

我的Cluster配置

一共7臺電腦,兩個機架:

機架一:dragon-1, dragon-2, dragon-3, dragon-4, dragon-5

機架二:cat-5, cat-7

Hadoop安裝版本爲2.9.2,設置dragon-1爲namenode和resource manager

Spark安裝版本是2.4.4,由於我讓Hadoop中的yarn作爲cluster manager,所以master,slave配置不重要。

如果還想單獨使用spark自帶的cluster manager的話,可以參考上面博文配置spark的master和slave信息。

 

 

 

正式開始安裝OOzie

 進入oozie官網:http://oozie.apache.org, 我下載的是4.3.1版。

下載之後解壓:

tar -xzvf oozie-4.3.1.tar.gz 

然後根據系統配置來修改pom.xml文件。

由於我的oozie只需要用到Hadoop和spark,所以我只需要參考以下三個值:

  1. java版本
  2. hadoop版本 : 2.9.2
  3. spark版本:2.4.4

java版本通過以下命令行查看:

java -version

我這裏的java版本是1.8...

在pom.xml中找到hadoop version,spark version還有java version這樣配置:

修改完之後,在oozie-4.3.1的目錄下輸入如下指令:

bin/mkdistro.sh  -DskipTests -Puber 

然後就開始等待編譯。編譯完成後,在oozie-4.3.1/distro/target中找到oozie-4.3.1.distro.tar.gz,這個就是編譯好的oozie。

把這個oozie複製到home目錄下。先把編譯的前的oozie文件夾給改個名字,因爲解壓編譯好的oozie文件夾名字和原來的名字一樣,會覆蓋掉。我把沒編譯的oozie文件夾命名爲oozie-4.3.1.uncompiled,解壓之後的編譯後版本是oozie-4.3.1。

解壓剛編譯好的oozie:

tar -xzvf oozie-4.3.1-distro.tar.gz

修改~/.bash_profile

命令行輸入:

vim ~/.bash_profile 

    在裏面加入下面三行:

export OOZIE_HOME=/home/qianwen/oozie-4.3.1
export OOZIE_CONFIG=$OOZIE_HOME/conf
export CLASSPATH=$CLASSPATH:$OOZIE_HOME/bin

    然後source一下:

 source ~/.bash_profile 

 

修改hadoop的core-site.xml

    在命令行輸入:

vim hadoop-2.9.2/etc/hadoop/core-site.xml

然後在裏面添加。這裏不要偷懶,要把所有的slave node上的core-site.xml都修改了:

<property>
     <name>hadoop.proxyuser.qianwen.hosts</name>
     <value>*</value>
</property>
 
<property>
     <name>hadoop.proxyuser.qianwen.groups</name>
     <value>*</value>
</property>

值得注意的是,下圖紅圈部分的設置,是根據所在用戶組來填的。(因爲我是個假cs學生,所以一開始也鬧不明白,錯了好久)。你看看你的終端,@前面是什麼,在core-site.xml兩個紅圈裏面就填什麼。

 

修改oozie的oozie-site.xml

進入oozie配置的文件夾:

cd ~/oozie-4.3.1/conf

    然後修改oozie-site.xml:


<property>
    <name>oozie.service.JPAService.jdbc.driver</name>
    <value>com.mysql.cj.jdbc.Driver</value>
</property>


<property>
    <name>oozie.service.JPAService.jdbc.url</name>
    <value>jdbc:mysql://localhost:3306/oozie</value>  <!-- .....master:3306,..localhost:3306 -->
</property>


<property>
    <name>oozie.service.JPAService.jdbc.username</name>
    <value>oozie</value>
</property>


<property>
    <name>oozie.service.JPAService.jdbc.password</name>
    <value>mysql</value>
</property>


<property>
    <name>oozie.service.HadoopAccessorService.hadoop.configurations</name>
    <value>*=/home/qianwen/hadoop-2.9.2/etc/hadoop</value>
</property>


<property>
    <name>oozie.service.WorkflowAppService.system.libpath</name>
    <value>hdfs://dragon-1:9000/user/qianwen/share/lib</value>
</property>

<property>
        <name>oozie.service.WorkflowAppService.WorkflowDefinitionMaxLength</name>
        <value>100000000</value>
</property>

但是這裏要注意下面兩點:

    第一,這裏寫qianwen是和之前hadoop core-site配置裏面的一樣。下面的那個屬性配置的是oozie在hdfs裏面share lib的地址。

    第二,下面這兩個屬性,一個是數據庫用戶的用戶名,一個是用戶的密碼,這個需要和後面在數據庫裏創建的用戶名密碼相匹配。不如下一步就把數據庫那邊先搞定吧。

 

創建數據庫和用戶及其授權

   進入mysql:

mysql -uroot -p

 然後照提示輸入密碼,就會進入如下界面:

創建oozie數據庫:

 CREATE DATABASE oozie;

因爲上一步我們在oozie-site.xml裏面配置的用戶名是oozie,密碼是mysql,所以我們要在mysql裏面建立這個用戶

CREATE USER 'oozie'@'%' IDENTIFIED BY 'mysql';

前面那個oozie,代表的是用戶名,identified by後面跟着的‘mysql’是密碼。 然後@後面‘%’代表的意思是:我們創建的這個用戶可以在任意主機上訪問mysql。下一步是給oozie用戶操作數據庫oozie的權限:

GRANT ALL ON oozie.* TO 'oozie'@'%';

    ALL代表給所有的權限, oozie.*,前面的oozie代表的是數據庫名字,*代表的是oozie數據庫下所有的表,最後的‘oozie’@'*'是剛剛創建的用戶。最後輸入如下命令使得剛剛操作生效:

 FLUSH privileges;

然後輸入如下命令退出mysql

exit

把需要的jar包都打包(這一步不一樣!!)

首先在進入oozie-4.3.1目錄:

cd ~/oozie-4.3.1/

    創建libext文件夾:

mkdir libext

然後把hadoop裏面的包複製到libext裏面:

cp ../hadoop-2.9.2/share/hadoop/*/lib/*.jar libext/
cp ../hadoop-2.9.2/share/hadoop/*/*.jar libext/

把spark裏面的包複製到libext裏面:

 cp ../spark-2.4.4-bin-hadoop2.7/jars/* libext/

    然後把之前百度網盤裏面下載的mysql-connector的jar包和ext-2.2.zip也放到libext文件夾裏面:

cp ../mysql-connector-java-8.0.11.jar libext/
cp ../ext-2.2.zip libext/

然後把libext 裏面一系列和hadoop衝突的包丟掉:

cd libext
mv servlet-api-2.5.jar servlet-api-2.5.jar.bak
mv jsp-api-2.1.jar jsp-api-2.1.jar.bak
mv slf4j-log4j12-1.7.25.jar slf4j-log4j12-1.7.5.jar.bak
mv slf4j-log4j12-1.7.16.jar slf4j-log4j12-1.7.16.jar.bak

    回到oozie文件夾下:    

cd ~/oozie-4.3.1/

下一步就是打包oozie.war。因爲我的ubuntu裏面有unzip和zip,所以我得先安裝unzip和zip。如果你也沒有zip和unzip,那麼可用如下命令安裝zip和unzip:

sudo apt-get install zip
sudo apt-get install unzip

如果已經有了unzip和zip就直接執行下面命令。

bin/oozie-setup.sh prepare-war

執行完成後會出現如下命令:

 

下一步修改oozie-env.sh

vim conf/oozie-env.sh

然後添加如下內容:

# Set Java hoem and hadoop prefix
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
export OOZIE_PREFIX=/home/qianwen/oozie-4.3.1


# Set hadoop configuration path
export OOZIE_CONF_DIR=/home/qianwen/oozie-4.3.1/conf/
export OOZIE_HOME=/home/qianwen/oozie-4.3.1



for file in $OOZIE_HOME/libext/*.jar
do
        export CLASSPATH=$CLASSPATH:$file
done

  然後千萬記得要soufce一下:

source conf/oozie-env.sh

 

上傳share lib到hdfs(這一步也不一樣)

先啓動hadoop。千萬要啓動historyserver,沒有這個oozie是用不了的!

cd ~/hadoop-2.9.2
sbin/start-dfs.sh
sbin/start-yarn.sh
sbin/mr-jobhistory-daemon.sh start historyserver

解壓oozie-4.3.1目錄下的share lib:

cd ~/oozie-4.3.1
tar -xzvf oozie-sharelib-4.3.1.tar.gz 

因爲oozie中的spark包是支持spark1的,爲了支持spark2,所以我們得做如下改動,進入share/lib文件夾下:

cd share/lib
mkdir spark2

然後把spark裏面所有的jar包,放進spark2裏:

cp ~/spark-2.4.4-bin-hadoop2.7/jars/* spark2/

然後把oozie中自帶的oozie-spark包放進我們的spark2目錄下:

cp spark/oozie-sharelib-spark-4.3.1.jar spark2/

接着回到oozie主目錄,上傳oozie的share lib到hdfs:

cd ~/oozie-4.3.1
hdfs dfs -put share 

 

在oozie關聯mysql數據庫

進入oozie頁面:

cd ~/oozie-4.3.1

然後輸入如下命令關聯數據庫:

bin/ooziedb.sh create -sqlfile oozie.sql -run

 

撒花:終於可以啓動oozie了

在啓動oozie之前,記得先啓動hadoop和job history server。

然後進入到oozie的目錄下,啓動oozie:

cd ~/oozie-4.3.1
bin/oozied.sh start

然後輸入下列命令查看oozie狀態:

bin/oozie admin --oozie http://localhost:11000/oozie -status

 

最重要的步驟,跑例子!!

先建立一個新的文件夾spark_test,然後進入這個目錄下:

mkdir spark_test
cd spark_test

新建WordCount.scala文件:

vim WordCount.scala

然後在裏面添加如下內容:

import org.apache.spark.SparkContext
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext._
import org.apache.hadoop.conf.Configuration
import org.apache.hadoop.fs.FileSystem


object WordCount{

  def main(args : Array[String]) {

    val hadoopconf = new Configuration();
    hadoopconf.setBoolean("fs.hdfs.impl.disable.cache", true);
    val fileSystem = FileSystem.get(hadoopconf);

    //spark configuration
    val conf = new SparkConf().setAppName("WordCount");
    val sc = new SparkContext(conf);

    val wordcount=sc.textFile(args(0)).flatMap(_.split(" ")).map(word=>(word,1)).reduceByKey(_+_).saveAsTextFile(args(1));
    println("Word Count program running results are successfully saved.");

  }

}

這個代碼主要就是接受參數,input的地址,然後給單詞計數,把結果放入第二個參數,也就是output地址中。

解壓oozie目錄下的example:

tar -xzvf oozie-examples.tar.gz 

進入examples/apps文件夾,然後建一個新的project:sparkonyarn

cd examples/apps/sparkonyarn
cd sparkonyarn

下一步就是build代碼,build之前需要編輯build文檔,類似於maven裏的pom.xml:

vim build.sbt

添加以下內容:

name := "sparkScala"
version := "1.0"
scalaVersion := "2.10.4"
javacOptions ++= Seq("-source", "1.8", "-target", "1.8")
libraryDependencies += "org.apache.spark" % "spark-core_2.11" % "2.3.4" % "provided"
mainClass in Compile := Some("WordCount")

這裏的version我寫的是1.0,之後修改WordCount之後,可以相應的改成2.0,3.0之類的。

JavaOption,要填寫當前電腦安裝的Java版本:1.8

ScalaVersion填寫scala的Version。

對於libraryDependencies。spark-core後面的數字是這樣決定的:

首先進入spark主目錄中的jars目錄下:

cd ~/spark-2.3.4-bin-hadoop2.7/jars/

然後輸入如下內容:

ls * | grep "core"

然後再輸出中找到scala-score,後面的2.11和2.3.4都是根據這個來填的:

接着輸入如下命令build:

sbt package

成功後,輸入ls應該能看到當前目錄下多了project和target兩個文件夾。

進入target/scala-2.10文件夾,將這裏的sparkscala_2.10-1.0.jar複製到oozie主目錄下:

cp sparkscala_2.10-1.0.jar ~/oozie-4.3.1

進入oozie目錄,解壓oozie目錄下的example:

cd ~/oozie-4.3.1
tar -xzvf oozie-examples.tar.gz 

進入examples/apps目錄下,建立一個新的project目錄,sparkonyarn:

cd examples/apps
mkdir sparkonyarn
cd sparkonyarn

在sparkonyarn目錄下,建立lib文件夾,把剛剛編譯好的sparkscala_2.10-1.0.jar放入lib文件夾:

mkdir lib
cp ~/oozie-4.3.1/sparkscala_2.10-1.0.jar lib/

然後在sparkonyarn目錄下新建job.properties文檔:

vim job.properties

然後寫入如下內容:

nameNode=hdfs://dragon-1:9000
jobTracker=dragon-1:8032
master=yarn-cluster
queueName=default
examplesRoot=examples

oozie.action.sharelib.for.spark=spark2

oozie.use.system.libpath=true
oozie.wf.application.path=${nameNode}/user/${user.name}/${examplesRoot}/apps/sparkonyarn/workflow.xml

nameNode的配置根據hadoop中core-site.xml裏面配置的,jobtracker的配置是在hadoop的yarn-site.xml裏面配置的yarn.resourcemanager.address屬性。

注意這裏要specify一下spark的sharelib,爲之前新建的spark2。不然用成了spark1的包,那就完犢子了:

然後新建workflow.xml:

vim workflow.xml

然後添加如下內容:

<workflow-app xmlns='uri:oozie:workflow:0.5' name='SparkFileCopy'>
    <start to='spark-node' />

    <action name='spark-node'>
        <spark xmlns="uri:oozie:spark-action:0.1">
            <job-tracker>${jobTracker}</job-tracker>
            <name-node>${nameNode}</name-node>
            <prepare>
                <delete path="${nameNode}/user/${wf:user()}/output"/>
            </prepare>
            <master>${master}</master>
            <name>WordCount</name>
            <class>WordCount</class>
            <jar>${nameNode}/user/${wf:user()}/${examplesRoot}/apps/sparkonyarn/sparkscala_2.10-1.0.jar</jar>
            <arg>${nameNode}/user/${wf:user()}/input/*</arg>
            <arg>${nameNode}/user/${wf:user()}/output</arg>
        </spark>
        <ok to="end" />
        <error to="fail" />
    </action>

    <kill name="fail">
        <message>Workflow failed, error
            message[${wf:errorMessage(wf:lastErrorNode())}]
        </message>
    </kill>
    <end name='end' />
</workflow-app>

裏面的<arg>這個標籤就是參數,第一個參數的input地址,第二個是output地址。

然後回到oozie主目錄,簡單粗暴把整個example全上傳到hdfs上:

cd ~/oozie-4.3.1
hdfs dfs -put examples 

接着準備input,在hdfs中的主目錄下新建一個input目錄:

hdfs dfs -mkdir input

然後隨便放一個txt文件進去就行:

hdfs dfs -put release-log.txt input/

    然後就可以執行oozie job啦:

bin/oozie job -oozie  http://localhost:11000/oozie -config examples/apps/sparkonyarn/job.properties -run

 job提高成功之後就會給一個job ID。之後就可以通過如下命令查看job的狀態,最後那一串就是剛剛給的job ID:

bin/oozie job -oozie http://localhost:11000/oozie -info 0000001-191010143920598-oozie-qian-W

然後在hdfs上就能查看輸出啦:

hdfs dfs -cat output/part-00000

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