西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁西西教程其它教程 → web服務器BCrypt性能問題的解決方法

web服務器BCrypt性能問題的解決方法

相關軟件相關文章發(fā)表評論 來源:lixiong時間:2011/12/25 2:40:54字體大小:A-A+

作者:lixiong點擊:34次評論:0次標簽: web服務器

  • 類型:下載工具大。670KB語言:英文 評分:5.0
  • 標簽:
立即下載

在昨天的研究中,發(fā)現(xiàn)BCrypt最大的隱患在于性能。BCrypt的安全性是通過犧牲性能來獲取的。BCrypt比傳統(tǒng)hash+salt要安全一萬倍,但是代價是使用BCrypt做認證對比密碼和密文時候,性能也比hash+salt要慢一萬倍。

所以,我得出一個結論。如果使用傳統(tǒng)hash+salt需要N臺認證服務器的話,那用BCrypt就需要添加10000*N臺服務器才能達到同樣的性能。比如一個郵件系統(tǒng)使用了2臺服務器來專門作認證,那使用BCrypt的話就需要再購買2萬臺。當然,小的應用,如果使用一臺服務器1%的性能就可以做完認證的話,使用BCrypt只需要100臺服務器。

這個聽起來比較嚇人,但是我通過另外一種計算方法,也能得出同樣的結果。比如說163的郵件系統(tǒng),峰值的時候每秒鐘可能需要處理10000個登陸請求。比如每天早上9點到9點半之間,很多人都會登陸郵件系統(tǒng)。按照BCrypt提到的,每個請求需要花費0.3秒,那么處理10000個請求需要3000秒。這顯然是不能接受的。如果要讓客戶都能在1秒鐘登陸,那就需要添加服務器,把登陸請求均分到各個服務器上。對于單CPU的服務器,就一共需要3000臺。

我把上面的想法和網(wǎng)友討論后,得到了不同的意見。有人覺得0.3秒的處理時間其實不多阿,因為通常一個web請求,內(nèi)存,磁盤數(shù)據(jù)庫轉(zhuǎn)一圈下來,離0.3秒也差不多了吧,所以BCrypt的0.3秒的開銷是一個正常值,不會帶來什么問題。有人提到普通web服務器每秒處理1000個請求是很常見的。如果按照我上面的計算方法,這就表示每個請求在1ms內(nèi)完成了,這聽起來有點不可能嘛。

根據(jù)上面的意見,我又仔細思考了一下。我想借這個話題,先討論一下Web服務器的性能,再看看BCrypt帶來的問題應該如何解決。

注意,下面所敘述的,是根據(jù)我現(xiàn)有知識和經(jīng)驗做的邏輯推理。我沒有寫半行web程序的code來驗證,我也沒有任何大規(guī)模web項目的經(jīng)驗。但是我非常喜歡先做這樣“紙上談兵”的推理,因為這樣可以讓我先仔細想清楚后再行動。

網(wǎng)頁的加載時間,和單個request的處理時間是不一樣的。單個網(wǎng)頁中往往包含多個子元素,比如圖片和AJAX調(diào)用。這些子元素的加載都會在額外的request里面完成。另外網(wǎng)頁加載的時間除了web服務器的運算處理時間外,還有數(shù)據(jù)在網(wǎng)絡上的傳輸時間,腳本運行時間,瀏覽器繪制時間,當然如果是第一次訪問,還包括DNS查詢和TCP握手時間等等,F(xiàn)在主流網(wǎng)站的頁面加載時間都在2秒以內(nèi),每個頁面大概包含10-50個子元素。客戶端腳本和瀏覽器的處理占用了大概一半時間,所以跟服務器相關的時間大概就是1秒。由于部分子元素可能在瀏覽器中有cache,所以這1秒鐘對應的大概就是5-25個請求。這樣算下來每個請求大概在200-40毫秒之間。這里面大概web服務器的運算開銷可能只有25%,那大概就是50ms到10ms之間。注意,50ms-10ms這個估算是指平均時間。

由于網(wǎng)絡傳輸和客戶端導致的開銷不是今天的討論范圍,所以下面就只討論web服務器運算一個request需要怎樣的開銷。處理一個web request,通常牽涉到下面一些工作。輸出流添加,數(shù)據(jù)庫讀寫,文件讀寫,復雜計算。輸出流添加是最常見的,比如服務器會把Response.Write里面的內(nèi)容加入到Response里面。輸出流添加是非常快的。速度和string.format或者StringBuilder.Append應該在一個數(shù)量級?隙ū群撩胍於鄠數(shù)量級。復雜計算是指需要CPU密集超過50ms的運算,比如正則表達式運算和BCrypt操作。數(shù)據(jù)庫讀寫和文件讀寫所需要的時間往往也超過50ms,但是這兩者不一定需要占用web服務器的CPU資源。

由此,在考量web服務器運算一個request所需的開銷的時候,先看這個request是不是需要復雜運算。如果需要,那么這個復雜運算肯定是一個瓶頸。

那么數(shù)據(jù)庫和文件操作是不是瓶頸呢。從處理request所需的時間上來說,這兩者肯定也是瓶頸。因為再快也得先等到這兩者返回。但是和復雜運算相比,復雜運算損害的不單單是request所需的時間,另外還損害了服務器的可伸縮性。

由于數(shù)據(jù)庫和文件操作不占用web服務器的CPU,所以web服務器在等待數(shù)據(jù)庫和文件操作結果的時候,可以把CPU資源用來處理新的request。比如來了100個請求,每個請求都需要2秒鐘的數(shù)據(jù)庫操作,不等于說服務器需要200秒才能處理完所有請求的。因為服務器可以讓100個請求都進來,然后發(fā)送者100個請求的數(shù)據(jù)庫操作,然后讓這100個請求同時等待。2秒鐘以后,這100個數(shù)據(jù)庫操作的結果都返回回來后,服務器可以把這100個請求的結果都返回了。

但如果請求中牽涉到了復雜運算呢,服務器就沒辦法并發(fā)了。如果來了100個請求,每個請求都需要運算2秒鐘,而服務器如果只有一個CPU的話,那就一定需要200秒。

由此可見,請求的平均處理時間和服務器的吞吐量不是簡單的比例關系。這牽涉到這個請求具體是如何處理的。如果服務器的吞吐量是1秒鐘1000個請求,不能簡單地用1000毫秒除以1000,得到每個請求只需要1毫秒來處理。這個運算法則只在沒有任何并發(fā)可能性的情況下才有效。這也在此證明了,合理使用異步調(diào)用,對服務器性能會有多大的提高。

接下來反過來想,對于一個不涉及數(shù)據(jù)庫,不涉及文件,不涉及復雜運算的請求,合理的處理時間應該是多少呢。這個處理時間其實等同于同等復雜程度的函數(shù)調(diào)用時間。換句話說,如果只是計算出一個幾十k的頁面,花費的時間肯定在1ms的數(shù)量級。你肯能覺得這里沒有考慮web服務器的“儀式性”開銷,比如說處理TCP報文,分析HTTP頭等等。其實,主流的web服務器在這方面已經(jīng)足夠優(yōu)化,比如從IIS6開始,對于HTTP協(xié)議的處理都直接在內(nèi)核里面做了,所以就算把這些開銷都算上,也能做到1ms的數(shù)量級。對于計算機來說,1ms其實很長的,1ms表示一秒內(nèi)調(diào)用函數(shù)1000次而已。不信你可以估算一下下面的代碼,循環(huán)了10000次,大概需要多少時間:

StringBuilder dummy = new StringBuilder();
for (int i = 0; i < 10000; i++)
{
                dummy.AppendLine((string.Format("this is {0}", i)));
}
var len = dummy.Length;

另外,上訴的討論還沒有考慮一個非常重要的武器:Cache。如果使用cache, 整個頁面可能根本不需要任何運算,都不需要跑一行處理代碼,web服務器就把結果給返回了。如果大量使用cache,別說一千次,一秒鐘處理上十萬次都可以。大多數(shù)的網(wǎng)站已經(jīng)廣泛使用cache了,圖片是cache的,blog文章的內(nèi)容是cache的,甚至評論都是cache的。正因為如此,把包含復雜運算,數(shù)據(jù)庫和文件處理的慢操作跟帶cache的塊操作一平均,結果落到前面估算的50ms-10ms是很自然的事情。

有了上面的分析后,再來看文章前面的兩個問題。第一個問題是,BCrypt的300ms開銷,和數(shù)據(jù)庫,磁盤文件兜一圈下來的開銷也差不多阿,為什么說BCrypt就更嚴重呢。原因是BCrypt的300ms都壓在了CPU上面,而人家的是可以并發(fā)的。當然,動不動就要去兜數(shù)據(jù)庫和磁盤文件的web應用,設計上也有問題的。第二個問題是,我的服務器可以一秒鐘處理1000個請求,按照原來的計算方法,就是1ms處理1個了,這個不可能吧。這個問題就要區(qū)分情況來回答了。首先,1ms處理1個請求是可能的,比如使用了cache,絕對能。其次,如果考慮并發(fā)的話,的確不能簡單做除法。但問題關鍵是,BCrypt是不支持并發(fā)的阿。

所以,BCrypt最大的隱患的確就是在性能上。我所做的下列判斷是正確的:“如果使用傳統(tǒng)hash+salt需要N臺認證服務器的話,那用BCrypt就需要添加10000*N臺服務器才能達到同樣的性能”。

接下來的問題是,BCrypt性能問題有解決辦法么。在前面的邏輯推理中,我想到了一個最常見的辦法:用空間換時間。我可以在內(nèi)存中建立cache,把密碼原文和用BCrypt計算后的hash緩存起來。這樣每次處理認證請求的時候,就不需要計算了。當然,這里其實帶來了新的安全隱患。如果有人盜竊了服務器的內(nèi)存轉(zhuǎn)儲(memory dump), 那么就能看到cache里面的東西,那可就是密碼的原文明文阿。這有何去何從呢?

    web服務器
    (20)web服務器
    西西軟件園提供好用的服務器官方下載,網(wǎng)絡上提供了很多免費服務器,大家不知道如何選擇,西西小編給大家推薦幾款使用不錯的服務器,支持.斷點續(xù)傳大文件下載正則表達式重寫虛擬目錄等,可通過接口接口實現(xiàn)執(zhí)行服務器腳本如,,.等通過重寫可讓服務器變成一臺代理服務器代理上網(wǎng),服務端口就是代理端口...更多>>

    相關評論

    閱讀本文后您有什么感想? 已有人給出評價!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評論

    最新評論

    發(fā)表評論 查看所有評論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字數(shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)