寻找随机的错误-一个真实的故事
本文將介紹我的工作。 我將概述我的旅程,以實(shí)際找到正在發(fā)生的事情的根本原因。 我在本文中的目標(biāo)是突出顯示可以使用的技術(shù)示例,以實(shí)際跟蹤奇怪的和隨機(jī)的錯誤。
最后,我找到了一個非常清楚的解釋,說明問題發(fā)生的原因和原因。 本文標(biāo)題中存在“隨機(jī)性”并非巧合。
開始–問題出在哪
問題是,在遵循使用開發(fā)虛擬機(jī)的指南時,有時啟動應(yīng)用程序會花費(fèi)很長時間,然后失敗。 兩次啟動應(yīng)用程序后,我馬上遇到了問題。 其他人也有同樣的問題。
有人告訴我,沒有人真正知道它為什么會以這種方式運(yùn)行-但是重新啟動VM可能會解決它。 它不適合我。
但是我喜歡深入研究問題-所以我想知道出了什么問題。
將檔案耙到Solr
運(yùn)行rake app:run 有時會發(fā)生錯誤。 通過使用--trace --verbose (調(diào)試選項)運(yùn)行rake,我可以看到該應(yīng)用程序正在等待黑子啟動Apache Solr搜索服務(wù)。
所以問題是,該過程始終花在哪里? 開始的好處是,rake和sunspot用Ruby編寫。 因此,我閱讀了代碼,并添加了一些輸出語句,以查看哪個語句花費(fèi)了很長時間。 原來,這是Java進(jìn)程啟動了Solr。
挖掘Java
Apache Solr將一些輸出發(fā)送到sdtout-但黑子將其隱藏在您的面前。 但是由于調(diào)試時任何輸出都非常有用,因此我想查看輸出。
我使用ps -aux查找了ps -aux發(fā)出的確切命令行參數(shù),并從命令行手動啟動了該過程。 幸運(yùn)的是,它仍然花費(fèi)了一些時間-所以我知道問題不在Ruby代碼中。
通過端口映射程序nmap,我發(fā)現(xiàn)啟動該服務(wù)需要2秒鐘到2分鐘以上的時間。 但是耙任務(wù)只等待了10秒鐘。
現(xiàn)在,有了控制臺輸出,我可以看到,Solr在內(nèi)部使用Jetty – 在版本6.1.3中是Jetty ,這花了很多時間– 在這種情況下,它花了時間。 因此,我從源代碼管理中下載了6.1.3版的代碼,并查看了代碼。
我發(fā)現(xiàn)了一個名為DEBUG的系統(tǒng)屬性,它會增加輸出。 我啟用了它,并看到最后的調(diào)試輸出(花了很長時間)與啟動會話服務(wù)有關(guān)(不幸的是,我丟失了指向代碼的指針)。
這并沒有真正幫助我。 我嘗試使Jetty日志與log4j一起工作以最終看到更多內(nèi)容,但未成功-但我失敗了,不得不放棄當(dāng)晚(第二個)。
調(diào)試Java代碼
因此,如果您沒有從日志中獲取任何信息,則仍然可以使用調(diào)試器。 但是,代碼在VM(Ubuntu盒)上失敗了,但在我的本地計算機(jī)上卻失敗了。 但是幸運(yùn)的是Java有一個遠(yuǎn)程調(diào)試器 。
我使用遠(yuǎn)程調(diào)試參數(shù)啟動Java進(jìn)程,并使用SVN中的Jetty代碼在IntelliJ中附加了一個偵聽器。 我試圖使執(zhí)行在最后一個日志輸出附近的斷點(diǎn)處停止–但是此方法經(jīng)常被調(diào)用,而我沒有在正確的時機(jī)到達(dá)斷點(diǎn)。
但是,當(dāng)事情花費(fèi)很長時間時,僅停止正在運(yùn)行的進(jìn)程并查看堆棧跟蹤可能會有所幫助。 因此,我停止了執(zhí)行,并從Jetty中搜索了最后一個方法框架,該框架正在調(diào)用JDK –在這里,我發(fā)現(xiàn)了以下注釋:
//This operation may block on some systems with low entropy. See this page //for workaround suggestions: //http://docs.codehaus.org/display/JETTY/Connectors+slow+to+startup Log.debug('Init SecureRandom.'); _random=new SecureRandom();
解決方案
最后–我確實(shí)轉(zhuǎn)到了引用的Jetty Wiki頁面 。 我發(fā)現(xiàn),Java的java.util.SecureRandom使用來自操作系統(tǒng)的真實(shí)熵-當(dāng)沒有可用的熵時,它將阻塞。
僅使用普通的java.util.Random的方法,來自Wiki頁面的解決方案將很困難,因?yàn)榕渲梦募挥趕unspot和Solr內(nèi)部。 但是行“ NB一些解決方法報告使用/dev/./urandom而不是/ dev / urandom”給了我一個提示,那就是另找。
我用Google搜索解決方案,并在Stack Overflow上發(fā)現(xiàn),可以在Java進(jìn)程/dev/./urandom /dev/urandom隨機(jī)替換為/dev/./urandom 。 這可以通過使用命令行參數(shù)-Djava.security.egd=file:/dev/./urandom或通過將其替換為文件/usr/lib/jvm/java-6-openjdk/jre/lib/security/java.security (在Ubuntu機(jī)器上)。
那怎么了? Java的安全隨機(jī)數(shù)將不接受/dev/urandom作為隨機(jī)數(shù)的源 。 /dev/urandom是無阻塞的,這意味著它將在沒有可用的實(shí)際熵的情況下返回可以猜測的隨機(jī)數(shù)。 因此,Java默認(rèn)為/dev/random ,它將阻塞并等待,直到出現(xiàn)熵為止。
這就是為什么在生產(chǎn)或開發(fā)機(jī)器上極不可能發(fā)生阻塞的原因-但是在使用虛擬機(jī)時,它確實(shí)發(fā)生了,因?yàn)樘摂M機(jī)的網(wǎng)絡(luò)流量和IO并不多。 當(dāng)您經(jīng)常重啟應(yīng)用程序時(尤其是在某些情況下無法正常工作時),這種情況通常會發(fā)生。
解決方法有點(diǎn)有趣。 Java根據(jù)字符串拒絕/dev/urandom 。 它不會拒絕/dev/./urandom ,它當(dāng)然指向同一個可能不安全的隨機(jī)數(shù)生成器。
最后的話
該修補(bǔ)程序會帶來潛在的安全風(fēng)險–但是在開發(fā)虛擬機(jī)上,這不是問題。
如您所見,在系統(tǒng)中查找錯誤或問題涉及使用技術(shù),這些技術(shù)使您更接近根本原因。 但是,沒有黃金路。 有時,一種技術(shù)將無法為您提供更多信息。 因此,您將不得不嘗試另一種技術(shù)。 有時,您的直覺也會對您有所幫助。
到達(dá)這里后,您對這個故事有何看法?
參考:在Johannes Thones博客博客上,我們的JCG合作伙伴 Johannes Thones 狩獵隨機(jī)的錯誤-一個真實(shí)的故事 。
翻譯自: https://www.javacodegeeks.com/2012/10/hunting-random-bug-true-story.html
總結(jié)
以上是生活随笔為你收集整理的寻找随机的错误-一个真实的故事的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 番禺公章备案的地点(番禺公章备案)
- 下一篇: 国税财务制度备案流程图(国税财务制度备案