我想调试在AWS EMR集群上运行的Spark应用程序。如果我可以使用IntelliJ进行远程连接和调试,那将会很棒。我已经搜索,但发现很少。AWS EMR - IntelliJ远程调试Spark应用程序
是否有可能,如果有的话,有人可以指导我朝着正确的方向吗?
谢谢。
我想调试在AWS EMR集群上运行的Spark应用程序。如果我可以使用IntelliJ进行远程连接和调试,那将会很棒。我已经搜索,但发现很少。AWS EMR - IntelliJ远程调试Spark应用程序
是否有可能,如果有的话,有人可以指导我朝着正确的方向吗?
谢谢。
首先,由于AWS EMR的众多错误和意外的使用情况,我会告诫你要做的事情基本上是不可能的。我强烈建议支付您可以运行工作的最大单一实例(它们的c4.8xlarge
在负担得起,而x1.32xlarge
为真正的疯狂!),并简单地在该实例中安装spark
并运行您的工作。
nc -l 5005
。 SSH到你的主人并尝试echo "test" | nc your_ip_address 5005
。在您的机器终端上看到test
之前,请勿继续。创建一个新的远程配置。将调试器模式更改为侦听。命名配置并保存。当你点击调试时,它会等待连接。在该窗口中,您将看到“运行远程JVM的命令行参数”,读书是这样的:
-agentlib:jdwp=transport=dt_socket,server=n,address=localhost:5005,suspend=y
您可以删除onthrow
和oncaught
线像我一样。假设您的调试机器可以通过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 --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控制台。请注意,在SDK中,您不应该尝试自己连接“参数” - 将它们作为数组项一样将它们传递给您。
为了调试驱动程序(同样用slave的安全组来调试执行程序),您需要修改主机的安全组。创建一个安全组,允许出站连接到您的调试器的IP地址和端口(即TCP Outbound到24.13.242.141:5005)。您应该使用该条目创建安全组,并使用AWS SDK(.withAdditionalMasterSecurityGroups(...)
)将其添加到主/从属作业流实例配置的安全组。我不确定如何从Web控制台执行此操作。
classpath "com.github.jengelman.gradle.plugins:shadow:1.2.4"
插件阴影罐子。另外,启用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
启动星火应用程序(基本上没有证件)。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
日志中的错误你懒得调试之前!maximizeResourceAllocation
为spark
分类。new Configuration()
.withClassification("spark")
.addPropertiesEntry("maximizeResourceAllocation", "true"))
sc.close()
)年底前关闭您的上下文。否则,纱线永远不会启动。欢迎无证。ClassLoader.getSystemClassLoader()
。如果class A
通常在a.jar
想要访问b.jar
中的资源,并且class B
是b.jar
中的类,请使用B.class.getClassLoader().getResource...
。此外,使用相对路径(在资源引用的开头省略正斜杠)。我会建议捕获NullPointerException
并尝试这两种方法,这样无论它如何打包,您的JAR都能正常工作。Function
接口和类似的类,请确保创建一个无参数构造函数来执行您可能依赖的所有初始化。 Spark对闭包和函数实例都使用Kryo序列化(而不是Java序列化),如果您忽略为特定于应用程序的初始化代码提供无参数构造函数(例如,从资源加载),则不会执行所有操作您期待的初始化。
哇,非常感谢你这么详细的深入的答案 - 我会尝试什么似乎是一个徒劳的尝试很快:D – null
我甚至不想尝试这个了。反正...非常好的回应 – Cristian