saprk及scala环境搭建

*1.本地idea配置scala*

访问scala官网下载scala安装包,windows和linux都需要。

在这里插入图片描述

先配置本地scala,解压scala-{版本号}.zip文件配置环境变量,和jdk一样。

SCALA_HOME->new %SCALA_HOME%=”解压路径”

PATH->添加%SCALA_HOME%/bin;

Win+R,输入scala可以运行就配置成功。

打开idea->File->Settings->plugins

在这里插入图片描述

从本地选择插件安装

在idea官网上可以找到scala的相关插件,自行选择版本

https://plugins.jetbrains.com/plugin/1347-scala

安装完创建maven项目,要么从pom中导入scala相关jar包,要么右键点击项目

在这里插入图片描述

在里面找到scala手动添加##每个项目都需要手动添加,嫌麻烦就在pom里导入jar包依赖

右键main文件夹->new dictionary “scala”->右键scala文件夹->Mark Dictionary as->source root

这样把新创建的scala文件夹作为了项目的代码根文件夹。

创建package->new scala object->scala需要选择object创建。

在这里插入图片描述

下面展示一些 内联代码片

object wordcount {
  def main(args: Array[String]): Unit = {
Printf(hello world!)
}
}

先来个helloworld,scala换行就相当于分号了,除非两条代码在同一行需要分号隔开,其他情况基本不需要分号,当然写了不会报错。

至此scala算是完事儿了。

*2.编写spark第一个wordcount程序*

*Pom依赖*

Pom中引入相关依赖,务必刷新maven下载jar包。

<dependencies>
    <dependency>
<!--  引入sparkjar    -->
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-core_2.12</artifactId>
        <version>2.4.6</version>
    </dependency>
    <dependency>
<!--  引入scala依赖,就不用再手动添加插件了    -->
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-library</artifactId>
        <version>2.12.8</version>
    </dependency>
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-reflect</artifactId>
        <version>2.12.8</version>
    </dependency>
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-compiler</artifactId>
        <version>2.12.8</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
<!--  scala的编译相关插件    -->
            <groupId>net.alchim31.maven</groupId>
            <artifactId>scala-maven-plugin</artifactId>
            <version>3.2.2</version>
            <executions>
                <execution>
                    <id>scala-compile-first</id>
                    <phase>process-resources</phase>
                    <goals>
                        <goal>add-source</goal>
                        <goal>compile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.scala-tools</groupId>
            <artifactId>maven-scala-plugin</artifactId>
            <version>2.15.2</version>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>testCompile</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

*遇到问题*

大坑!一开始安装最新的scala2.13.3,这沙雕版本不兼容spark2.4.6,一直报错

Exception in thread “main” java.lang.NoSuchMethodError: scala.util.matching (Java String,Java Long/Scala String,Scala Long)V

Exception in thread “main” java.lang.NoClassDefFoundError: scala/Cloneable

就出大问题,这个类型的问题就是版本不兼容,把scala换成2.12.x版本的,spark3.4.5或者3.4.6都可以兼容。版本匹配了还报错需要检查

File->project structure->Global Libraries有可能是scala早就配置好了,删除了重新加载或者手动添加正确版本。

*编写程序*

编写一个spark程序测试。

object wordcount {
  def main(args: Array[String]): Unit = {
//链接spark所需配置文件,Master("local")->仅idea运行spark,AppName->进程名
    val sparkConf = new SparkConf().setMaster("local").setAppName("WordCount1")
    //创建链接和关闭链接
val sc = new SparkContext(sparkConf)
    sc.stop()
  }
}

运行如果报之前提到的错误就是scala和spark版本不匹配,换匹配的版本就行了。

报Failed to locate the winutils binary in the hadoop binary path是找不到本地的hadoop环境

把hadoop.tar.gz解压了再配置环境变量就行。没必要配置文件,能让程序找到hadoop的环境就行。

如果非要让hadoop在windows运行一个本地版本。

因为hadoop默认是不兼容windows的,需要下载一个winutils插件。

https://github.com/steveloughran/winutils

在这里下载一个合适的版本,大版本一致就行,比如你是2.7.5就可以用2.7.1。解压后用新的bin目录把hadoop/bin替换掉,然后配置hadoop/etc/hadoop/里的配置文件。

在这里插入图片描述

这些INFO都是spark的日志信息,虽然是红的但是没有ERROR就算成功。

可以编写spark相关的计算逻辑了。

在这里插入图片描述

创建文件夹和两个txt文件,随便弄几个不同的单词

object wordcount {
  //链接spark所需配置文件,Master("local")->仅idea运行spark,AppName->进程名
  def main(args: Array[String]): Unit = {
    val sparkConf = new SparkConf().setMaster("local").setAppName("WordCount1")
    val sc = new SparkContext(sparkConf)
    //TODO 读取目录下的文件
    //RDD 是spark的计算单位,弹性数据集
    val fileRDD: RDD[String] = sc.textFile("input")
    //TODO spark自动按行切分,再每行按空格切分单词
    val wordRDD: RDD[String] = fileRDD.flatMap(line => {line.split(" ")})
    //TODO 将数据分组,就按照单词进行分组,每组一个Iterable迭代器
    val groupRDD: RDD[(String,Iterable[String])] = wordRDD.groupBy(word=>word)
    //TODO 分组后统计完成合并,把Iterable计数就行
    val mapRDD: RDD[(String,Int)] = groupRDD.map {
      case (word, iter) => {
        (word, iter.size)
      }
    }
    //TODO 采集结果打印控制台,把RDD采集成数组
    val wordCountArray: Array[(String,Int)] = mapRDD.collect()
    println(wordCountArray.mkString(","))
    sc.stop()
  }
}

结果正确

在这里插入图片描述

红色日志信息很烦,取消spark的日志信息。Resource下创建一个log4j.properties

log4j.rootLogger=ERROR, console
log4j.logger.com.test=DEBUG
log4j.logger.org=ERROR
log4j.logger.org.apache.spark=ERROR
log4j.logger.org.spark-project=ERROR
log4j.logger.org.apache.hadoop=ERROR
log4j.logger.io.netty=ERROR
log4j.logger.org.apache.zookeeper=ERROR
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n

*优化计算逻辑*

原逻辑:按行读取,按单词切分,把相同单词放入同一个迭代器,统计迭代器size,打印控制台。

优化后逻辑:按行读取,按单词切分,把单词转换为(单词,数量)的kv格式(默认数量为1),合并时直接把数量求和,打印求和结果即可,省略了迭代器的步骤。

object wordCount2 {
  def main(args: Array[String]): Unit = {
    val sparkConf = new SparkConf().setMaster("local").setAppName("WordCount2")
    val sc = new SparkContext(sparkConf)
    //TODO 读取目录下的文件
    //RDD 是spark的计算单位,弹性数据集
    val fileRDD: RDD[String] = sc.textFile("input")
    //TODO spark自动按行切分,再每行按空格切分单词
    val wordRDD: RDD[String] = fileRDD.flatMap(line => {line.split(" ")})
    //TODO 对粉刺后的数据进行结构转换
    val mapRDD: RDD[(String,Int)] = wordRDD.map(word => (word, 1))
    //TODO 分组聚合,根据单词分组,对value聚合
    val wordToSumRDD: RDD[(String,Int)] = mapRDD.reduceByKey(_ + _)
    //TODO 打印控制台
    val wordCountArray: Array[(String,Int)] = wordToSumRDD.collect()
    println(wordCountArray.mkString(","))
    sc.stop()
  }
}

项目分层

把spark的WordCount项目分为Dao-Service-Controller三层

其中dao负责数据交互,Service是数据分析逻辑,Controller负责控制wordcount

编写一个框架->简化spark链接和关闭链接的步骤

New->package->core

New->Tapplication,Tcontroller,TService,TDao,类型为trait

TApplication中将业务逻辑抽象处理,负责创建链接、关闭链接,之后只需要object wordcount with TApplication即可。

trait TApplication {
  var envData : Any = null;
  //创建链接
  def start(t:String = "jdbc")(op : =>Unit) : Unit={
    if(t=="spark"){
      val sparkConf = new SparkConf().setMaster("local").setAppName("WordCount1")
      envData = new SparkContext(sparkConf)
    }
    //业务抽象
    try{
      op
    }catch {
      case ex: Exception=> println(ex.getMessage)
    }
    //关闭链接
    if(t=="spark"){
      val sc :SparkContext = envData.asInstanceOf[SparkContext]
      sc.stop()
    }  }
}
trait TController {  def excute():Unit }
trait TDao {def readFile(path:String):RDD[String] = {  EnvUtil.getEnv().textFile(path) } }

Wordcount暂时不需要数据交互,所以Dao层为空。
Controller层放置相关控制函数。

class wordCountController extends TController{
  private val wordCountService=new wordCountService
  override def excute(): Unit = {
    val wordCountArray: Array[(String,Int)] = wordCountService.analysis()
    println(wordCountArray.mkString(","))
  }
}

Service层中放置实际的数据处理逻辑

class wordCountService extends TService{
    private val wordCountDao = new wordCountDao
  override def analysis(): Array[(String, Int)] = {
    val fileRDD: RDD[String] = wordCountDao.readFile("input")
    val wordRDD: RDD[String] = fileRDD.flatMap(line => {line.split(" ")})
    val mapRDD: RDD[(String,Int)] = wordRDD.map(word => (word, 1))
    val wordToSumRDD: RDD[(String,Int)] = mapRDD.reduceByKey(_ + _)
    val wordCountArray: Array[(String,Int)] = wordToSumRDD.collect()
    return wordCountArray
  }

在application中只需要调用controller即可

在这里插入图片描述

*3.配置spark集群*

rz命令发送spark.tar.gz文件至三个节点,解压,配置环境变量。

cd spark-3.4.6/conf

mv spark-env.sh.template spark-env.sh

*编辑spark-env.sh*

export SCALA_HOME=/usr/local/bigdata/scala
export JAVA_HOME=/usr/local/bigdata/java/jdk1.8.0_211
export HADOOP_HOME=/usr/local/bigdata/hadoop-2.7.1
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
SPARK_MASTER_IP=Master
SPARK_LOCAL_DIRS=/usr/local/bigdata/spark-2.4.3
SPARK_DRIVER_MEMORY=512M

实际路径根据自身安装路径来。

*配置yarn-site.xml*

添加两条属性,用于检查应用的物理/虚拟内存,超过后不杀死进程(默认是true,会杀死进程)

<property>
        <name>yarn.nodemanager.pmem-check-enabled</name>
        <value>false</value>
</property>
<property>
        <name>yarn.nodemanager.vmem-check-enabled</name>
        <value>false</value>
</property>

重启hadoop,重启yarn。

rz发送scala.tart.gz安装包,解压,配置scala环境变量,scala -version 测试。

在确认hadoop和yarn启动后,启动spark,主节点上执行以下命令。因为spark和hadoop都有start-all.sh文件,所以最好切换spark目录执行。然后在主节点上启动spark客户端

./spark-3.4.6/sbin/start-all.shspark-shell --master spark://hadoop01:7077

*Spark测试*

执行一个spark自带的example测试一下,先本地试运行一下。

spark-submit \
--class org.apache.spark.examples.SparkPi \
--master local \
./spark-2.4.6/examples/jars/spark-examples_2.11-2.4.6.jar 10

在这里插入图片描述

然后再从yarn上运行,记得将master的参数改为yarn

spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
./spark-2.4.6/examples/jars/spark-examples_2.11-2.4.6.jar 10

spark非常占用内存,yarn运行时务必给节点足够的内存,不然容易报错。

在这里插入图片描述

这里数值有问题是他算法的问题,忽略这个细节。真实环境中一般都用yarn,但是自己虚拟机使用yarn会非常卡,酌情使用。

至此spark开发环境已经搭建完成,进一步学习编写spark项目请移步spark实战项目开发
实战项目中使用的数据下载
实战项目源码下载
大数据hadoop环境搭建教程
apache手动搭建
CDH快速搭建

posted @ 2020-08-21 14:56  鹤望兰号  阅读(176)  评论(0)    收藏  举报