java - 在 flink YARN 集群作业中使用 JNI

标签 java scala hadoop apache-flink

我有一个应用程序通过 RemoteExecutionEnvironment scala API 将 Apache Flink 作业分派(dispatch)到 AWS Elastic MapReduce YARN 集群。

这些作业使用 JNI 通过 C 库运行部分计算。在开发过程中,我只是在 RichCrossFunctionopen() 方法中调用了一个 System.loadLibrary() 来加载这个 JNI 库。这在 LocalExecutionEnvironment 中运行良好。

现在我要转到 RemoteExecutionEnvironment 这似乎不再有效。看起来 Flink 每次分派(dispatch)作业时都在使用新的 ClassLoader 并且我在计算节点上收到 Native library already loaded in another classloader 错误。

谷歌搜索告诉我这是 Tomcat 应用程序的常见问题,Tomcat 常见问题解答中提供了解决方案:http://wiki.apache.org/tomcat/HowTo#I.27m_encountering_classloader_problems_when_using_JNI_under_Tomcat

Flink 或 YARN 是否有类似的解决方案?

此外,是否可以避免每次作业排队时都重新提交 JAR?我总是在这个集群上使用同一个 jar,所以这是不必要的开销......

最佳答案

我通过在我的 JNI jar 中的静态初始化器中调用 loadLibrary 解决了这个问题,然后将我的 JNI jar 放到 Flink 的 /lib 文件夹中,类似于上面的 Tomcat 链接。

yarn-session.sh 启动过程自动复制到 Flink TaskManagers。这使我能够以与 Tomcat 相同的方式绕过 ClassLoader 隔离。

我正在使用 Maven,所以我使用 maven-shade-plugin 阻止了 JNI jar 被包含在我的 uberjar 中。

我仍然不知道这是否是最好的方法,因为 flink 手册不鼓励使用 /lib 文件夹,因为它不尊重他们的 ClassLoader 管理( https://ci.apache.org/projects/flink/flink-docs-release-1.0/apis/cluster_execution.html ),但这是正是我想要的。

也许另一种方法是使用 NativeLoader 模式并为每个 ClassLoader 创建一个单独的临时文件,但这会创建一堆重复的 native 库,这种方法适合我。

关于java - 在 flink YARN 集群作业中使用 JNI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38267836/

相关文章:

Scala Nothing 数据类型

hadoop - Hadoop单节点群集设置问题

java - Google Cloud Messaging - 即时收到或延迟很长时间的消息

java - 从文本文件生成源代码

java - 哪个 Java Collection 最适合这种情况

scala - Akka FSM Goto future

json - 使用 Argonaut 或 Circe 从不完整的 JSON 更新案例类

java - 如何将十六进制值传递给字符串 - Android

hadoop - 如何查看hadoop的堆使用情况?

java - IOException:无法初始化群集Hadoop 2.4.0