Mcrypt響應慢的一個緣由

上午的時候, 有同事來找我說上週新上線的一個使用mcrypt的腳本, 響應很是慢, 可是服務器的各項指標都正常, 不知道是什麼緣由.php

通過了解, 一個簡單的可重現的腳本以下:html

 
 
 

  
  
  
  

 
  1. <?php
  2. $dmcryptText = "dummy";
  3. $key = "foobar";
  4. $size = mcrypt_get_iv_size(MCRYPT_BLOWFISH,MCRYPT_MODE_ECB);
  5.  
  6. $iv = mcrypt_create_iv($size); //注意這裏
  7.  
  8. $m = mcrypt_ecb(MCRYPT_BLOWFISH, $key, $dmcryptText, MCRYPT_DECRYPT, $iv);
  9. var_dump($m);

當20個併發請求這個腳本的時候, 咱們會發現Apache的響應時間急劇上升…安全

考慮到這個問題可能具備必定的廣泛性, 因而我想我仍是寫一篇文章來介紹下這個坑, 防止後來人再次踩到.bash

PHP的Mcrypt擴展的mcrypt_create_iv, 若是你不指定的話, 默認使用/dev/random(Linux上), 做爲隨機數產生器. (也許有的同窗已經知道緣由了, 呵呵, 那就能夠略過了)服務器

這裏的問題就在於/dev/random, 它的random pool依賴於系統的中斷來產生. 當系統的中斷數不足, 不夠產生足夠的隨機數, 那麼嘗試讀取的進程就會等待, 也就是會hang住, 來看一個簡單的例子:併發

 
 
 

  
  
  
  

 
  1. $ dd if=/dev/random bs=1024k count=1

當你的機器不夠繁忙的時候, 你會發現, 輸出的速度很慢, 偶爾還有停頓…dom

問題就出在了這裏, 當你20個併發請求的時候, 服務器的中斷數不夠, 產生不了足夠的隨機數給mcrypt, 繼而致使PHP進程等待, 從而表現出, 響應時間變長測試

解決的辦法就是, 改用/dev/urandom, /dev/urandom也是一個產生隨機數的設備, 可是它不依賴於系統中斷.spa

 
 
 

  
  
  
  

 
  1. <?php
  2. $dmcryptText = "dummy";
  3. $key = "foobar";
  4. $size = mcrypt_get_iv_size(MCRYPT_BLOWFISH,MCRYPT_MODE_ECB);
  5.  
  6. $iv = mcrypt_create_iv($size, MCRYPT_DEV_URANDOM); //注意這裏
  7.  
  8. $m = mcrypt_ecb(MCRYPT_BLOWFISH, $key, $dmcryptText, MCRYPT_DECRYPT, $iv);
  9. var_dump($m);

修改後測試, 問題解決, 一切正常…..net

Weibo上SAE的同窗 @胥昕ops提供了一個不須要修改PHP代碼的解決方案:

胥昕ops: SAE 二三月份遇到的這個問題,一條命令秒殺此問題,

 
  
  

   
   
   
   

  
  1. $ rngd -r /dev/urandom -o /dev/random -t 1

用urandom的結果填充entropy池子,這樣既保證了entropy池的數量,也保證了隨機性

然而, 爲何PHP使用/dev/random做爲默認, 這是由於理論上來講, /dev/urandom在必定的狀況下, 可能會被可預測(參看: /dev/random), 因此通常上認爲, /dev/urandom不如/dev/random安全.

後記, 你們看手冊, 必定也要看手冊下面的評論, 呵呵, 有不少東西在評論中, 是有提到的, 以下面這條評論, 來自mcrypt_create_iv:

相關文章
相關標籤/搜索