Windows Docker Desktop安装spark并建立集群运行简单的Java词汇统计Maven项目

确保你已经安装了Docker Desktop for Windows。接下来,我们将使用Bitnami的Spark Docker镜像创建一个简单的Spark集群,并在该集群上运行一个简单的程序。

一、拉取镜像

打开Windows PowerShell命令窗口界面,确保你已经运行docker了,拉取Bitnami的Spark镜像:

docker pull bitnami/spark:latest

二、创建一个docker网络

创建一个docker网络,方便容器之间通信:

docker network create spark-network

三、启动Spark Master节点

这是一个Docker命令,用于运行一个名为"spark-master"的容器。

docker run -d --name spark-master --network spark-network -p 4040:4040 -p 8080:8080 -p 7077:7077 bitnami/spark:latest bin/spark-class org.apache.spark.deploy.master.Master

让我们详细解释一下这个命令的各个部分:

  1. docker run: Docker命令用于启动一个新的容器。
  2. -d: 这个参数表示容器将以"detached"模式运行,即在后台运行。
  3. --name spark-master: 为创建的容器分配一个名称,这里将其命名为"spark-master"。
  4. --network spark-network: 将容器连接到一个名为"spark-network"的网络。如果这个网络不存在,你需要先创建它。
  5. -p 4040:4040 -p 8080:8080 -p 7077:7077: 这些参数将容器的端口映射到宿主机的端口。格式为-p 宿主机端口:容器端口。在这个例子中,映射了三个端口:4040,8080和7077。
  6. bitnami/spark:latest: 使用的Docker镜像。在这里,我们使用了Bitnami提供的最新版本的Apache Spark镜像。
  7. bin/spark-class org.apache.spark.deploy.master.Master: 容器启动后执行的命令。这个命令会启动Apache Spark的Master节点。

总之,这个命令会创建并运行一个名为"spark-master"的Docker容器,使用Bitnami的最新Apache Spark镜像,并将其连接到名为"spark-network"的网络。同时,映射了容器的4040、8080和7077端口到宿主机的相应端口。在容器启动后,将运行命令以启动Apache Spark的Master节点。

运行后你会在docker界面看到这个容器已经开始跑了,如下图所示:

docker desktop 是仓库吗 docker desktop service_spark

四、获取Spark master的IP地址

方法一:

如果这种方法不行,请使用方法二。

docker inspect -f "{{ .NetworkSettings.Networks.spark-network.IPAddress }}" spark-master

方法二:

①首先,运行以下命令来获取 Spark master 的容器 ID,如下图所示,返回一串字符

docker ps -aqf "name=spark-master2"

docker desktop 是仓库吗 docker desktop service_docker_02

这将返回 Spark master 的容器 ID。将此 ID 替换为以下命令中的 <container_id>,如下图所示。

docker inspect <container_id> | ConvertFrom-Json | % { $_.NetworkSettings.Networks.'spark-network'.IPAddress }

docker desktop 是仓库吗 docker desktop service_java_03

这个命令将正确解析并返回 Spark master 的 IP 地址。

记下IP地址,这将在创建worker节点时使用。

五、启动Spark worker节点

替换<MASTER_IP>为你在上一步中获得的Spark master IP地址。

docker run -d --name spark-worker --network spark-network -e SPARK_MASTER=spark://<MASTER_IP>:7077 bitnami/spark:latest bin/spark-class org.apache.spark.deploy.worker.Worker spark://<MASTER_IP>:7077

通过浏览器访问http://localhost:8080,确认master和worker节点已成功运行。

docker desktop 是仓库吗 docker desktop service_spark_04

六、创建简单的Java程序测试Spark集群

①创建一个maven项目

使用IDEA创建一个maven项目,File -> New -> Project -> Maven

docker desktop 是仓库吗 docker desktop service_docker_05

②在pom.xml文件添加相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>wordcount</artifactId>
    <version>1.0-SNAPSHOT</version>
    
    <dependencies>
        <!-- Spark Core -->
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-core_2.12</artifactId>
            <version>3.2.0</version>
        </dependency>

        <!-- Spark SQL -->
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql_2.12</artifactId>
            <version>3.2.0</version>
        </dependency>

        <dependency>
            <groupId>org.codehaus.janino</groupId>
            <artifactId>janino</artifactId>
            <version>3.1.4</version>
        </dependency>
    </dependencies>

    <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>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

②创建一个名为WordCount.java的Java类文件,并添加以下内容:

docker desktop 是仓库吗 docker desktop service_docker desktop 是仓库吗_06

import org.apache.spark.SparkConf;
import org.apache.spark.api.java.JavaRDD;
import org.apache.spark.api.java.JavaSparkContext;
import org.apache.spark.api.java.function.FlatMapFunction;

import java.util.Arrays;

/**
 * 统计词汇个数
 */
public class WordCount {
    public static void main(String[] args) {
        SparkConf conf = new SparkConf().setAppName("wordCount").setMaster("spark://<MASTER_IP>:7077");
        JavaSparkContext sc = new JavaSparkContext(conf);

        JavaRDD<String> input = sc.textFile("/data/input.txt");
        JavaRDD<String> words = input.flatMap((FlatMapFunction<String, String>) x
                -> Arrays.asList(x.split(" ")).iterator());
        JavaRDD<String> distinctWords = words.distinct();

        long wordCount = distinctWords.count();
        System.out.println("Distinct word count: " + wordCount);

        sc.stop();
    }
}

记得将 <MASTER_IP> 替换为你在之前步骤中获取的 Spark master IP 地址。

七、打包成jar包

点击IDEA下方的终端,在界面中输入下面命令进行打包

mvn clean package

docker desktop 是仓库吗 docker desktop service_spark_07

然后你就可以在这个位置找到jar包,如下图所示:

docker desktop 是仓库吗 docker desktop service_apache_08

八、提交该jar包到Spark集群运行

①准备数据

在上一步jar包的位置新建一个input.txt文件,里面放我们需要统计单词的内容

hello world
hello docker
hello how are you
I am fine
you are good

docker desktop 是仓库吗 docker desktop service_docker_09

②将jar包和数据复制到容器中

在jar包这个界面,按住shift并右键,选择打开Powershell窗口

docker desktop 是仓库吗 docker desktop service_java_10

可能你的spark-master容器还没有/data该目录,可以使用下面这个命令创建/data目录:

docker exec -u root -it spark-master mkdir -p /data

将生成的 JAR 文件复制到 Spark master 容器的 /data 目录:

docker cp ./wordcount-1.0-SNAPSHOT.jar spark-master:/data

input.txt 文件复制到 Spark master 容器的 /data 目录:

docker cp ./input.txt spark-master:/data

这里注意了哈,下面是将input.txt文件复制到worker容器中,之前我没复制到这个工作节点,运行后会出现input.txt该文件不存在的情况

input.txt 文件复制到 Spark worker容器的 /data 目录:

docker cp ./input.txt spark-worker:/data

可能你的spark-worker容器还没有/data该目录,可以使用下面这个命令创建/data目录:

docker exec -u root -it spark-worker mkdir -p /data

③提交到spark集群运行

你们需要将172.18.0.2替换成之前获取到的IP地址

docker exec -it spark-master /opt/bitnami/spark/bin/spark-submit --class com.example.WordCount --master spark://172.18.0.2:7077 /data/wordcount-1.0-SNAPSHOT.jar

这是一个Docker命令,用于在名为"spark-master"的已运行容器中执行一个Apache Spark作业提交。让我们详细解释一下这个命令的各个部分:

  1. docker exec: Docker命令用于在运行中的容器中执行命令。
  2. -it: 这两个参数表示分配一个伪终端(-t)并保持标准输入(stdin)开启(-i),以便与容器进行交互。
  3. spark-master: 容器的名称,我们在这里执行命令的容器名为"spark-master"。
  4. /opt/bitnami/spark/bin/spark-submit: 容器内的spark-submit命令的路径。spark-submit是Apache Spark用于提交作业的命令行工具。
  5. --class com.example.WordCount: 指定作业的主类,这里是com.example.WordCount
  6. --master spark://172.18.0.2:7077: 指定Spark作业的Master URL,这里是spark://172.18.0.2:7077。这是Spark集群中Master节点的地址和端口。
  7. /data/wordcount-1.0-SNAPSHOT.jar: 作业的JAR文件路径。这里使用的是/data/wordcount-1.0-SNAPSHOT.jar

总之,这个命令会在名为"spark-master"的Docker容器中执行一个Apache Spark作业提交。该作业的主类是com.example.WordCount,Master URL为spark://172.18.0.2:7077,作业的JAR文件路径为/data/wordcount-1.0-SNAPSHOT.jar

九、结果

提交到spark运行后,命令窗口就是一顿日志输出,我们可以在里面找到我们想要的数据:

docker desktop 是仓库吗 docker desktop service_docker desktop 是仓库吗_11

上面结果显示是单词的数量是10,我们之前的数据如下所示,重复的算一个,三个hello看作是一个单词,那刚好是10个不同的单词,成功运行,如果需要统计更大的数据,应该需要添加多个worker节点到集群中。

docker desktop 是仓库吗 docker desktop service_docker_12