spark JAVA 开发环境搭建及远程调试
之后要在项目中使用Spark 用户昵称文本作一下聚类分析,找出一些违规的昵称信息。之前折腾过Hadoop,因而看了下Spark官网的文档以及 github 上 官方提供的examples,看完了以后决定动手跑一个文本聚类的demo,因而有了下文。html
1. 环境介绍
本地开发环境是:IDEA201八、JDK八、windows 10。远程服务器 Ubuntu 16.04.3 LTS上安装了spark-2.3.1-bin-hadoop2.7
java
看spark官网介绍,有两种形式(不是Spark Application Execution Mode)来启动sparkgit
-
Running the Examples and Shellgithub
好比说
./bin/pyspark --master local[2]
启动的是一个交互式的命令行界面,能够在4040端口查看做业。算法 -
Launching on a Clustersql
spark 集群,有多种部署选项:Standalone。另外还有:YARN,Mesos(将集群中的资源将由资源管理器来管理)。apache
对于Standalone,
./sbin/start-master.sh
启动Master,经过8080端口就能看到:集群的状况。json
再经过./sbin/start-slave.sh spark://panda-e550:7077
启动slave:Alive Workers 就是启动的slave。windows
执行jps:看到Master和Worker:服务器
~/spark-2.3.1-bin-hadoop2.7$ jps 45437 Master 50429 Worker
下面介绍一下在本地windows10 环境下写Spark程序,而后链接到远程的这台Ubuntu机器上的Spark上进行调试。
2. 一个简单的开发环境
建立Maven工程,根据官网提供的Spark Examples 来演示聚类算法(JavaBisectingKMeansExample )的运行过程,并介绍如何配置Spark调试环境。
2.1添加maven 依赖:
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-sql_2.11</artifactId> <version>2.3.1</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.spark/spark-mllib --> <dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-mllib_2.11</artifactId> <version>2.3.1</version> <!--<scope>runtime</scope>--> </dependency>
2.2 编写代码:
package net.hapjin.spark; import org.apache.spark.ml.clustering.BisectingKMeans; import org.apache.spark.ml.clustering.BisectingKMeansModel; import org.apache.spark.ml.linalg.Vector; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; import org.apache.spark.sql.SparkSession; public class JavaBisectingKMeansExample { public static void main(String[] args) { // SparkSession spark = SparkSession.builder().appName("JavaBisectingKMeansExample").getOrCreate(); SparkSession spark = SparkSession.builder().appName("JavaBisectingKMeansExample").master("spark://xx.xx.129.170:7077").getOrCreate(); // Dataset<Row> dataset = spark.read().format("libsvm").load(".\\data\\sample_kmeans_data.txt"); Dataset<Row> dataset = spark.read().format("libsvm").load("hdfs://172.25.129.170:9000/user/panda/sample_kmeans_data.txt"); // Dataset<Row> dataset = spark.read().format("libsvm").load("file:///E:/git/myown/test/spark/example/data/sample_kmeans_data.txt"); // Trains a bisecting k-means model. BisectingKMeans bkm = new BisectingKMeans().setK(2).setSeed(1); BisectingKMeansModel model = bkm.fit(dataset); // Evaluate clustering. double cost = model.computeCost(dataset); System.out.println("Within Set Sum of Squared Errors = " + cost); // Shows the result. System.out.println("Cluster Centers: "); Vector[] centers = model.clusterCenters(); for (Vector center : centers) { System.out.println(center); } // $example off$ spark.stop(); } }
2.3 配置远程调试环境
在IDEA中,"Run"-->"Edit Configurations"-->"Template"--->"Remote",点击 "+"号:
报错:
Could not locate executable null\bin\winutils.exe
去这个github下载对应的Hadoop版本的winutils.exe。
配置windows10环境变量:HADOOP_HOME,并将该环境变量添加到 Path 环境变量下%HADOOP_HOME%\bin
。
再次Debug调试,成功进入断点:(若是报拒绝链接的错误,修改一下 conf/spark-env.sh 指定SPARK_LOCAL_IP
为机器的IP地址,而后再 修改 /etc/hosts 文件 将主机名与机器IP地址相对应便可)
其实,在本地开发环境(Windows10)连不上远程的服务器时,先在Windows下telnet 一下看一下能不能通。若是不能通,那确定连不上了。另外,能够在远程服务器上看下相应的端口绑定在哪一个IP地址上,是否是绑定到了环回地址上了。好比下面这个spark master默认端口绑定在127.0.1.1上,那你本地的开发环境确定连不上这个端口了:
~/spark-2.3.1-bin-hadoop2.7$ netstat -anp | grep 7077 tcp6 0 0 127.0.1.1:7077 :::* LISTEN 18406/java
tcp6 0 0 127.0.0.1:29599 127.0.1.1:7077 ESTABLISHED 18605/java
tcp6 0 0 127.0.1.1:7077 127.0.0.1:29599 ESTABLISHED 18406/java
接下来,执行读取文件,明明文件就在windows的该路径下,可是就是报错:
Caused by: java.io.FileNotFoundException: File file:/E:/git/myown/test/spark/example/data/sample_kmeans_data.txt does not exist
尝试了好几个路径写法,好比这篇stackoverflow,都未果。
// Dataset<Row> dataset = spark.read().format("libsvm").load(".\\data\\sample_kmeans_data.txt"); Dataset<Row> dataset = spark.read().format("libsvm").load("file:///E:\\git\\myown\\test\\spark\\example\\data\\sample_kmeans_data.txt"); // Dataset<Row> dataset = spark.read().format("libsvm").load("file:///E:/git/myown/test/spark/example/data/sample_kmeans_data.txt");
看里面的解释:
SparkContext.textFile internally calls
org.apache.hadoop.mapred.FileInputFormat.getSplits
, which in turn usesorg.apache.hadoop.fs.getDefaultUri
if schema is absent. This method reads "fs.defaultFS" parameter of Hadoop conf. If you set HADOOP_CONF_DIR environment variable, the parameter is usually set as "hdfs://..."; otherwise "file://".
由于我本地Windows10没有安装Hadoop,只是上面提到的下载winutils.exe时,简单地配置了个 HADOOP_HOME
环境变量。因此我也不知道这种远程调试中读取本地windows系统上的文件是否可行了。
看来,我只能在远程服务器上再安装个Hadoop了,而后把文件上传到HDFS上。因而,下载Hadoop-2.7.7,解压安装(按照官网 伪分布式模式配置安装),并启动HDFS:
$ sbin/start-dfs.sh
jps查看当前服务器上的进程:
panda@panda-e550:~/data/spark$ jps 2435 Master 10181 SecondaryNameNode 11543 Jps 9849 NameNode 3321 Worker 9997 DataNode
其中Master是Spark master;Worker是spark worker;NameNode、DataNode、SecondaryNameNode是Hadoop HDFS的相关进程。把文件上传到HDFS上:
panda@panda-e550:~/software/hadoop-2.7.7$ ./bin/hdfs dfs -ls /user/panda Found 2 items -rw-r--r-- 1 panda supergroup 70 2018-10-30 17:54 /user/panda/people.json -rw-r--r-- 1 panda supergroup 120 2018-10-30 18:09 /user/panda/sample_kmeans_data.txt
修改一下代码中文件的路径:(仍是隐藏一下具体的ip吧)
Dataset<Row> dataset = spark.read().format("libsvm").load("hdfs://xx.xx.129.170:9000/user/panda/sample_kmeans_data.txt");
继续右击debug,又报错:
failed on connection exception: java.net.ConnectException: Connection refused: no further information; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused
按照提示的连接看:应该是下面这个问题。
- If the error message says the remote service is on "127.0.0.1" or "localhost" that means the configuration file is telling the client that the service is on the local server. If your client is trying to talk to a remote system, then your configuration is broken.
- Check that there isn't an entry for your hostname mapped to 127.0.0.1 or 127.0.1.1 in
/etc/hosts
(Ubuntu is notorious for this)
cat /etc/hosts
部份内容以下:
127.0.0.1 localhost
172.25.129.170 panda-e550
再看看 hdfs上的配置文件:cat etc/hadoop/core-site.xml
<configuration> <property> <name>fs.defaultFS</name> <value>hdfs://localhost:9000</value> </property> </configuration>
在远程服务器上:
panda@panda-e550:~/software/hadoop-2.7.7$ netstat -anp | grep 9000 tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 9849/java
tcp 0 0 127.0.0.1:43162 127.0.0.1:9000 ESTABLISHED 9997/java
tcp 0 0 127.0.0.1:43360 127.0.0.1:9000 TIME_WAIT -
tcp 0 0 127.0.0.1:9000 127.0.0.1:43162 ESTABLISHED 9849/java
所以,出现ConnectException的缘由就很明显了。所以,服务器Hadoop HDFS 9000端口绑定在到环回地址上。那我在windows10上的机器上的IDEA的代码程序里面指定:hdfs://172.25.129.170:9000/user/panda/sample_kmeans_data.txt
确定是不行的了。毕竟windows10开发环境机器的ip地址,确定和安装Hadoop的远程服务器的ip地址是不一样的。
因为core-site.xml
配置的是hdfs://localhost:9000
,按理说,把 localhost 改为 ip 地址应该是能够的。可是我采用另外一种方案,修改 /etc/hosts中的文件:把原来的127.0.0.1
对应的localhost注释掉,修改为机器的ip地址,以下:
panda@panda-e550:~/software/hadoop-2.7.7$ cat /etc/hosts # comment this line and add new line for hadoop hdfs #127.0.0.1 localhost 172.25.129.170 localhost
而后再重启一下 HDFS进程。此时:
panda@panda-e550:~/software/hadoop-2.7.7$ netstat -anp | grep 9000 tcp 0 0 172.25.129.170:9000 0.0.0.0:* LISTEN 13126/java
tcp 0 0 172.25.129.170:50522 172.25.129.170:9000 ESTABLISHED 13276/java
tcp 0 0 172.25.129.170:50616 172.25.129.170:9000 TIME_WAIT -
tcp 0 0 172.25.129.170:9000 172.25.129.170:50522 ESTABLISHED 13126/java
在windows10 机器的cmd命令行上telnet 一下:发现能成功链接上。所以能够放心debug了。
C:\Users\Administrator.000>telnet 172.25.129.170 9000
最终,整个远程调试完整跑通:
程序输出:
Within Set Sum of Squared Errors = 0.11999999999994547 Cluster Centers: [0.1,0.1,0.1]
汇总一下: 启动spark master 和 slave命令。
./sbin/start-master.sh
./sbin/start-slave.sh spark://panda-e550:7077
http://172.25.129.170:8080/ 查看spark管理界面
启动hdfs命令(伪分布式)
./sbin/start-dfs.sh
在知乎上看到一个问题:如何更有效地学习开源项目的代码?,放到这里供你们参考一下。