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

标签 amazon-web-services apache-spark intellij-idea remote-debugging amazon-emr

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

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

谢谢。

最佳答案

首先,我要提醒您,由于 AWS EMR 的众多错误和意外用例,您尝试做的事情基本上是不可能的。我强烈建议您为最大的单个实例付费来运行您的工作(他们有 c4.8xlarge 在经济实惠的一端,x1.32xlarge 用于真正的疯狂!),然后简单地安装 spark在该实例中并运行您的工作。

先决条件

  • 您的 VPC 必须正确配置,以完全允许与外部世界的任何连接。这意味着您的 Internet 网关工作正常。您可以通过使用 EC2 key 对启动集群、修改主服务器的安全组以允许来自您的机器的 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 进程的调试。

    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,即使他们声称可以。我相信如果其他执行程序会失败(当他们无法连接到您的调试 session 时会失败),那没关系。但是这一步是未经测试的。

    把这一切放在一起

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

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

    一些常见的问题
  • 确保使用 Gradle 生成带有 classpath "com.github.jengelman.gradle.plugins:shadow:1.2.4" 的 shadow 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 启动您的 Spark 应用程序和 --master yarn (基本上没有记录)。
  • 要从 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:初始作业未接受任何资源;请检查您的集群 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... .此外,使用相对路径(省略资源引用开头的正斜杠)。我建议捕捉 NullPointerException s 并尝试两者,以便您的 JAR 可以正常工作,无论它是如何打包的。
  • 如果您使用实现 Function 的类接口(interface)和类似的,确保创建一个无参数构造函数来执行你可能依赖的所有初始化。 Spark 对闭包和函数实例都使用 Kryo 序列化(而不是 Java 序列化),如果您忽略为应用程序特定的初始化代码(例如,从资源加载)提供无参数构造函数,您将不会执行所有您期望的初始化。
  • 关于amazon-web-services - AWS EMR - IntelliJ 远程调试 Spark 应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40506908/

    相关文章:

    python - 培训中的 AWS NoCredentials

    mapreduce - Apache Spark 中的驱动程序何时不会运行某个操作?

    intellij-idea - IntelliJ更新后我无法加载dart/flutter插件

    python - 在aws中获取表的列名作为元组而不是字符串

    python-3.x - 使用 python 连接到 AWS RDS Postgres 数据库

    java - Spark join/groupby 数据集需要很多时间

    node.js - 如何让IDEA识别Jasmine Node.js包中的关键字?

    java - 带有 Flex 的 IntelliJ Idea Java 项目,如何嵌入生成的 SWF

    amazon-web-services - 使用 aws_elasticache_replication_group 获取 Terraform 的终端节点

    java - 如何将 scala.collection.Set 转换为 java.util.Set 并在 RDD 中进行序列化