返回《在阿里云中搭建大数据实验环境》首页
提示:本教程是一个系列文章,请务必按照本教程首页中给出的各个步骤列表,按照先后顺序一步步进行操作,本博客假设你已经顺利完成了之前的操作步骤。
现在介绍如何在阿里云ECS的Ubuntu系统中安装Spark,本教程采用的版本是Spark2.1.0。Spark部署模式主要有四种:Local模式(单机模式)、Standalone模式(使用Spark自带的简单集群管理器)、YARN模式(使用YARN作为集群管理器)和Mesos模式(使用Mesos作为集群管理器)。这里介绍Local模式(单机模式)的 Spark安装。
安装Spark
可以到Spark官网下载Spark2.1.0安装包,或者,直接到笔者提供的百度云盘下载。笔者已经把Spark安装包保存到了百度云盘中,可以点击这里直接从百度云盘下载文件spark-2.1.0-bin-without-hadoop.tgz(提取码:gx0b)。下载成功以后,可以在本地电脑,打开FTP软件,使用linziyu用户名登录到阿里云ECS的Ubuntu系统,把spark-2.1.0-bin-without-hadoop.tgz通过FTP软件上传到“/home/linziyu/Downloads”目录下。
然后,在本地电脑通过VNC Viewer连接远程的阿里云ECS实例中的Ubuntu系统(使用用户名linziyu),打开一个命令行终端,执行如下命令进行Spark的安装:
cd ~
sudo tar -zxvf /home/linziyu/Downloads/spark-2.1.0-bin-without-hadoop.tgz -C /usr/local
cd /usr/local
sudo mv ./spark-2.1.0-bin-without-hadoop ./spark
sudo chown -R linziyu:linziyu ./spark
然后,修改Spark配置文件:
cd /usr/local/spark
cp ./conf/spark-env.sh.template ./conf/spark-env.sh
编辑spark-env.sh文件(vim ./conf/spark-env.sh),在第一行添加以下配置信息:
export SPARK_DIST_CLASSPATH=$(/usr/local/hadoop/bin/hadoop classpath)
有了上面的配置信息以后,Spark就可以把数据存储到Hadoop分布式文件系统HDFS中,也可以从HDFS中读取数据。如果没有配置上面信息,Spark就只能读写本地数据,无法读写HDFS数据。
配置完成后就可以直接使用,不需要像Hadoop运行启动命令。
通过运行Spark自带的示例,验证Spark是否安装成功。
cd /usr/local/spark
./bin/run-example SparkPi
执行时会输出非常多的运行信息,输出结果不容易找到,可以通过 grep 命令进行过滤(命令中的 2>&1 可以将所有的信息都输出到 stdout 中,否则由于输出日志的性质,还是会输出到屏幕中):
cd /usr/local/spark
./bin/run-example SparkPi 2>&1 | grep "Pi is"
这里涉及到Linux Shell中管道的知识,详情可以参考Linux Shell中的管道命令
过滤后的运行结果可以得到π 的 5 位小数近似值,效果如下:
linziyu@iZbp11gznj7n38xkztu64dZ:/usr/local/spark$ ./bin/run-example SparkPi 2>&1 | grep "Pi is"
Pi is roughly 3.1414157070785356
启动进入spark-shell交互式执行环境
在Ubuntu终端里面,执行如下命令启动进入spark-shell交互式执行环境:
cd /usr/local/spark
./bin/spark-shell
然后,会在屏幕上显示如下信息:
linziyu@iZbp11gznj7n38xkztu64dZ:/usr/local/spark$ ./bin/spark-shell
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
18/04/08 09:48:49 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Spark context Web UI available at http://192.168.1.106:4040
Spark context available as 'sc' (master = local[*], app id = local-1523262130155).
Spark session available as 'spark'.
Welcome to
____ __
/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/___/ .__/\_,_/_/ /_/\_\ version 2.1.0
/_/
Using Scala version 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_162)
Type in expressions to have them evaluated.
Type :help for more information.
scala>
这样就进入了交互式执行环境,可以在里面输入Scala代码并执行:
scala> 3+5
res0: Int = 8
然后,使用如下命令退出spark-shell交互式环境:
scala> :quit
测试Spark是否可以正常访问Ubuntu系统中的本地文件
在Ubuntu系统中打开一个终端(当前登录用户是linziyu),进行如命令行提示符状态,然后,在Ubuntu系统的本地文件系统目录中,进入到用户linziyu的主目录,使用vim编辑器新建一个word.txt文本文件,具体命令如下:
cd /home/linziyu
vim word.txt
在word.txt文件中随意输入几行英文单词(比如第一行输入:I love Spark 第2行输入:I love Hadoop 第3行输入:Spark is good),保存文件并退出vim编辑器。
然后,再新建一个终端,新建的终端会在新的窗口中,有多个终端窗口存在时,可以在不同终端窗口之间进行切换,切换到你要操作的终端窗口。
新建一个终端以后,在这个新的终端里面,执行如下命令启动进入spark-shell交互式执行环境:
cd /usr/local/spark
./bin/spark-shell
启动以后就进入了“scala>”命令提示符状态,下面可以在Scala交互式环境中执行如下命令测试是否可以正常访问word.txt:
scala> val line=sc.textFile("file:///home/linziyu/word.txt")
line: org.apache.spark.rdd.RDD[String] = file:///home/linziyu/word.txt MapPartitionsRDD[5] at textFile at <console>:24
scala> println(line.count())
3
如果能够运行得到上述结果,说明Spark可以正常访问Ubuntu系统中的本地文件word.txt。
测试Spark是否能够正常访问Hadoop中的HDFS
由于我们经常需要让Spark去访问Hadoop中的HDFS,因此,需要测试一下Spark是否可以正常访问HDFS。
首先,请在阿里云ECS的Ubuntu系统中打开一个终端,执行如下命令启动Hadoop中的HDFS:
cd /usr/local/hadoop
./sbin/start-dfs.sh
然后,执行jps查看是否成功启动:
linziyu@iZbp11gznj6m26xkztu64dZ:/usr/local/hadoop$ jps
21923 Jps
21592 DataNode
21417 NameNode
21806 SecondaryNameNode
如果看到了至少上述4个进程,则表示HDFS启动成功。
下面开始在命令行终端中使用HDFS Shell操作命令,对HDFS进行相关操作,如果不熟悉HDFS Shell命令,请点击这里阅读HDFS Shell命令使用方法。
然后,使用如下命令,为当前登录Ubuntu系统的用户linziyu,在HDFS中创建linziyu的对应“主目录”,也就是“hdfs://192.168.0.106:9000/user/linziyu”:
cd /usr/local/hadoop
./bin/hdfs dfs -mkdir -p /user/linziyu
然后,把上面已经建好的Ubuntu系统中的本地文件/home/linziyu/word.txt上传到HDFS中,命令如下:
cd /usr/local/hadoop
./bin/hdfs dfs -put /home/linziyu/word.txt /user/linziyu
上传成功以后,可以使用如下命令查看一下HDFS中的word.txt的内容:
cd /usr/local/hadoop
./bin/hdfs dfs -cat /user/linziyu/word.txt
这时屏幕上就会显示出word.txt中的各行单词。
然后,在Ubuntu的终端中启动进入spark-shell交互式执行环境,去测试Spark读取HDFS数据是否成功,首先使用阿里云ECS实例的私有IP地址去测试:
scala> val line=sc.textFile("hdfs://192.168.1.106:9000/user/linziyu/word.txt")
line: org.apache.spark.rdd.RDD[String] = hdfs://172.16.206.36:9000/user/linziyu/word.txt MapPartitionsRDD[5] at textFile at <console>:24
scala> println(line.count())
java.lang.IllegalArgumentException: java.net.URISyntaxException: Relative path in absolute URI: 192.168.1.106:9000
//会出现错误信息,此处省略更多错误信息
注意,上面的192.168.1.106这个IP地址是阿里云ECS实例的私网IP地址(不是公网IP地址),你可以在你的阿里云ECS网页管理控制台中查询到你的ECS实例的私网IP地址,你的ECS实例的私网IP地址应该不会和192.168.1.106相同,请替换成你的私网IP地址。
可以看到,上述访问方式是不行的,会报错。
下面我们使用另外一种方式去测试:
scala> val line=sc.textFile("hdfs:///127.0.0.1:9000/user/linziyu/word.txt")
line: org.apache.spark.rdd.RDD[String] = hdfs:///127.0.0.1:9000/user/linziyu/word.txt MapPartitionsRDD[11] at textFile at <console>:24
scala> println(line.count())
java.lang.IllegalArgumentException: java.net.URISyntaxException: Relative path in absolute URI: 127.0.0.1:9000
//会出现错误信息,此处省略更多错误信息
可以看到,上述访问方式是不行的,会报错。
下面我们使用另外一种方式去测试:
scala> val line=sc.textFile("hdfs:///localhost:9000/user/linziyu/word.txt")
line: org.apache.spark.rdd.RDD[String] = hdfs:///localhost:9000/user/linziyu/word.txt MapPartitionsRDD[13] at textFile at <console>:24
scala> println(line.count())
java.lang.IllegalArgumentException: java.net.URISyntaxException: Relative path in absolute URI: localhost:9000
//会出现错误信息,此处省略更多错误信息
可以看到,上述访问方式是不行的,会报错。
下面我们使用阿里云ECS实例的公网IP地址去测试:
scala> val line=sc.textFile("hdfs:///48.94.171.104:9000/user/linziyu/word.txt")
line: org.apache.spark.rdd.RDD[String] = hdfs:///48.94.171.104:9000/user/linziyu/word.txt MapPartitionsRDD[15] at textFile at <console>:24
scala> println(line.count())
java.lang.IllegalArgumentException: java.net.URISyntaxException: Relative path in absolute URI: 48.94.171.104:9000
//会出现错误信息,此处省略更多错误信息
可以看到,上述访问方式是不行的,会报错。
下面我们使用另外一种方式去测试:
scala> val line=sc.textFile("/user/linziyu/word.txt")
line: org.apache.spark.rdd.RDD[String] = /user/linziyu/word.txt MapPartitionsRDD[7] at textFile at <console>:24
scala> println(line.count())
3
//运行成功
可以看出,这种方式可以成功运行。
下面我们再使用另外一种方式去测试:
scala> val line=sc.textFile("word.txt")
line: org.apache.spark.rdd.RDD[String] = word.txt MapPartitionsRDD[9] at textFile at <console>:24
scala> println(line.count())
3
//运行成功
可以看出,这种方式可以成功运行。
所以,总结一下,在spark-shell交互式环境中,要访问HDFS中的文件时,可以直接使用sc.textFile("/user/linziyu/word.txt")和sc.textFile("word.txt")这两种路径格式。但是,需要注意的是,这两种路径格式,在IntelliJ IDEA中,又会出错,后面有篇博客会专门介绍如何使用IntelliJ IDEA工具调试Spark应用程序,在那篇博客中,会解决这个问题。
实际上,如果通过修改/etc/hosts这个文件,我们也可以让下面这种采用阿里云ECS实例的私网IP地址的测试也能够成功。
scala> val line=sc.textFile("hdfs://192.168.1.106:9000/user/linziyu/word.txt")
具体方法如下:
使用用户名linziyu登录ECS中的Ubuntu系统,打开一个终端,执行如下命令修改hosts文件内容:
cd ~
sudo vim /etc/hosts
/etc/hosts这个文件的原来内容如下:
192.168.1.106 iZbp11gznj7n38xkztu64dZ
127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
修改后,请把里面的最后三行注释掉,使用#可以注释掉一行内容,修改后如下:
192.168.1.106 iZbp11gznj7n38xkztu64dZ
127.0.0.1 localhost
# The following lines are desirable for IPv6 capable hosts
#::1 localhost ip6-localhost ip6-loopback
#ff02::1 ip6-allnodes
#ff02::2 ip6-allrouters
修改后保存文件并退出vim编辑器。
这时,执行下面语句就可以成功了:
scala> val line=sc.textFile("hdfs://192.168.1.106:9000/user/linziyu/word.txt")
line: org.apache.spark.rdd.RDD[String] = hdfs://192.168.1.106:9000/user/linziyu/word.txt MapPartitionsRDD[29] at textFile at <console>:24
scala> println(line.count())
3