吹静静

欢迎QQ交流:592590682

内容简介

本篇文章主要讲述了Springboot项目和Spark相结合的方法。

在Spark的学习过程中,我们大多数提交作业的方式都是使用Spark的命令来提交jar包并运行,但是本次相反,我们将使用Springboot来开发Spark的相关计算任务代码,开发完成后将项目打包部署到服务器上,项目启动以后会生成一个SparkSession的长服务,各种请求可通过http来调用项目中相关的接口,再来调用Spark来进行计算。

环境准备

安装好Spark环境,单节点、集群都可以,如果是集群,则要保证节点之间的端口通信正常。

Spark版本要和代码中的Spark版本相同。

如果使用集群,则需要一个Nginx,做反向代理,用来分发项目包到各个节点。

server {
    listen       30443 default_server;
    server_name  _;

    location /jar/ {
        alias /opt/jar/;     // 放项目包的目录
    }

    location / {
        return 502;
    }
}

代码实现

POM文件只放打包相关的,依赖的包各不相同。

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.7.RELEASE</version>
                <configuration>
                    <includeSystemScope>true</includeSystemScope>
                    <mainClass>com.xxx.xxx.TestApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

创建SparkSession长服务实现代码:

import lombok.extern.slf4j.Slf4j;
import org.apache.spark.SparkConf;
import org.apache.spark.sql.SparkSession;
import org.apache.spark.sql.UDFRegistration;
import org.apache.spark.sql.types.StructType;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.Map;

@Service
@Slf4j
public class SparkService implements DisposableBean, InitializingBean {
    private SparkSession session = null;

    public SparkSession session() {
        return session;
    }

    @Override
    public void afterPropertiesSet() {
        try {
            log.info("正在创建Spark Session......");
            SparkConf config = new SparkConf();
            config.setAppName(getClass().getSimpleName());
            config.setMaster("spark://bigdata1:7077");
            config.setJars(new String[]{ "http://bigdata1:30543/jar/Test-1.0-SNAPSHOT.jar.original" });
            config.set("spark.executor.cores", "2");  // 每个executor占用的核心数
            config.set("spark.driver.memory", "2g");
            config.set("spark.driver.cores", "2");
            config.set("spark.executor.memory", "2g");
            config.set("spark.default.parallelism", "8");  // 任务并行度
            session = SparkSession.builder().config(config).getOrCreate();
        } catch (Exception e) {
            log.error("Spark Session创建失败!!!");
            e.printStackTrace();
        }
    }

    @Override
    public void destroy() {
        FileUtil.close(session);
    }

    // 注册自定义UDF
    public SparkSession udf(SparkSession session) {
        UDFRegistration udf = session.udf();
        udf.register(ToCharUDF.NAME, new ToCharUDF(), ToCharUDF.TYPE);
        udf.register(AgeUDF.NAME, new AgeUDF(), AgeUDF.TYPE);
        udf.register(NullIfUDF.NAME,new NullIfUDF(), NullIfUDF.TYPE);
        udf.register(DatePartEpochUDF.NAME,new DatePartEpochUDF(), DatePartEpochUDF.TYPE);
        udf.register(ToNumberUDF.NAME,new ToNumberUDF(), ToNumberUDF.TYPE);
        return session;
    }
}

当需要用到Spark时先将上面的类注入:

    @Autowired
    public SparkService sparkService;

再创建一个新的session:

SparkSession session = sparkService.session().newSession(); // 没有注册自定义UDF函数
SparkSession sparkSession = sparkService.udf(session);      // 注册没有自定义UDF函数

部署运行

再说项目打包相关事宜,一共会打两个项目包,一个是以“.jar”结尾,另一个是以“.jar.original”结尾。

还要导出所有项目相关依赖的jar包放到Spark /jars目录下,使用下面命令即可:

mvn dependency:copy-dependencies

但是需要注意,自己导出来的包可能会和Spark的jars目录下的包有冲突,此时要以项目里的依赖版本为准,如果删除Spark中的冲突依赖之后导致Spark服务无法启动,则需要调整项目中引用的依赖版本向Spark服务靠齐。

做完以上几步之后就可以启动spark服务,启动项目(命令:java -jar xxx)即可。

posted on 2022-12-20 22:34  吹静静  阅读(219)  评论(0编辑  收藏  举报