• 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看下,并发急剧消耗的内存,这个代码测试可以你线上正式服并发情况,比如你要测试首页服务器最大并发数,在内网机器,或者本地大内存机器上做测试,小内存机器用这个测不出极限值

  • 相关阅读:
    完成后台管理系统功能(三)查询商品信息列表
    完成后台管理系统功能(二)有关SSM的整合
    实现后台管理系统功能(一)maven工程的建立
    开始‘京西商城’的电商项目(SSM)
    到此,使用struts2+hibernate实现登陆以及学生列表的增删改查 结束 -------------------------------------------------------
    chrome 中 preview 和 response 数据不一致
    单元测试执行过程中忽略出错的单元测试
    使用Maven 构建时跳过单元测试
    使用 AutoIt3 加密解密数据
    SpringBoot 启动流程
  • 原文地址:https://www.cnblogs.com/zx-admin/p/5564984.html
Copyright © 2020-2023  润新知