php多線程詳解


在說明多線程的題前,需要弄清楚以下幾個問題

1,ts 和 nts的區別

 Thread Safe和NoneThread Safe

先說windows的,在php官網,在windows區域有在文件下在有

http://windows.php.net/download#php-7.0

文件名有很明顯區分

VC14 x86 Non Thread Safe (2016-May-25 23:02:14)

VC14 x86 Thread Safe (2016-May-25 23:02:14)

VC6與VC9的區別:

VC6版本是使用Visual Studio 6編譯器編譯的,如果你的PHP是用Apache來架設的,那你就選擇VC6版本。

VC9版本是使用Visual Studio 2008編譯器編譯的,如果你的PHP是用IIS來架設的,那你就選擇 VC9版本。

VC9版本是針對IIS服務器的版本,沒有對APACHE的支持,而VC6版本對IIS和apache都提供了支持

 

 

Windows版的PHP從版本5.2.1開始有Thread Safe和NoneThread Safe之分。

先從字面意思上理解,Thread Safe是線程安全,執行時會進行線程(Thread)安全檢查,以防止有新要求就啟動新線程的CGI執行方式而耗盡系統資源。Non Thread Safe是非線程安全,在執行時不進行線程(Thread)安全檢查。

 

Linux上的PHP同樣有NTS和TS版本的區別,默認是NTS版本,configure時加上--enable-maintainer-zts則編譯為TS版本.什么時候需要TS版本呢?比如你要使用pthreads這個多線程的PECL擴展時,或者PHP以MOD_PHP嵌入多線程運行下的Apache,比如Apache在Linux上提供的Event MPM就是一個多進程多線程的工作模型,Windows上Apache采用的WinNT MPM也是一個多線程模型,這時都需要TS版本的PHP.

 
         
         
        

而如果以PHP-FPM(比如搭配Nginx或者Apache的mod_fastcgi)或者PHP-CGI(比如搭配Apache的mod_fcgid或者Win上的IIS)來運行PHP,則一般都不需要TS線程安全版本的PHP.這個在之前博客也說過

2,運行模式

 

1)CGI(通用網關接口 / Common Gateway Interface)

2)FastCGI(常駐型CGI / Long-Live CGI)

3)CLI(命令行運行 / Command Line Interface)

4)Web模塊模式(Apache等Web服務器運行的模式)

5)ISAPI(Internet Server Application Program Interface)

備注:在PHP5.3以后,PHP不再有ISAPI模式,安裝后也不再有php5isapi.dll這個文件。要在IIS6上使用高版本PHP,必須安裝FastCGI 擴展,然后使IIS6支持FastCGI。

為什么要說運行模式呢?因為在有些擴展並發的時候,有些擴展只能在cli下運行,其實不是

3,php多線程

 目前常用的擴展有pcnlt,POSIX ,pthreads,這三個比較多,但是與其說是多線程其實多進程,在並發的時候會巨急消耗內存所以用的時候,請注意,比如pcnlt,

真的多線程只有pthreads,但是本人沒有確認過,參看http://zyan.cc/pthreads/,因為我現在的測試環境是nts的,所有測試就必須重新在做一個新環境

所以來不及測試,后續更新測試結果,還有一個問題就是php-fpm去管理php的內存帶來的php並發效果不錯,但是php-fpm會有一個壞處就是執行完之后,不會主動把內存

還給系統而是吧資源依然控制在php-fpm,所以為什么php第一次運行慢,第二次速度就上來了,這個就帶來一個問題關於php-fpm分配內存的選擇

dm有三種分配方式dynamic ,static,demand,光這個調優就得一片文章來講,所以pcnlt在服務器正式環境使用 最好是吧內存弄大一些,而且並發數也不要多

不然很容易內存消耗過多,導致錯誤,這里還有一個地方值得注意的是,當php以靜態模塊在apache下運行的時候內存消耗是怎么樣的,會及時還給系統嗎?,和php-fpm管理內存對比也是值得注意的,這測試也是有必要去做的

4,實際運用和測試

 在php的源碼包的ext下面有下面很多擴展

bcmath dba fileinfo iconv mbstring odbc pdo_firebird phar shmop sqlite3 tokenizer zip
bz2 dom filter imap mcrypt opcache pdo_mysql posix simplexml standard wddx zlib
calendar enchant ftp interbase mssql openssl pdo_oci pspell skeleton sybase_ct xml
com_dotnet ereg gd intl mysql pcntl pdo_odbc readline snmp sysvmsg xmlreader
ctype exif gettext json mysqli pcre pdo_pgsql recode soap sysvsem xmlrpc
curl ext_skel gmp ldap mysqlnd pdo pdo_sqlite reflection sockets sysvshm xmlwriter
date ext_skel_win32.php hash libxml oci8 pdo_dblib pgsql session spl tidy xsl

安裝pcntl

在php的源碼包里面ext下面會有,如果前期沒有在編譯時安裝上需要擴展,不必要重新編譯,

我php安裝在/usr/local/php/bin  

cd到pcntl

cd /usr/local/src/php-5.6.2/ext

/usr/local/php/bin/phpize

./configure --with-php-config=/usr/local/php/bin/php-config

make && make install

 

在 php.ini 里面加上

extension=pcntl.so

restart php-fpm 和nginx

php-m 或者phpinfo查看下擴展是否成功

 

下面是一個簡單的測試代碼

<?php

set_time_limit(0);
error_reporting(E_ALL); 
 $sc = new  SoapClient('http://10.168.33.22/Service.svc?wsdl'); //正式服測試機器接口性能測試
 

 
// var_dump($return->GetOrderNoResult);

 $file='./log.txt';


 //多線程性能測試+壓力測試

 
//$max = 2000;
$workers =10;

$pids = array();
for($i = 0; $i < $workers; $i++){
   $pids[$i] = pcntl_fork();
   $pid = pcntl_fork();

if ($pid == -1) {
    //錯誤處理:創建子進程失敗時返回-1.
     die('could not fork');
} else if ($pid) {
     //父進程會得到子進程號,所以這里是父進程執行的邏輯
     pcntl_wait($status); //等待子進程中斷,防止子進程成為僵屍進程。
} else {
     //子進程得到的$pid為0, 所以這里是子進程執行的邏輯。
//     var_dump($pid[$i]);
    
    for($j= $i*5;$j<=($i+1)*5;$j++){
    $start = microtime(true);
    $return =  $sc->Get();
    if($return->GetResult){

        $end = microtime(true);
        $time = $end - $start;
        
        $str =  '第'.$j.'請求成功,消耗時間-'.$time.'-占用訂單號-'.$return->Get1.'<br>';
        $fp = fopen($file, "a");
        fwrite($fp, $str);
        fclose($fp);
        echo $str;
    }else{
        
        $end = microtime(true);
        $time = $end - $start;
        
        $str =  '第'.$j.'請求失敗,消耗時間-'.$time.'-占用訂單號-'.$return->Get1.'<br>';
        $fp = fopen($file, "a");
        fwrite($fp, $str);
        fclose($fp);
        echo $str;
    }
}
  
}
}

 你可以運行的時候top看下,並發急劇消耗的內存,這個代碼測試可以你線上正式服並發情況,比如你要測試首頁服務器最大並發數,在內網機器,或者本地大內存機器上做測試,小內存機器用這個測不出極限值


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM