在 Arm64 上编译测试 Storm regexisart
如需转载,请标明原文出处以及作者
陈锐 RuiChen @kiwik
2019/07/04 17:02:17
背景
我们已经在aarch64
上编译测试了 Hadoop、Spark、HBase 和 Hive,今天开始在aarch64
上编译
验证 Storm。
Storm 85%的代码由 Java 组成,7%是 Python,另外有 HTML,Clojure 和 JavaScript,还有 0.4%是 C 语言。
编译环境
编译环境的配置请参考我的另一篇博客《在ARM64上编译Hadoop》, 在这里仅列出基本的编译环境信息:
- OS: CentOS 7.6
- Arch: aarch64
- Host: 华为云 ARM 公测实例
- Storm: git commit
b4f9eb1dc7284fa7f3a28368c1538dd901c5dd6f
(2019-06主干) - Java: 1.8.0
- Maven: 3.6.1
- Python: 2.7 and 3.6
- rvm: 2.4.2
- nvm: 8.9.3
执行编译
Storm 的官方开发文档
还要求安装rvm
和nvm
,根据文档要求的前置步骤配置环境之后,开始正式的编译。
mvn clean package -DskipTests
[INFO] --- maven-antrun-plugin:1.8:run (prepare) @ storm-metrics ---
[WARNING] Parameter tasks is deprecated, use target instead
[INFO] Executing tasks
main:
[echo] Downloading sigar native binaries...
[get] Getting: https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/magelan/hyperic-sigar-1.6.4.zip
[get] To: /root/.m2/repository/org/fusesource/sigar/1.6.4/hyperic-sigar-1.6.4.zip
[get] Error getting https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/magelan/hyperic-sigar-1.6.4.zip to /root/.m2/repository/org/fusesource/sigar/1.6.4/hyperic-sigar-1.6.4.zip
[INFO] ------------------------------------------------------------------------
遇到第一个问题,Storm 用到了一个收集系统信息的工具 sigar, 需要从 Google 的地址下载,我使用的华为云公测 ARM 实例是在国内的 Region,下载不了。替换成 一个 SourceForge 的地址如下,可以编译成功:
mvn clean package -DskipTests -Dsigar.download.url=https://nchc.dl.sourceforge.net/project/sigar/sigar/1.6/hyperic-sigar-1.6.4.zip
...
[INFO] storm-pmml-examples ................................ SUCCESS [ 1.505 s]
[INFO] storm-jms-examples ................................. SUCCESS [ 16.925 s]
[INFO] storm-rocketmq-examples ............................ SUCCESS [ 1.869 s]
[INFO] Storm Perf ......................................... SUCCESS [ 32.079 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 09:51 min
[INFO] Finished at: 2019-06-29T16:52:58+08:00
[INFO] ------------------------------------------------------------------------
编译完成之后,查了一下sigar
的二进制版本是打包在storm-metrics
模块的 jar 包里的,但是
展开 jar 之后,发现并没有对应的aarch64
的版本,所以虽然编译通过了,但是实际执行的时候应该
会有运行时异常。查了一下sigar
上确实也有一个 Open Issue,
希望对于aarch64
提供支持。
[root@arm-chenrui target]# jar xvf storm-metrics-2.0.1-SNAPSHOT.jar | grep resources
created: resources/
inflated: resources/sigar-x86-winnt.dll
inflated: resources/libsigar-universal-macosx.dylib
inflated: resources/sigar-x86-winnt.lib
inflated: resources/libsigar-sparc-solaris.so
inflated: resources/libsigar-sparc64-solaris.so
inflated: resources/libsigar-x86-freebsd-5.so
inflated: resources/libsigar-universal64-macosx.dylib
inflated: resources/libsigar-pa-hpux-11.sl
inflated: resources/libsigar-s390x-linux.so
inflated: resources/libsigar-amd64-solaris.so
inflated: resources/libsigar-amd64-linux.so
inflated: resources/libsigar-ppc64-linux.so
inflated: resources/libsigar-ia64-hpux-11.sl
inflated: resources/sigar-amd64-winnt.dll
inflated: resources/libsigar-x86-solaris.so
inflated: resources/libsigar-ppc-aix-5.so
inflated: resources/libsigar-ia64-linux.so
inflated: resources/libsigar-x86-freebsd-6.so
inflated: resources/libsigar-ppc-linux.so
inflated: resources/libsigar-amd64-freebsd-6.so
inflated: resources/libsigar-ppc64-aix-5.so
inflated: resources/libsigar-x86-linux.so
Unit Tests
编译成功,尝试执行 UT 测试。由于 Storm 通过模块storm-shaded-deps
将很多第三方依赖包的
包名进行了修改并重新打包,导致直接执行mvn test
会找不到依赖包,例如: org.apache.storm.shade.com.google.common.collect.Lists。
需要首先执行mvn install
将 storm-shaded-deps.jar 安装到本地 Maven 仓库中,解决依赖问题。
mvn clean install -DskipTests
由于某些模块依赖没有在 Storm 项目根目录下的pom.xml
中声明,所以直接在根目录下执行mvn test
,
会遇到 NoClassDefFoundError,这一点官方的开发者文档描述有误,需要使用-pl
参数显示
指定要执行的模块测试,如下:
mvn test -pl 'storm-client,storm-server,storm-webapp,storm-core'
storm-client
和storm-webapp
模块可以测试成功,但是storm-server
和storm-core
测试失败,
原因相同,测试依赖的组件RocksDB
包含二进制执行文件,但是没有对aarch64
提供支持,导致初始化
RocksDB
失败。
<dependency>
<groupId>org.rocksdb</groupId>
<artifactId>rocksdbjni</artifactId>
<version>5.18.3</version>
</dependency>
[root@arm-chenrui test]# jar xvf rocksdbjni-5.18.3.jar | grep librocksdbjni
inflated: librocksdbjni-linux32.so
inflated: librocksdbjni-linux64.so
inflated: librocksdbjni-osx.jnilib
inflated: librocksdbjni-linux-ppc64le.so
inflated: librocksdbjni-win64.dll
[ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.609 s <<< FAILURE! - in org.apache.storm.TickTupleTest
[ERROR] testTickTupleWorksWithSystemBolt Time elapsed: 0.609 s <<< ERROR!
java.lang.UnsatisfiedLinkError: /tmp/librocksdbjni8914565631636894594.so: /tmp/librocksdbjni8914565631636894594.so: cannot open shared object file: No such file or directory (Possible cause: can't load AMD 64-bit .so on a AARCH64-bit platform)
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1824)
at java.lang.Runtime.load0(Runtime.java:809)
at java.lang.System.load(System.java:1086)
at org.rocksdb.NativeLibraryLoader.loadLibraryFromJar(NativeLibraryLoader.java:78)
at org.rocksdb.NativeLibraryLoader.loadLibrary(NativeLibraryLoader.java:56)
at org.rocksdb.RocksDB.loadLibrary(RocksDB.java:64)
at org.rocksdb.RocksDB.<clinit>(RocksDB.java:35)
at org.apache.storm.metricstore.rocksdb.RocksDbStore.prepare(RocksDbStore.java:67)
at org.apache.storm.metricstore.MetricStoreConfig.configure(MetricStoreConfig.java:33)
at org.apache.storm.daemon.nimbus.Nimbus.<init>(Nimbus.java:533)
at org.apache.storm.LocalCluster.<init>(LocalCluster.java:244)
at org.apache.storm.LocalCluster.<init>(LocalCluster.java:126)
at org.apache.storm.LocalCluster$Builder.build(LocalCluster.java:1234)
at org.apache.storm.TickTupleTest.testTickTupleWorksWithSystemBolt(TickTupleTest.java:64)
...
从RocksDB
社区的 issue 列表
来看,aarch64
的支持工作正在进行中,还有部分 PR 没有合入,肯定要等到 6.0.1 以后的版本才能
提供支持了,但是很幸运开源社区已经有了一些工作基础,感谢开源开发者。
查看了一下RocksDB
Java 部分的代码,Jar 中的二进制代码是在最后一步加载的,所以还有一个
规避方案,就是在环境上提供自己编译的aarch64
的二进制包,这个还没有验证过,过两天试一下。
public synchronized void loadLibrary(String var1) throws IOException {
try {
System.loadLibrary(sharedLibraryName);
} catch (UnsatisfiedLinkError var5) {
try {
System.loadLibrary(jniLibraryName);
} catch (UnsatisfiedLinkError var4) {
this.loadLibraryFromJar(var1);
}
}
}
问题
想要推动一个大型软件支持 ARM,例如:Storm,绝对不是增加一个 ARM CI 就可以完成的工作, CI 仅仅是发现问题,解决问题还是要靠在开源社区长时间的工作积累。举一个简单的例子,支持 ARM 可能需要替换第三方库,例如:leveldbjni,随之而来的就大量的重构和重新测试的工作,增加一个 ARM 版本还需要后续持续的支持和问题跟进,而 ARM 的客户需求又不是特别广泛,想要找到一起工作的 开源开发者是比较难的,因此很多开源项目是比较犹豫的。在这种情况下,长期持久的战略投入是 必要条件,构建 ARM 软件生态没有捷径。