今天介紹一下将ODL移植到powerpc平台上遇到的一些問題。
1、啟動karaf時提示找不到hostname,無法進行tcp連接配接。
可以通過hostname指令進行設定,例如hostname localhost
2、啟動過程中出現異常,提示檔案句柄不足。
一個程序打開檔案句柄數目是有限制(也可以設定成無限),不同作業系統是不同的。我們可以通過ulimit進行設定,例如:ulimit -n 65535
3、啟動過程出現異常,提示找不到類名(最惡心的問題),百度+谷歌都不好使。
[email protected]>Uncaught error from thread [opendaylight-cluster-data-
akka.persistence.dispatchers.default-plugin-dispatcher-18] shutting down JVM since 'akka.jvm-exit-on
-fatal-error' is enabled for ActorSystem[opendaylight-cluster-data]
java.lang.NoClassDefFoundError: org/iq80/leveldb/DBFactory
at akka.persistence.journal.leveldb.LeveldbJournal.<init>(LeveldbJournal.scala:22)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at akka.util.Reflect$.instantiate(Reflect.scala:44)
at akka.actor.NoArgsReflectConstructor.produce(IndirectActorProducer.scala:105)
at akka.actor.Props.newActor(Props.scala:213)
at akka.actor.ActorCell.newActor(ActorCell.scala:562)
at akka.actor.ActorCell.create(ActorCell.scala:588)
at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:461)
at akka.actor.ActorCell.systemInvoke(ActorCell.scala:483)
at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:282)
at akka.dispatch.Mailbox.run(Mailbox.scala:223)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.ClassNotFoundException: org.iq80.leveldb.DBFactory
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 18 more
#
#
【定位過程-第一階段】
定位過程1:提示找不到類,那麼就看一下類是否存在,經過确認類檔案是存在且路徑也是對的,類檔案在leveldbjni-all-1.8-odl.jar包中。
定位過程2:檢視leveldbjni-all-1.8-odl.jar中META-INF/MANIFEST.MF檔案,其中有一段内容如下(整理格式後):
Bundle-NativeCode:
META-INF/native/windows32/leveldbjni.dll;osname=Win32;processor=x86,
META-INF/native/windows64/leveldbjni.dll;osname=Win32;processor=x86-64,
META-INF/native/osx/libleveldbjni.jnilib;osname=macosx;processor=x86,
META-INF/native/osx/libleveldbjni.jnilib;osname=macosx;processor=x86-64,
META-INF/native/linux32/libleveldbjni.so;osname=Linux;processor=x86,
META-INF/native/linux64/libleveldbjni.so;osname=Linux;processor=x86-64,
META-INF/native/sunos64/amd64/libleveldbjni.so;osname=SunOS;processor=x86-64,
META-INF/native/sunos64/sparcv9/libleveldbjni.so;osname=SunOS;processor=sparcv9
因為我們是linux系統(紅色字段),然而我們是powerpc平台并非x86平台。基本可以确定so動态庫以及processor這個地方是有問題的,那麼就先解決這個問題。
【解決問題-第一階段】
解決1:libleveldbjni.so必須是powerpc平台上,需要下載下傳如下三個軟體:
軟體名稱 | 下載下傳方式 | 備注 |
snappy | wget http://snappy.googlecode.com/files/snappy-1.0.5.tar.gz | 無 |
leveldb | git clone git://github.com/chirino/leveldb.git | 非谷歌官方倉庫位址 |
leveldbjni | git clone git://github.com/fusesource/leveldbjni.git | 無 |
具體編譯方式可參考leveldbjni中readme.md檔案,提醒一下必須是交叉編譯啊!!将編譯好的libleveldbjni.so替換到jar包中。
解決2:processor應該設定成什麼呢?
通過走查代碼,發現processor的擷取是通過System.getProperty("os.arch"),在我們的環境中os.arch傳回的是ppc64。是以我們對MANIFEST.MF檔案修改,将對應的processor修改成ppc64。
【驗證-第一階段】
替換so以及MANIFEST.MF檔案之後,再次啟動karaf,仍然報相同錯誤,沒有任何進展。
【定位過程-第二階段】
定位過程1:為了驗證替換檔案之後的jar是否正确,下載下傳原生的karaf,并且手動安裝這個jar包,發現bundle的狀态一直都是Installed(正常應該Active狀态)。說明jar包還是有問題。
定位過程2:針對這種問題,我們隻能調試,調試方法有:日志、debug調試。對于一個不太了解軟體,debug調試是最佳方式。針對這個問題,我們應該将斷點設定在什麼地方呢?由于我們是通過bundle:install -s bundle名稱,那麼好我們就設定在指令行入口的地方。
【解決問題-第二階段】
通過上面debug過程中,最終發現指令行在安裝bundle的時候,比對arch名字是powerpc,而非是ppc64。是以我們可以得出我們需要将processor設定成powerpc。(這部分代碼進行了适配,把ppc64是配成powerpc)
【驗證-第二階段】
通過上面将processor設定powerpc,将jar包放到原生的karaf中,發現安裝這個bundle之後,狀态是active。非常的興奮!!!然後把該jar包放到odl中,啟動karaf,不幸的事情發生了,還是報錯且錯誤一樣。簡直是在做過山車一般,倍兒爽!!
【定位過程-第三階段】
既然原生的karaf能運作起來,證明這樣配置問題不大且so庫應該也是正常的。那麼就隻能調試debug調試odl。
定位過程1:我們在調試odl的時候一般都是系統啟動ok,調試我們業務邏輯,但是針對這種啟動過程中抛出了異常,我們應該如何調試呢?我們面臨的是必須在抛異常之前就把斷點斷住,我們應該怎麼做呢?原來jvm提供了一個參數suspend,我們需要将這個參數設定.即可。這個參數含義是程序啟動之後隻配置設定基本資源,不執行任何業務邏輯,當用戶端連上jvm之後,才開始執行業務邏輯。說白點大白話,就設定這個參數之後進行先挂起。
定位過程2:bundle:install [bundle名稱] 與 bundle:install -s [bundle名稱] 差別是s表示start,安裝并激活。通過分步調試,隻調試install過程,發現install過程沒有問題,processor校驗過程對os.arch進行了适配,适配成powerpc。
【解決問題-第三階段】
解決方法1:修改start過程對processor校驗。
解決方法2:修改配置MANIFEST.MF檔案,增加對processor是ppc64。
【驗證-第三階段】
META-INF/native/linux64/libleveldbjni.so;osname=Linux;processor=ppc64,
META-INF/native/linux64/libleveldbjni.so;osname=Linux;processor=powerpc,
采用解決方法2,驗證通過,karaf可以在powerpc平台正常啟動。
【特别說明】
1、在解決過程還需要編一個libjansi.so,在jline-2.12.jar,是以需要單獨再編譯一下libjansi.so
2、我們的odl代碼其實包含了兩套osgi架構Apache Felix和Equinox(原生karaf隻有Felix),由于存在兩個osgi架構,才導緻上面對于processor的處理出現不一緻。