文章目录
一 Spark的运行模式
- Local本地模式用于测试环境, 在eclipse或IDEA中
- Standalone是spark自带的一个调度系统,它支持完全分布式
- YARN 将spark使用YARN的资源调度来进行执行
- Mesos 也是一种资源调度, 用的人较少
二 spark2.2.0 伪分布式搭建
-
基本设置:时间同步, 免密登录, 安装JDK1.8
-
上传spark2.2.0 的压缩包到指定的集群位置
-
解压spark2.2.0 的压缩包
tar -zxvf spark-2.2.0-bin-hadoop2.7.tgz -C /opt/app/
-
进入到spark安装目录下 cd spark-2.2.0-bin-hadoop2.7/ 看一下目录结构
-
修改配置文件 spark-env.sh
-
在文件最后添加环境变量
vi spark-env.sh
JDK安装路径, MasterIP地址, Master端口号
export JAVA_HOME=/opt/app/jdk1.8.0_181 export SPARK_MASTER_IP=hadoop export SPARK_MASTER_PORT=7077
-
修改conf目录下slaves文件
-
将配置好的spark集群进行分发(这里是伪分布式, 不用分发),分发到不同的节点上
scp -r ./spark-2.2.0-bin-hadoop2.7/ hadoop@hadoop02:$PWD
- 安装spark集群的所有节点是不需要安装scala, spark安装包会集成scala
- 可以配置spark全局环境变量
vi /etc/profile export SPARK_HOME=自己安装spark路径 $PATH=$SPARK_HOME/bin:$PATH
-
启动集群, 进入到spark安装目录中的sbin目录
-
Jps查看一下(主节点会有Master, 从节点会有worker)
-
spark集群的webUI界面 port:8080
三 spark 程序执行
- 使用当前spark自带的任务, 求解 π
- 提交任务的时候需要在当前的$SPARK_HOME/bin目录下提交
./spark-submit --class org.apache.spark.examples.SparkPi --master spark://hadoop:7077 /opt/app/spark-2.2.0-bin-hadoop2.7/examples/jars/spark-examples_2.11-2.2.0.jar 100
在提交任务的时候可以指定cores 和 memory
./spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://hadoop:7077 \
--executor-memory 512m \
--total-executor-cores 1 \
/opt/app/spark-2.2.0-bin-hadoop2.7/examples/jars/spark-examples_2.11-2.2.0.jar 100
//其中--executor-memory 512m 为设置内存512M, --total-executor-cores 1: 设置总共使用1个核
运行结果
四 sparkShell
spark shell 是spark 自带的交互式程序, 可以方便的使用命令在shell进行交互式编程, 在shell中可以编写scala语句. scala语句可以在本地执行, 也可以提交给集群运行. 一般情况下, shell作为测试使用
spark -shell两个模式
- 本地模式[Local]: 在本地模拟启动一个spark-submit进程, 不会和集群有任何联系
- 集群模式[cluster]: 将任务提交到集群上运行,并且可以和集群进行交互
启动本地模式:在bin目录下执行spark-shell
启动集群模式: 在bin目录下执行
./spark-shell \
--master spark://hadoop:7077 \
--executor-memory 512m \
--total-executor-cores 1
//后两个命令不是必须的, 但是第二个命令是必须要有的, 是集群的位置, 要写内部端口
集群模式下, shell会在webUI界面下只有一个常驻
- 在这里需要注意的是退出spark-shell的时候不要用Ctrl+C, spark-shell开启后, 回启动一个进程来监控一直进行监控, 当使用Ctrl+C后, 这个进程并不会停止, 所以再次启动shell的时候会出现错误, 需要使用命令将这个进程杀死
netstat -apn | grep 4040 kill -9 进程号
五 spark2.2shell和spark1.6shell的对比
spark 2.2创建sparkcontext和sparksession对象的时候会告诉用户
spark 1.6创建sparkcontext和SQLcontext对象的时候不会告诉用户
六 Wordcount
6.1 集群模式版本
- 上传到hdfs一个文件word.txt
vi word.txt ------------------------ hello world hello zhangsan hello lisi hello wangwu this is a test file there are zhangsan lisi wangwu ------------------------ hdfs dfs -put /
sc.textFile("hdfs://hadoop:8020/word.txt").flatMap(_.split(" ")).map((_,1)).redcueByKey(_+_).saveAsTextFile("hdfs://hadoop:8020/out")
6.2 scala版本的Wordcount
-
maven中pom文件
<properties> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <encoding>UTF-8</encoding> <scala.version>2.11.8</scala.version> <spark.version>2.2.0</spark.version> <hadoop.version>2.7.1</hadoop.version> <scala.compat.version>2.11</scala.compat.version> </properties> <dependencies> <dependency> <groupId>org.scala-lang</groupId> <artifactId>scala-library</artifactId> <version>${scala.version}</version> </dependency><dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-core_2.11</artifactId> <version>${spark.version}</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>${hadoop.version}</version> </dependency> </dependencies> <build> <sourceDirectory>src/main/scala</sourceDirectory> <!--<testSourceDirectory>src/test/scala</testSourceDirectory>--> <plugins> <plugin> <groupId>net.alchim31.maven</groupId> <artifactId>scala-maven-plugin</artifactId> <version>3.2.2</version> <executions> <execution> <goals> <goal>compile</goal> <goal>testCompile</goal> </goals> <configuration> <args> <arg>-dependencyfile</arg> <arg>${project.build.directory}/.scala_dependencies</arg> </args> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>2.4.3</version> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> <configuration> <filters> <filter><artifact>*:*</artifact> <excludes> <exclude>META-INF/*.SF</exclude> <exclude>META-INF/*.DSA</exclude> <exclude>META-INF/*.RSA</exclude> </excludes> </filter> </filters> <transformers> <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <mainClass></mainClass> </transformer> </transformers> </configuration> </execution> </executions> </plugin> </plugins> </build>
-
SparkWordCount
import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* * @Description: java类作用描述 * ClassName SparkWordCount * @Author: WCH * @CreateDate: 2018/12/29$ 11:09$ * @Version: 1.0 */ class SparkWordCount { def main(args: Array[String]): Unit = { //模板封装成一个模板后调用即可 /** * 模板代码 * 需要创建SparkConf()对象 * 必传参数1 setAppName("")-->设置任务的名称, 不传默认是一个UUID产生的名字 * 必传参数2 setMaster("")设置运行模式(不写这个参数可以打包提交到集群, 写这个参数可以设置本地模式) * "local"-->本地一个线程进行处理 * "local[数值]"-->开启相应数值的线程来模拟spark集群运行任务 * "local[*]"-->当前程序中, 有多少空闲线程, 就使用多少线程类模拟spark集群运行任务 * */ val conf = new SparkConf().setAppName("SparkWordCount").setMaster("local") //创建sparkContext对象 val sc = new SparkContext(conf) //通过当前sparkContext对象处理数据 //读取文件, 参数是一个String类型的字符串, 传入的是一个路径 val lines: RDD[String] = sc.textFile(args(0)) //切分数据 val words: RDD[String] = lines.flatMap(_.split(" ")) //将每一个单词生成为元组 val tuples: RDD[(String, Int)] = words.map((_, 1)) //spark中提供了一个算子, reduceByKey, 相同的key为一组进行求和 val sumed: RDD[(String, Int)] = tuples.reduceByKey(_ + _) //对当前这个结果进行排序 sortBy()比scala中的sortBy()多了一个参数, 用来指定升序还是降序, 默认true是升序 val sorted: RDD[(String, Int)] = sumed.sortBy(_._2, false) //将数据提交到集群进行存储, 无返回值 sorted.saveAsTextFile(args(1)) //本地模式 //一定要设置setMaster() //可以直接打印 println(sorted.collect.toBuffer) //或者 sorted.foreach(println) //回收资源, 结束任务 sc.stop() } }
-
将代码打包上传到集群运行
./spark-submit \ --class Day00.SparkWordCount \ --master spark://hadoop:7077 \ --executor-memory 512m \ --total-executor-cores 1 \ /home/hadoop/data/Spark00-1.0-SNAPSHOT.jar hdfs://hadoop:8020/word.txt hdfs://hadoop:8020/out2
运行效果
查看结果
6.3 Java版本的Wordcount
package Day01;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.FlatMapFunction;
import org.apache.spark.api.java.function.Function2;
import org.apache.spark.api.java.function.PairFunction;
import scala.Tuple2;
import java.util.Arrays;
import java.util.Iterator;
public class JavaWordcount {
public static void main(String[] args) {
SparkConf conf = new SparkConf();
conf.setAppName("JavaWordCount");
//这里在提交到集群中时需要注释掉, 否则运行的是local模式
conf.setMaster("local[2]");
JavaSparkContext jsc = new JavaSparkContext(conf);
//获取数据
JavaRDD<String> lines = jsc.textFile("hdfs://192.168.91.100:8020/word.txt");
//切分
JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String, String>() {
@Override
public Iterator<String> call(String s) throws Exception {
return Arrays.asList(s.split(" ")).iterator();
}
});
//将单词生成元组
JavaPairRDD<String, Integer> tup = words.mapToPair(new PairFunction<String, String, Integer>() {
@Override
public Tuple2<String, Integer> call(String s) throws Exception {
return new Tuple2<String, Integer>(s, 1);
}
});
//聚合
JavaPairRDD<String, Integer> aggred = tup.reduceByKey(new Function2<Integer, Integer, Integer>() {
@Override
public Integer call(Integer v1, Integer v2) throws Exception {
return v1 + v2;
}
});
//spark 没有在JavaAPI中提供sortBy算子, 这里需要把元组中的数据对调一下再进行排序
JavaPairRDD<Integer, String> swaped = aggred.mapToPair(new PairFunction<Tuple2<String, Integer>, Integer, String>() {
@Override
public Tuple2<Integer, String> call(Tuple2<String, Integer> tup) throws Exception {
return tup.swap();
}
});
//排序
JavaPairRDD<Integer, String> sorted = swaped.sortByKey(false);
//将排序后的结果进行反转
JavaPairRDD<String, Integer> res = sorted.mapToPair(new PairFunction<Tuple2<Integer, String>, String, Integer>() {
@Override
public Tuple2<String, Integer> call(Tuple2<Integer, String> tup) throws Exception {
return tup.swap();
}
});
//返回的是一个数组 Return an array that contains all of the elements in this RDD.
System.out.println(res.collect());
//释放资源
jsc.stop();
}
}
运行效果
6.4 Lamda表达式版本的Wordcount
package Day01;
import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaPairRDD;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import scala.Tuple2;
import java.util.Arrays;
public class JavaLamdWC {
public static void main(String[] args) {
SparkConf conf = new SparkConf().setAppName("JavaLamdWC").setMaster("local[2]");
JavaSparkContext jsc = new JavaSparkContext(conf);
JavaRDD<String> lines = jsc.textFile("hdfs://hadoop:8020/word.txt");
JavaRDD<String> words = lines.flatMap(line -> Arrays.asList(line.split(" ")).iterator());
JavaPairRDD<String, Integer> tup = words.mapToPair(word -> new Tuple2<>(word, 1));
JavaPairRDD<String, Integer> aggred = tup.reduceByKey((v1, v2) -> v1 + v2);
JavaPairRDD<Integer, String> swaped = aggred.mapToPair(tuple -> tuple.swap());
JavaPairRDD<Integer, String> sorted = swaped.sortByKey(false);
JavaPairRDD<String, Integer> res = sorted.mapToPair(tuple -> tuple.swap());
System.out.println(res.collect());
res.saveAsTextFile("hdfs://hadoop:8020/output");
jsc.stop();
}
}
运行结果