閱讀鳥哥的風雪之隅PHP博客的筆記(1)

1. 在PHP中使用協程實現多任務調度

http://www.laruence.com/2015/05/28/3038.htmlphp

 

2. Curl的毫秒超時的一個」Bug」

CentOS服務器上, 當你設置了小於1000ms的超時之後, curl不會發起任何請求, 而直接返回超時錯誤(Timeout reached 28).html

原來, 這裏面有一個坑, CURL默認的, 在Linux系統上, 若是使用了系統標準的DNS解析, 則會使用SIGALARM來提供控制域名解析超時的功能, 可是SIGALARM不支持小於1s的超時, 因而在libcurl 7.28.1的代碼中(注意中文註釋行):mysql

int Curl_resolv_timeout(struct connectdata *conn,
                        const char *hostname,
                        int port,
                        struct Curl_dns_entry **entry,
                        long timeoutms)
{
.......
.......
#ifdef USE_ALARM_TIMEOUT
  if(data->set.no_signal)
    /* Ignore the timeout when signals are disabled */
    timeout = 0;
  else
    timeout = timeoutms;
 
  if(!timeout)
    /* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
    return Curl_resolv(conn, hostname, port, entry);
 
  if(timeout < 1000) //若是小於1000, 直接超時返回
    /* The alarm() function only provides integer second resolution, so if
       we want to wait less than one second we must bail out already now. */
    return CURLRESOLV_TIMEDOUT;  
 
  ....
  ....
<?php
   curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
?>

這樣就能夠支持了。sql

在比較新的PHP版本中,CURLOPT_NOSIGNAL是默認啓用的,因此能夠不用設置了。數組

能夠純粹瞭解一下就行吧。安全

 

3.  PHP浮點數的一個常見問題的解答

關於PHP的浮點數, 我以前寫過一篇文章: 關於PHP浮點數你應該知道的(All ‘bogus’ about the float in PHP)服務器

不過, 我當時遺漏了一點, 也就是對於以下的這個常見問題的回答:less

 
<?php
    $f = 0.58;
    var_dump(intval($f * 100)); //爲啥輸出57
?>

爲啥輸出是57啊? PHP的bug麼?dom

我相信有不少的同窗有過這樣的疑問, 由於光問我相似問題的人就不少, 更不用說bugs.php.net上常常有人問…curl

要搞明白這個緣由, 首先咱們要知道浮點數的表示,

計算機專業科班出身的我,表示理解這個並不難。

4. PDOStatement::bindParam的一個陷阱

<?php
$dbh = new PDO('mysql:host=localhost;dbname=test', "test");
 
$query = <<<QUERY
  INSERT INTO `user` (`username`, `password`) VALUES (:username, :password);
QUERY;
$statement = $dbh->prepare($query);
 
$bind_params = array(':username' => "laruence", ':password' => "weibo");
foreach( $bind_params as $key => $value ){
    $statement->bindParam($key, $value);
}
$statement->execute();

 最後執行的確實下面的sql。

INSERT INTO `user` (`username`, `password`) VALUES ("weibo", "weibo");

究其緣由, 也就是bindParam和bindValue的不一樣之處, bindParam要求第二個參數是一個引用變量(reference).

解決方法:

 A. 不要使用foreach, 而是手動賦值

$statement->bindParam(":username", $bind_params[":username"]); //$value是引用變量了
$statement->bindParam(":password", $bind_params[":password"]);

 B. 使用bindValue代替bindParam, 或者直接在execute中傳遞整個參數數組.

 

5. Mcrypt響應慢的一個緣由

<?php
$dmcryptText = "This string was AES-256 / CBC / ZeroBytePadding encrypted.";

$key = pack('H*', "bcb04b7e103a0cd8b54763051cef08bc55abe029fdebae5e1d417e2ffb2a00a3");
    
# 顯示 AES-128, 192, 256 對應的密鑰長度:
#     #16,24,32 字節。
$key_size =  strlen($key);
echo "Key size: " . $key_size . ", key: $key\n";
//$size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
//$iv = mcrypt_create_iv($size);  //注意這裏
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);
echo "Iv size: " . $iv_size . ", iv: $iv\n";
# 建立和 AES 兼容的密文(Rijndael 分組大小 = 128)
    # 僅適用於編碼後的輸入不是以 00h 結尾的
    # (由於默認是使用 0 來補齊數據)
$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $dmcryptText, MCRYPT_MODE_CBC, $iv);
echo base64_encode($ciphertext) . "\n";

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

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

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

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

$ 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:

 

6. 再一次, 不要使用(include/require)_once

關於使用include仍是include_once(如下,都包含require_once), 這個討論很長了, 結論也一直有, 就是儘可能使用include, 而不是include_once, 之前最多的理由的是, include_once須要查詢一遍已加載的文件列表, 確認是否存在, 而後再加載.

解釋的比較複雜,懶得解釋了,反正儘可能少用。

排除這些技術因素, 我也一直認爲, 咱們應該使用include, 而不是include_once, 由於咱們徹底能作到本身規劃, 一個文件只被加載一次. 還能夠藉助自動加載, 來作到這一點.

你使用include_once, 只能證實, 你對本身的代碼沒信心.

 

7. 關於PHP的編譯和執行分離

這篇講得不是很詳細,我也沒有可以重現出來,估計是個人打開方式不對,評論裏面不少也是說不知道怎麼apc_bin_load的,Google了半天仍是沒有可以解決,因此我就說服本身別去想了,估計也用不上。若是真的要用的話,那麼試試Facebook的HHVM或者PHP7,估計效果也比這個強。

 

8.  請手動釋放你的資源(Please release resources manually)

相關文章
相關標籤/搜索