安装前准备:
安装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