用JavaScript编写Apache Spark程序
2020年3月19日
Apache Spark支持使用Scala,Java,Python和R等多种语言进行编程。这种多语言支持使Spark可以广泛用于各种用户和用例。
并非Spark支持的所有语言都具有相同的API支持。Scala和Java支持完整的面向用户和库开发API。Python和R仅限于面向用户的API。存在这种差异是因为以一种语言添加对新API的支持需要进行大量工作。因此,唯一必不可少的API已移植到所有语言。
如果我们想添加对Spark的新语言的支持怎么办?传统方法将需要大量工作。但是,借助GraalVM,我们可以以最小的努力访问全新语言的整套Spark库。
GraalVM
GraalVM是一个多语言VM,允许用户在同一VM上运行多种语言。它不仅支持多种语言,还允许用户将来自不同语言的库引入单个平台。您可以在此处阅读有关graalvm的更多信息。
GraalVM的引人入胜的部分之一是可以使用任何其他受支持语言的Java库。JavaScript是具有Node.js支持的GraalVM的一等公民。那让我开始思考,如果我能够使用它在Node.js上运行spark,该怎么办。如果我能够做到这一点,那么我基本上有一个适用于Apache Spark的JavaScript API。
让我们看看我们如何去做。
在GraalVM上运行Node.js的设置
帖子的这一部分我们讨论如何在GraalVM上设置Node.js。
下载GraalVM二进制文件
要在GraalVM上运行Node.js程序,我们需要下载graalvm二进制文件。您可以从下面的链接下载适当的一个
https://www.graalvm.org/downloads/
启动Node.js解释器
下载graalvm后,您可以使用以下命令启动Node.js解释器
bin/node --jvm
该-jvm选项是说,我们要在JVM模式下运行。如果我们不指定模式,它将在本机模式下运行,本机模式经过优化,但没有多语言功能。
一旦运行上面的命令,您应该显示以下输出
Welcome to Node.js v12.15.0.
Type ".help" for more information.
>
运行示例节点代码
拥有Node解释器后,您可以运行hello world代码来查看您是否确实在运行Node.js环境。
console.log("Hello World");
它将输出
hello world
现在,我们在JVM上运行Node.js。
为Node.js环境设置Spark
设置Node.js环境后,我们需要为其设置Spark环境。本文档的这一部分讨论了各个步骤。
下载Spark Binary
我们需要从下面的链接下载Spark Binary,并将其路径设置为SPARK_HOME。
https://spark.apache.org/downloads.html
您可以使用以下命令检查是否设置了SPARK_HOME
echo $SPARK_HOME
将所有Spark JARS添加到类路径
为了从Node.js访问Spark,我们需要将其所有jar添加到JVM类路径中。当前GraalVM不允许我们向其类路径添加目录。因此,我们将使用下面的shell脚本生成一个字符串,其中所有jar都将包含在spark二进制文件中。
CLASSPATH=$(find "$SPARK_HOME/jars/" -name '*.jar' | xargs echo | tr ' ' ':')
上面的命令生成一个包含所有jar的字符串,并将其存储在CLASSPATH环境变量中
将Classpath传递给Node.js
CLASSPATH变量准备好后,我们可以将类路径传递给GraalVM,如下所示
bin/node --jvm --vm.cp $CLASSPATH
现在,我们已经为火花准备好了环境。
用JavaScript进行Spark编程
博客的这一部分将讨论如何使用JavaScript编写Spark程序。
加载SparkSession类
任何spark程序的第一步都是创建一个spark会话。
但是在创建Spark Session之前,我们需要导入该类。在GraalVM中,这意味着我们需要使该类可用于JavaScript。下面的代码执行相同的操作。
var sparkSessionType = Java.type("org.apache.spark.sql.SparkSession")
在上面的代码中,我们使用Java.type API将给定的Java类导入JavaScript。
创建SparkSession
导入Spark会话后,现在我们可以使用以下代码创建Spark会话。
var sparkSession = sparkSessionType.builder().master("local[*]").appName("example").getOrCreate()
上面的代码看起来几乎像Scala代码一样,尽管它是用JavaScript编写的。
加载数据中
创建Spark会话后,现在就可以使用它加载数据了。用系统中的csv替换路径。
var data = sparkSession.read().format("csv").option("header","true").load("<path to your csv>")
同样,代码看起来完全像Scala。但是要注意的一件事是阅读。在Scala中,它是SparkSession类的val 。但是在JavaScript中,它被视为函数。因此,当我们在GraalVM中使用任何Java / Scala库时,所有公共属性都将成为JavaScript中的零参数方法。
打印数据
data.show()
加载数据后,将使用上述方法显示数据样本。
运行示例
将以上代码保存在名为server.js的文件中。然后运行以下命令
bin/node --jvm --vm.cp $CLASSPATH server.js
现在,您可以看到火花在Node.js内部运行并打印csv示例。
我们成功地用JavaScript编写了我们的第一个spark程序。
通过Node.js HTTP服务器提供服务架构
到目前为止,我们只编写了火花代码。让我们将其与Node.js代码混合使用。这显示了整合的真正力量。当用户在Node.js上获取请求时,以下代码将打印数据框的架构
const http = require("http");
http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/html"});
response.end(data.schema().prettyJson());
}).listen(8000, function() { console.log("Graal.js server running at http://127.0.0.1:8000/"); });
将以上代码添加到server.js并再次运行,将在8000端口启动Web服务器。当您访问http://127.0.0.1:8000/时,您将看到数据集的架构。
这显示了我们如何在同一台VM上混合Node代码和spark。
代码
您可以在github上访问完整的代码。
参考文献
https://medium.com/graalvm/using-testcontainers-from-a-node-js-application-3aa2273bf3bb