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

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