题 如何在本地调试spark应用程序?


我很新兴,我想逐步学习如何在本地调试spark应用程序?有谁可以详细说明这样做的步骤?

我可以从命令行在本地运行spark网站上的simpleApp,但我只需要逐步完成代码并查看它是如何工作的。很感谢任何形式的帮助。谢谢。


33
2018-05-22 18:37


起源


我真的不知道'学习调试'是什么意思。您可以在本教程中查看如何在IntelliJ ide中本地设置spark docs.sigmoidanalytics.com/index.php/...。 - abalcerek
我的意思是“如何在spark网站上单步执行SimpleApp应用程序。有SimpleApp.java文件和pom.xml(在spark网站上编码)。如何使用Intellij IDE逐行执行SimpleApp.java中的代码并查看每行实际执行的操作?我希望能够在不将作业发送到集群的情况下执行此操作。我只想在本地笔记本电脑上单步执行代码。您提供的链接提供了使用IntelliJ IDEA构建Spark App的步骤。如何逐行执行代码?非常感谢任何帮助。谢谢。 - ekardes
我不知道scala,但至少在java中你可以使用标准的IDEA调试器(在本地模式下)。有一件事你必须记住,如果你有大集合,你将不得不迈出所有元素。 - abalcerek


答案:


正如大卫格里芬所说,使用 spark-shell 可以非常有帮助。但是,我发现做实际的本地调试,设置断点,检查变量等是不可或缺的。这是我使用IntelliJ的方式。

首先,确保您可以使用本地运行spark应用程序 spark-submit,例如就像是:

spark-submit --name MyApp --class MyMainClass --master local[2] myapplication.jar

然后,通过添加如下选项,告诉本地火花驱动程序暂停并等待调试器启动时的连接:

--conf spark.driver.extraJavaOptions=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005

哪里 agentlib:jdwp 是Java Debug Wire Protocol选项,后跟逗号分隔的子选项列表:

  • transport 定义调试器和调试对象之间使用的连接协议 - 套接字或“共享内存” - 你几乎总是想要socket(dt_socket)除了我相信Microsoft Windows上的某些情况
  • server 在与调试器(或相反地,客户端)通信时,此进程是否应该是服务器 - 您始终需要一个服务器和一个客户端。在这种情况下,我们将成为服务器并等待调试器的连接
  • suspend 是否在调试器成功连接之前暂停执行。我们打开它,因此在调试器连接之前驱动程序不会启动
  • address 在这里,这是要监听的端口(用于传入的调试器连接请求)。您可以将其设置为任何可用端口(您只需确保将调试器配置为连接到同一端口)

所以现在,你的 spark-submit 命令行应该类似于:

spark-submit --name MyApp --class MyMainClass --master local[2] --conf spark.driver.extraJavaOptions=agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005

现在如果你运行上面的内容,你会看到类似的东西

Listening for transport dt_socket at address: 5005

并且您的spark应用程序正在等待调试器附加。

接下来,打开包含Spark应用程序的IntelliJ项目,然后打开“运行 - >编辑配置...”然后单击“+”添加新的运行/调试配置,并选择“远程”。给它起一个名字,例如“SparkLocal”,并选择“Socket”进行传输,“Attach”进入调试器模式,并键入Host的“localhost”和上面用于Port的端口,本例中为“5005”。单击“确定”保存。

在我的IntelliJ版本中,它给出了调试命令行用于调试过程的建议,它使用“suspend = n” - 我们忽略了它并使用“suspend = y”(如上所述),因为我们想要等待我们连接开始的应用程序。

现在你应该准备调试了。只需使用上面的命令启动spark,然后选择刚刚创建的IntelliJ运行配置,然后单击Debug。 IntelliJ应该连接到您的Spark应用程序,该应用程序现在应该开始运行。您可以设置断点,检查变量等。


15
2018-04-15 13:21



编辑通过在“agentlib”之前添加“ - ”来修复拼写错误,如其他答案所述 - Jason Evans
感谢您的投入。这很有帮助。您还可以查看以下问题并提供您的意见吗? stackoverflow.com/questions/51988803/... - rajcool111
嘿@ rajcool111,我不是Spark Streaming专家,但我对你的问题留下了一般评论。 - Jason Evans
谢谢你的投入 - rajcool111


启动Spark shell。这是直截了当的 Spark文档

./bin/spark-shell --master local[2]

你还会看到Spark shell被称为 REPL。这是迄今为止学习Spark的最佳方式。我将80%的时间花在Spark shell上,另外20%将代码转换为我的应用程序。


9
2018-05-23 05:09



如果应用程序是用Java编写的,该怎么办? - MFARID
Scala spark-shell可以加载Java jar,然后您可以从Scala运行您的app和/或方法。 - David Griffin
如果要构建一个一直在更改的(更大)函数,并且需要在shell中进行测试,则这不是很有用。每次改进后,都需要重新导入该功能。但这需要停止并启动shell(每次!),这不是构建代码的快速方法。 OP要求(python)类似ipdb的功能(显然仅在本地模式下有用),这显然不存在。 - Ytsen de Boer
不必要。您可以在脚本中定义函数,然后将其导入shell。 shell将允许您一遍又一遍地导入相同的函数或集合或函数/类/对象等。奇迹般有效。 - David Griffin


只需传递java选项即可打开调试端口。这是一篇很好的文章解决你的问题 - http://danosipov.com/?p=779 我正在使用它

$ SPARK_JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 spark-shell

(是的,SPARK_JAVA_OPTS已被弃用,但它运行正常)


7
2017-11-24 08:39



我也偶然发现了你提到的那篇文章,但是SPARK_JAVA_OPTS并没有以这种形式为我工作。我不得不修改它,它对我来说是什么: export SPARK_JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,address=5005,suspend=y,onuncaught=n - Szymon Przedwojski


@Jason Evans的回答对我不起作用。但

--conf spark.driver.extraJavaOptions=-Xrunjdwp:transport=dt_socket,server=y,address=8086,suspend=n

工作


3
2017-11-29 01:32



是的,在@ryan指出的“agentlib”之前有一个“ - ”缺失,现在修复了 - Jason Evans


@Jason Evan的回答只需要一个小的改动。在字符串“agentlib ....”之前需要一个' - '

 --conf spark.driver.extraJavaOptions=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005

您也可以使用选项“--driver-java-options”来实现相同的目的

--driver-java-options -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005

1
2018-02-13 09:29



是的,你是@Yanan关于失踪的“ - ”,谢谢! - Jason Evans


你可以尝试这个 spark-env.sh

SPARK_SUBMIT_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8888


0
2017-07-30 14:11