当前位置:   article > 正文

使用sbt编写Spark独立应用程序_头歌通过spark api编写一个独立应用程序

头歌通过spark api编写一个独立应用程序

使用Scala编写的程序需要使用sbt进行编译打包,相应的,java程序使用Maven编译打包,而Python程序通过spark-submit直接提交。

由于spark中并没有自带sbt,因此我们需要下载安装一个

安装最新版sbt工具方法和体会_厦大数据库实验室博客

安装sbt的方法参考上述内容

目录

安装sbt

编写Scala应用程序

第一个Spark应用程序WordCount

安装sbt

在https://www.scala-sbt.org/download.html 网站上下载sbt 1.3.8

 

下载好以后,使用共享文件夹,让虚拟机能访问到该文件

》cd /usr/local

将下载好的sbt安装包拷贝到/usr/local文件夹中

》sudo cp /mnt/hgfs/ubuntu-share/sbt-1.3.8.tgz .

 

在此处解压缩

》sudo tar -zxvf ./sbt-1.3.8.tgz

 

为文件夹赋予权限,此处的zhuluobigdata是本台计算机的用户名

》sudo chown -R zhuluobigdata /usr/local/sbt

接下来将bin目录下的sbt-launch.jar复制到sbt的安装目录下

》cd sbt

》sudo cp ./bin/sbt-launch.jar ./

 

接下来在安装目录中,使用下面的命令创建一个Shell脚本文件,用于启动sbt

》sudo vim /usr/local/sbt/sbt

将如下内容写入:

#!/bin/bash

SBT_OPTS="-Xms512M -Xmx1536M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256M"

java $SBT_OPTS -jar `dirname $0`/sbt-launch.jar "$@"

 

保存以后,需要为该文件添加一个可执行权限

》sudo chmod u+x /usr/local/sbt/sbt

接下来可以查看一下版本信息:

》sudo ./sbt sbtVersion

(访问sbt版本时,sbt将通过访问国外网站下载需要的内容,所以如果没有开代理的话,可能会出现卡住的情况,建议开启梯子后执行此步)

此时发生报错:

/sbt: line 3: java: command not found

搜索一下原因:

可以这样子排错:

首先,可能是jdk环境变量的问题

如果已经安装了jdk并配置过环境变量,重新执行

》source /etc/profile

重新使配置文件生效,再执行看看是否能够成功

若还是不能成功,则有可能是因为在sudo环境下,系统的环境变量发生了变化,导致找不到java命令

可以执行:

》sudo env “PATH=$PATH” ./sbt sbtVersion

这个命令会将PATH环境变量在sudo环境下重新设置为当前用户的PATH环境变量,从而解决找不到Java命令的问题

 

如果能返回上述信息,则说明sbt已经安装成功了

但是这个过程非常的漫长,会花费很长的时间

 

要下载不少内容

(为了减少时间,可以参考后续的内容:更换仓库地址加快编译速度)

但是,只要安装成功,第二次开始运行sudo env "PATH=$PATH" ./sbt sbtVersion或者执行编译打包命令,速度就会变得比较快了。

大概过了十多分钟,输出了如下结果

》sudo env "PATH=$PATH" ./sbt sbtVersion

第二次执行,查看版本,展示出如下结果仅花费4,5秒的时间

 

关于如何更换仓库地址,加快编译速度

在此不过多赘述,感兴趣的hxd可以查看厦门大学林子雨老师的博客:

安装最新版sbt工具方法和体会_厦大数据库实验室博客

网站中有换源的步骤以及老师的个人思考

编写Scala应用程序

在终端中执行如下命令创建一个文件夹sparkapp作为应用程序的根目录。

 

 

Mycode目录是专门用来保存我们的代码的

一定要按照这个规定定义目录

在此,我在用户主文件夹下,创建我的目录

》cd ~

》mkdir ./sparkapp

》mkdir -p ./sparkapp/src/main/scala

以上命令将在用户主文件夹下创建一个sparkapp文件夹,作为应用程序根目录

在~/sparkapp/src/main/scala目录下创建一个新的文件:SimpleApp.scala

》cd sparkapp/src/main/scala

》vim SimpleApp.scala

写入如下的内容:

 

接下来需要去添加sbt文件用于编译

在~/sparkapp目录下创建文件simple.sbt

》cd ~/sparkapp

》vim simple.sbt

添加内容如下,声明该独立应用程序的信息以及与Spark的依赖关系

 

Name和version声明了项目的名称和版本信息

另外两个字段需要根据我们的版本进行选择,在spark shell启动的时候,有如下信息:

此输出告诉我们,spark的版本为2.4.5,scala的版本为2.11.12

因此,上面的.sbt配置文件中与版本有关的信息要进行针对性的修改。

目前我们只使用到了spark-core这个核心包

后续如果要使用流计算、图计算、机器学习等内容,还需要引入其他的包

为了保证sbt能够正常运行,我们需要检查整个应用程序的文件结构:

》cd ~/sparkapp

》find .

输出的文件结构应该如下图所示:

 

 

接着,可以将整个应用程序进行打包

》sudo /usr/local/sbt/sbt package

 

出现如上的提示,这表明sbt获取不到java的环境

像先前查看sbt版本遇到的问题一样,我们使配置文件/etc/profile重新生效

》source /etc/profile

 

再次执行仍然还是command not found

原因也和先前查看sbt版本遇到的问题一样,在sudo的权限下,系统的环境变量发生了变化,导致找不到java命令

因此,我们将指令修改为,即可成功启动编译

》sudo env "PATH=$PATH" /usr/local/sbt/sbt package

第一次编译需要下载不少依赖,因此,最好开启梯子再进行此步

编译成功的返回如下:

 

在我们的应用程序目录下,就会多生成project文件夹和target文件夹

进入./target/scala-2.11文件夹,可以看到打包好的jar包

 

 

现在已经获取到了jar包,我们可以将其提交并运行。

可以通过spark-submit提交应用程序,该命令的格式如下:

将生成的jar包通过spark-submit提交到Spark中运行,命令如下:

》/usr/local/spark-2.4.5-bin-hadoop2.7/bin/spark-submit --class "SimpleApp" ~/sparkapp/target/scala-2.11/simple-project_2.11-1.0.jar

这样会输出非常多的执行信息,在诸多信息中,可以找到我们程序要产生的结果

 

可以使用下面的指令,直接查看我们希望看到的输出

》/usr/local/spark-2.4.5-bin-hadoop2.7/bin/spark-submit --class "SimpleApp" ~/sparkapp/target/scala-2.11/simple-project_2.11-1.0.jar 2>&1 | grep "Lines with a:"

 这样就可以把我们希望看到的输出筛选出来了

 

第一个Spark应用程序WordCount

① 在Spark Shell中执行词频统计

先创建一个word.txt文件用于词频统计

》cd /usr/local/spark-2.4.5-bin-hadoop2.7/

》sudo mkdir mycode

》cd mycode

》sudo mkdir wordcount

》cd wordcount

》sudo vim word.txt

将以下内容写入word.txt用于词频统计

I woke up feeling a sense of purpose. It was a beautiful day outside, with the sun shining and a gentle breeze blowing. I decided to go for a walk in the park, where I could enjoy the natural beauty around me. As I strolled along the path, I noticed the colorful flowers blooming in the flowerbeds, and the trees swaying in the wind.

I continued my walk, enjoying the fresh air and the peaceful atmosphere. Suddenly, I heard a loud noise coming from behind a nearby building. Curiosity getting the better of me, I decided to investigate. As I got closer, I realized it was a group of children playing with a ball. They were having so much fun, laughing and joking.

接下来打开spark-shell,执行词频统计相关代码

》val textFile = sc.textFile("file:///usr/local/spark-2.4.5-bin-hadoop2.7/mycode/wordcount/word.txt")

 

解释:在sparkshell中自带了sc对象(Spark Context),使用该对象可以读取本地文件系统或者HDFS分布式文件系统中的文件。在此我们访问本地文件

返回内容表明,现在的textFile变量已经是一个RDD了

》val wordCount = textFile.flatMap(line=>line.split(" ")).map(word=>(word,1)).reduceByKey((a,b)=>a+b)

解释:对textFile这个RDD进行粗粒度的转换处理。

首先,对于textFile中的每一行,都以空格” ”为分界线,将单词区分开

其次,对于每个单次,都将其以(单词,1)的方式写入map中

最后,key值相同的项进行合并,他们的数量相加

产生的结果为新的RDD

 》wordCount.collect()

解释:对wordCount对象使用collect()方法,能将集群中所有节点的处理结果获取并整合

》wordCount.foreach(println)

 

解释:即打印当前的统计结果

②编写独立应用程序执行词频统计

基于前面创建的~/sparkapp程序目录

在~/sparkapp/src/main/scala目录下创建新的.scala文件

》vim WordCount.scala

输入如下的内容

 

这段代码的解释为:

首先,导入了SparkContext、SparkConf 以及 SparkContext 对象中的一些函数

 

 

定义了名为WordCount的对象,在其中编写了主函数main()

变量inputFile包含要统计词频的文本文件的本地路径

创建了一个名为conf的SparkConfig对象,并设置了应用程序名称和运行模式

这里的local[2]表示使用两个本地的线程来执行

基于SparkConfig对象,创建了一个名为sc的SparkContext对象

利用SparkContext对象中的textFile()函数,读取了包含文本内容的文件,并将其转换为RDD对象。

利用flatMap()函数,将所有单词拆分成一个个字符串,并将它们转化为键值对形式

其中键是单词,值为数字1

最后利用reduceByKey函数,按照键值对中的键将所有单词进行分组,并将每个单词出现的次数相加。最后通过collect()函数将结果返回到本地驱动程序并打印结果。

使用sbt进行编译,生成jar包

》sudo env "PATH=$PATH" /usr/local/sbt/sbt package

使用spark-submit提交运行

》/usr/local/spark-2.4.5-bin-hadoop2.7/bin/spark-submit --class "WordCount" ~/sparkapp/target/scala-2.11/simple-project_2.11-1.0.jar

上面这个命令和之前相比,只在类名处有变化

因为程序执行需要从mian入手,而我在sparkapp应用程序目录中写入了两个以上的main,因此一定要指定入口类的名字,让程序能够正常地执行。

上图为执行成功之后的部分输出内容。

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/木道寻08/article/detail/888104
推荐阅读
相关标签
  

闽ICP备14008679号