AWS EMR - IntelliJ 远程调试 Spark 应用程序

Posted

技术标签:

【中文标题】AWS EMR - IntelliJ 远程调试 Spark 应用程序【英文标题】:AWS EMR - IntelliJ Remote Debugging Spark Application 【发布时间】:2017-03-23 06:13:59 【问题描述】:

我想调试在 AWS EMR 集群上运行的 Spark 应用程序。如果我可以使用 IntelliJ 远程连接和调试它,那就太好了。我已经搜索过,但发现很少。

有可能吗,如果可以,有人能指点我正确的方向吗?

谢谢。

【问题讨论】:

【参考方案1】:

首先,我要提醒您,由于 AWS EMR 存在大量错误和意想不到的用例,您尝试做的事情基本上是不可能的。我强烈建议您支付最大的单个实例来运行您的工作(他们有c4.8xlarge 在负担得起的一端和x1.32xlarge 真正的疯子!),只需在该实例中安装spark 并运行您的工作.

先决条件

您的 VPC 必须正确配置以允许任何与外部世界的连接。这意味着您的 Internet 网关工作正常。您可以通过使用 EC2 密钥对启动集群、修改主服务器的安全组以允许从您的机器进行 SSH 连接(默认情况下自然不会这样做)并尝试从您的机器连接到主服务器来测试这一点。如果你不能这样做,你将无法调试。在没有额外配置的新集群上,我什至无法满足这个先决条件! 运行 IntelliJ 进行调试的计算机必须可以从 Internet 访问。要对此进行测试,请修改主实例的安全组以允许在端口 5005 上与您的机器建立出站连接。然后,在您的机器上运行 nc -l 5005。 SSH 连接到您的主服务器并尝试echo "test" | nc your_ip_address 5005。在您机器的终端上看到 test 之前,请不要继续。

IntelliJ 设置

创建一个新的远程配置。将调试器模式更改为侦听。命名配置并保存。当您点击调试时,它将等待连接。在该窗口中,您会看到“用于运行远程 JVM 的命令行参数”,内容如下:

-agentlib:jdwp=transport=dt_socket,server=n,address=localhost:5005,suspend=y

您可以像我一样删除onthrowoncaught 行。假设您的调试机器可通过 Internet 访问,地址为 24.13.242.141。假装它实际阅读:

-agentlib:jdwp=transport=dt_socket,server=n,address=24.13.242.141:5005,suspend=y

我们将使用它来设置 Spark 进程的调试。

火花设置

有两个进程可以被调试:驱动进程(执行你的SparkContext被实例化的代码)和执行进程。最终,您会将这些 JVM 选项传递给 spark-submit 的特殊参数,以实现连接。要调试驱动程序,请使用

spark-submit --driver-java-options -agentlib:jdwp=transport=dt_socket,server=n,address=24.13.242.141:5005,suspend=y --class ...

对于调试执行程序进程,您可以使用配置选项:

spark-submit --conf "spark.executor.extraJavaOptions=-agentlib:jdwp=transport=dt_socket,server=n,address=24.13.242.141:5005,suspend=y" --class ...

调试执行器非常棘手,因为会有多个进程。您无法像在 IntelliJ 中想象的那样真正调试多个进程。此外,您不能真正将 AWS EMR 中的执行程序数量限制为 1,即使他们声称您可以。我相信如果其他执行程序失败(当他们无法连接到您的调试会话时)失败是可以的。但这一步未经测试。

把它们放在一起

您可以使用 SDK 和 Web 控制台将参数修改为 spark-submit。请注意,在 SDK 中,您不应该尝试自己连接“args”——按照它的要求将它们作为数组项传递。

您需要从集群一开始就修改主节点的安全组以调试驱动程序(同样使用从节点的安全组来调试执行程序)。创建一个安全组,允许出站连接到您的 IP 地址和调试器端口(即 TCP 出站到 24.13.242.141:5005)。您应该使用该条目创建一个安全组,并使用 AWS 开发工具包 (.withAdditionalMasterSecurityGroups(...)) 将其添加到主/从作业流实例配置的安全组中。我不确定如何从 Web 控制台执行此操作。

一些常见的陷阱

确保使用 Gradle 生成带有 classpath "com.github.jengelman.gradle.plugins:shadow:1.2.4" 插件的影子 Jar。另外,启用Zip64。您将把 :shadowJar 任务的结果上传到 S3 以在 AWS EMR 上实际执行。
buildscript 
    repositories 
        mavenCentral()
        maven 
            url "https://plugins.gradle.org/m2/"
        
    
    dependencies 
        classpath "com.github.jengelman.gradle.plugins:shadow:1.2.4"
    


apply plugin: "com.github.johnrengelman.shadow"

shadowJar 
    zip64 true

确保使用--deploy-mode cluster--master yarn 启动您的Spark 应用程序(基本上没有记录)。 要从 EMR 上的驱动程序或执行程序内部访问 S3,请不要执行修改 sc.hadoopConfiguration() 的繁琐操作(例如,configuration.set("fs.s3n.impl", "org.apache.hadoop.fs.s3native.NativeS3FileSystem");)。根本不要配置这些属性! hadoop-aws 默认在 EMR 环境中正常工作,并自动设置了相应的属性。 将您的log4j 日志记录选项设置为仅报告WARN 及更高版本。在此 SDK 中,您可以这样做:
.withConfigurations(new Configuration()
    .withClassification("spark-log4j")
    .addPropertiesEntry("log4j.rootCategory", "WARN, console"))
在调试之前检查您的 containers/applications_.../container.../stderr.gz 日志是否有错误! 如果您看到此错误,“WARN YarnClusterScheduler: Initial job has not accepted any resources;检查您的集群 UI 以确保工人已注册并有足够的资源”,请确保在您的容器日志中添加 maximizeResourceAllocation spark 分类的配置属性。
new Configuration()
        .withClassification("spark")
        .addPropertiesEntry("maximizeResourceAllocation", "true"))
不要忘记在驱动程序结束时关闭上下文 (sc.close())。否则,Yarn 永远不会启动。可笑的无证。 影子 JAR 中的资源只能由与资源位于同一“JAR”中的类加载。换句话说,不要使用ClassLoader.getSystemClassLoader()。如果class A 通常在a.jar 中想要访问b.jar 中的资源,而class Bb.jar 中的类,则使用B.class.getClassLoader().getResource...。此外,使用相对路径(省略资源引用开头的正斜杠)。我建议捕获 NullPointerExceptions 并尝试两者,以便您的 JAR 可以正常工作,无论它是如何打包的。 如果您使用实现Function 接口和类似接口的类,请确保创建一个无参数构造函数来执行您可能依赖的所有初始化。 Spark 对闭包和函数实例都使用 Kryo 序列化(与 Java 序列化相反),如果您忽略为应用程序特定的初始化代码(例如,从资源加载)提供无参数构造函数,您将不会执行所有您期望的初始化。

【讨论】:

哇,非常感谢您提供如此详细的深入回答 - 我很快就会尝试似乎是徒劳的尝试:D 我什至不想再尝试这个了。无论如何......非常好的回应??

以上是关于AWS EMR - IntelliJ 远程调试 Spark 应用程序的主要内容,如果未能解决你的问题,请参考以下文章

获取VS代码Python扩展以连接到远程AWS EMR主节点上运行的Jupyter。

使用 IntelliJ 12 部署和调试远程 Jetty

打开/关闭 AWS EMR 集群

Docker容器中的Intellij CE 2018.2 + SBT:远程调试断点无法正常工作

为啥 IntelliJ 在远程调试时跳过断点

AWS EMR性能HDFS与S3