在flink YARN集群作业中使用JNI

时间:2016-07-08 13:23:28

标签: java scala hadoop apache-flink

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

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

现在我转移到RemoteExecutionEnvironment这似乎不再适用了。看起来Flink每次调度作业时都使用新的ClassLoader,并且我在计算节点上出现Native library already loaded in another classloader错误。

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

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

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

1 个答案:

答案 0 :(得分:2)

我通过在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创建一个单独的临时文件,但这会创建一堆重复的本机库,这个方法对我有用。