安裝前準備:
安裝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,所以我只需要參考以下三個值:
- java版本
- hadoop版本 : 2.9.2
- 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