當前位置:
首頁 > 最新 > 隨機數阻塞問題

隨機數阻塞問題

有個使用了SpringBoot的API的項目拆分了不同業務的服務,一個jar包通過不同的命令行來啟動不同的10個業務進程.所以發布版本的時候基本上是重啟所有的進程.

偶然的一次線上發布看業務日誌,發現進程啟動的時候卡在tomcat embeded初始化的時候.而且基本上重啟的進程都卡住了.

定位

找出其中一個進程,執行了高效定位執行效率問題介紹的工具腳本.發現Random類初始化的時候所佔用的CPU時間有點異常,顯然這個隨機數一定還有什麼不可描述的操作.

我們可以做個實驗模擬下,代碼如下

上面的代碼在linux的系統下一般情況下會阻塞.在阻塞的情況下,高CPU的線程棧如下圖所示.

原因

linux的隨機數種子所使用的兩個特殊設備文件/dev/random和/dev/urandom.他們產生隨機數的原理是利用當前系統的熵池來計算出固定一定數量的隨機比特,然後將這些比特作為位元組流返回.

熵池就是當前系統的環境噪音,熵指的是一個系統的混亂程度,系統噪音可以通過很多參數來評估,如內存的使用,文件的使用量,不同類型的進程數量等等.

/dev/random

在讀取時,/dev/random設備會返回小於熵池雜訊總數的隨機位元組./dev/random可生成高隨機性的公鑰或一次性密碼本.若熵池空了,對/dev/random的讀操作將會被阻塞,直到從別的設備中收集到了足夠的環境雜訊為止.

/dev/urandom

/dev/random的一個副本是/dev/urandom ("unlocked",非阻塞的隨機數發生器),它會重複使用熵池中的數據以產生偽隨機數據.這表示對/dev/urandom的讀取操作不會產生阻塞,但其輸出的熵可能小於/dev/random的.它可以作為生成較低強度密碼的偽隨機數生成器,不建議用於生成高強度長期密碼.

上圖的數據可以算出2個設備生產隨機比特的速度差距了150倍.JDK的實現默認是使用/dev/random , 在熵池不足的情況下非常容易發生阻塞,有的時候甚至是幾分鐘.

解決

默認實現容易發生阻塞,我們可以使用偽隨機數發生器來避免.在程序啟動的時候加上-Djava.security.egd=file:/dev/urandom 的選項來選擇隨機數設備.問題即可解決.

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Java夜未眠 的精彩文章:

TAG:Java夜未眠 |