1、下载Spark
解压下载文件,可以看到
examples,其中可以找到很多经典的范例。
这里我们使用java版本:
spark-2.1.0-bin-hadoop2.6\examples\src\main\java\org\apache\spark\examples
2、这里我们仿照JavaWordCount.java自己来敲一遍代码,找找感觉
这里一步步的来,完整代码放最下面了
1、首先是初始化SparkContext。
在spark2.1.0版本中推荐使用SparkSession来初始化,这里为了明显的体现出SparkConf,采用new的方式。
1.1、设置SparkConf
Spark的配置属性都是以“spark.”开头的字符。在初始化时,会自动加载所有以spark.开头的系统属性。
SparkConf里能设置的属性很多,目前还没能找到一个比较全面的介绍,这个后续再说
-
SparkConf sparkConf = new SparkConf();
sparkConf.set("spark.app.name", "JavaWordCount");
- //采用local模式执行[4]表示使用四个cpu核(因为本人的机器是四核的哦)
sparkConf.set("spark.master", "local[4]");
- // 设置本地缓存目录,默认为/tmp,window下是C://tmp(本人很讨厌王C盘下胡乱添加东西的行为,所以这里色孩子为D盘)
sparkConf.set("spark.local.dir", "D:\\cloud\\spark\\tmp");
//设置executor占用的内存大小,默认512m,最小450m(如果没有单位,默认是B)
//也可用系统变量SPARK_EXECUTOR_MEMORY或者SPARK_MEM设置
sparkConf.set("spark.executor.memory","450m");
//配置TaskScheduler(任务调度)模式(有FAIR和FIFO两种,默认为FIFO)
sparkConf.set("spark.scheduler.mode", "FIFO");
// 默认分区数(这里设置为和能够使用的cup核数相同最好(如果不设置,会有一套默认值判断的逻辑,以后再讨论))
sparkConf.set("spark.default.parallelism", "4");
// 是否启动sparkUI,默认为true,如果启动了UI,可以在浏览器通过地址直接调用(本机执行就没必要耗费额外的资源了,这里关闭)
// SparkUI: Bound SparkUI to 0.0.0.0, and started at http://172.21.133.102:4040
sparkConf.set("spark.ui.enabled", "false");
// 是否允许sprakUi被kill,默认为true
//sparkConf.set("spark.ui.killEnabled", "true");
// sprakUi端口(默认端口4040)
//sparkConf.set("spark.ui.port", "8080");
1.2、创建SparkContext
SparkContext可以看做spark应用程序的引擎,而SparkConf则是这个引擎运行时设置参数的一个“面板”。
-
// 创建SparkContext
JavaSparkContext ctx = new JavaSparkContext(sparkConf);
虽然这里只是new了一个对象,但实际上背后有很多的工作,这里列一下,不做分析:
2)创建RDD清理器metadataCleaner;
3)创建并初始化Spark UI;(spark.ui.enabled=true时)
4)Hadoop相关配置及Executor环境变量的设置;
8)初始化块管理器BlockManager(BlockManager是存储体系的主要组件之一)
10)创建和启动Executor分配管理器ExecutorAllocationManager;
13)创建DAGSchedulerSource和BlockManagerSource;
2、接下来创建RDD(Creation Operation)
先拷贝一段RDD的概念:
RDD,全称为Resilient Distributed Datasets,是一个容错的、并行的数据结构,可以让用户显式地将数据存储到磁盘和内存中,并能控制数据的分区。同时,RDD还提供了一组丰富的操作来操作这些数据。在这些操作中,诸如map、flatMap、filter等转换操作实现了monad模式,很好地契合了Scala的集合操作。除此之外,RDD还提供了诸如join、groupBy、reduceByKey等更为方便的操作(注意,reduceByKey是action,而非transformation),以支持常见的数据运算。
RDD的一些特性(如分区、款依赖、窄依赖等)这里不去涉及
在这个例子里,JavaRDD
<
String
>
lines
可以看做是一个string数组,每一个数组元素对应文件里的一个行。
-
String filePath = args[0];
// 创建:创建RDD
JavaRDD<String> lines = ctx.textFile(filePath);
这里如果没有设置Hadoop环境变量的话,会抛出一个异常:
-
java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries.
不过这里不用管,因为这个例子里我们实际上并没有用到Hadoop。
3、接下来对RDD进行一系列的转换(Transformation Operation)操作
RDD转换操作方法有map、flatMap、mapToPair等等,这里我们只介绍word count 用到的
3.1、
flatMap:
每个元素输入项都可以被映射到0个或多个的输出项,最终将结果”扁平化“后输出
这里用来将输入文件里每一行中包含的单词都拆分出来,最终形成一个word集合
-
// 将lines里每个元素(line)按空格拆分为一个个word,组成新的RDD
// 转换-flatMap:每个元素输入项都可以被映射到0个或多个的输出项,最终将结果”扁平化“后输出
JavaRDD<String> words = lines.flatMap(new FlatMapFunction<String,String>(){
private static final long serialVersionUID = 1L;
@Override
public Iterable<String> call(final String line) throws Exception {
return Arrays.asList(SPACES.split(line.trim()));
}
});
3.2、 mapToPair
:每个元素输入都被映射到一个key-value格式的输出项