• PHP多进程模拟多客户端并发访问远程mysql数据库进行网络压力测试


    因为一台服务器(Server  A)被IDC无故断电产生了文件根目录不能写的情况,所以需要切换在这台服务器上跑着的数据和业务到另一台(Server  B)上,才能停掉在A上的业务进行维修,在数据迁移之前,需要对B上的数据库做一个压力测试,看看能否同时兼顾现有和附加的数据库的吞吐。

      参考了张宴的《PHP多进程并发控制的测试用例》一文,帮助良多,这里记录一下。

      大致思路是:规定一个最大进程数$limit,防止向后台推送的进程数过多导致本地的电脑爆表;同时设定一个变量记录当前剩余的空闲子进程数$p_number (空闲子进程数 = 最大进程数 - 当前脚本已经占用的进程数,一开始的空闲子进程数是0,也可以直接设置初始等于最大进程数$limit)。当剩余子进程数够用($p_number > 0),则开一个子进程给dosql.php脚本,在这个脚本里进行远程连接mysql然后进行一些CRUD的操作并且将操作记录放到ptest.log日志文件中,空闲子进程数减一;否则($p_number <= 0)就让脚本等待一秒钟,去读取当前系统中已有的进程数$line,那么剩余空闲子进程数就是$p_number = $limit - $line(所以一开始$p_number = 0也没关系,刚开始时$line = 0,$p_number = $limit),如果$p_number > 0,那么就可以开一个新的子进程,否则再等一秒,如此往复。

      上代码:

    ptest.php:

    <span style="font-size:14px;"><?php  
    /* 
     * 目的:利用popen()在后台打开多个进程连接远程mysql数据库模拟多客户端并发查询/操作,进行压力吞吐测试 
     * @$p_number:空闲的进程数 
     * @$limit:最大进程数 
    */  
      
      
        /* 
         *功能:在子进程数 < $limit下,打开多个子进程执行dosql.php;在空闲子进程不够的情况下($p_number <= 0),等待1秒继续执行 
        */  
        function run(){  
            global $p_number;  
            if($p_number <= 0){  
                $p_number = work_process($p_number);  
            }  
            $p_number = $p_number - 1;  
            $out = popen("/usr/bin/php /opt/dosql.php  &","r");  
            pclose($out);  
        }  
      
      
        /* 
         *功能:设置最大进程数$limit,查看当前已经打开的子进程脚本(dosql.php)占用的进程数,若空闲子进程不够用,则等待1秒;否则把剩余空闲子进程数返回给run() 
        */  
        function work_process($p_number){  
            $limit = 3000;  
            while($p_number <= 0){  
                //后台去查看dosql.php这个脚本占用的进程数  
                $cmd = popen("ps -ef | grep "/opt/dosql.php" | grep -v grep | wc -l","r");  
                $line = fread($cmd,512);  
                pclose($cmd);  
                $p_number = $limit - $line;  
                if($p_number <= 0){  
                    sleep(1);  
                }  
            }  
            return $p_number;  
        }  
      
          
        /* 
         *开始$count次mysql操作并发到$limit个子进程中执行 
        */  
        $count = 5000;  
        for($i = 0;$i < $count;$i++){  
            run();  
            echo "Idle process number :" . $p_number . "
    ";  
        }  
          
    ?>  
    </span>  
    

      dosql.php:

    <?php  
    /* 
     *说明:子进程执行的脚本,连接远程mysql数据库并且进行一系列增删查改操作,记录下所需时间到log文件中.每个子进程的mysql语句都是no query cache的. 
    */  
        $stime = time();          
        $dbhost = "xx.xx.xx.xx";  
        $dbuser = "root";  
        $dbpwd = "xxxx";  
        $dbname = "test";  
        $dbcharset = "gbk";  
          
        $conn = mysql_connect($dbhost,$dbuser,$dbpwd) or die("can not connect mysql host ".$dbhost);  
            if($dbcharset){  
                mysql_query("set names ".$dbcharset);  
            }  
            if($dbname){  
                    mysql_select_db($dbname,$conn) or die("can not select db ".$dbname);  
            }  
            /* 
             * 这里可以做一些CRUD的复杂操作,例子很简单。 
            $table1 = "pre_common_member"; 
            $sql = "select sql_no_cache * from `$table1` where uid = 78"; 
        $result = mysql_query($sql,$conn); 
        $data = @mysql_fetch_array($result); 
        if($data) 
            dolog("success",$stime); 
        else 
            dolog("fail",$stime); 
        mysql_close($conn); 
        */  
      
        /* 
         *功能:记录log,包括每个sql语句的开始/结束时间/耗费时间(sec),以及是否查询成功的标志 
        */  
        function dolog($input,$stime){  
            $etime = time();  
            $duration = $etime - $stime;  
            file_put_contents("/opt/ptest.log","start time :".date("Y-m-d H:i:s",$stime)."  end time :".date("Y-m-d H:i:s",$etime)."   ".$input."  duration :".$duration.PHP_EOL,FILE_APPEND | LOCK_EX);  
        }  
    ?>  
    

      执行脚本:

      /usr/bin/php /opt/ptest.php

     

      将PHP程序作为Linux守护进程的方法:

      nohup /usr/bin/php /opt/ptest.php 2>&1 > /dev/null &

    (nohup命令可以在用户退出终端后仍然执行程序,“2>&1 > /dev/null”表示不显示标准输出和错误输出,最后的&表示推到后台执行。)

     

     

      PS.可以在dosql.php中做一些复杂的查询操作,以测试mysql的压力极限,当然ptest.php中开的最大进程数也是与网站的并发访问量有关系的,只能说是尽可能地去模拟。对于dolog()也可以把记录放到本地数据库中,这样可以更详尽地分析查看语句执行的情况了,比如哪些语句的平均执行时间大于2秒等等。

      又想到一个问题,对于那些并发访问量特别大的,进程数开不了这么多的话,不知道该怎么做网络延迟的测试了。

      PS.mysql 5.1.x之后自带个mysqlslap,可以用几句命令很方便地做到模拟mysql的并发访问操作,但是好像只是本机测试的,没法做远程测试?

    1. <span style="font-size:14px;"><?php  
    2. /* 
    3.  * 目的:利用popen()在后台打开多个进程连接远程mysql数据库模拟多客户端并发查询/操作,进行压力吞吐测试 
    4.  * @$p_number:空闲的进程数 
    5.  * @$limit:最大进程数 
    6. */  
    7.   
    8.   
    9.     /* 
    10.      *功能:在子进程数 < $limit下,打开多个子进程执行dosql.php;在空闲子进程不够的情况下($p_number <= 0),等待1秒继续执行 
    11.     */  
    12.     function run(){  
    13.         global $p_number;  
    14.         if($p_number <= 0){  
    15.             $p_number = work_process($p_number);  
    16.         }  
    17.         $p_number = $p_number - 1;  
    18.         $out = popen("/usr/bin/php /opt/dosql.php  &","r");  
    19.         pclose($out);  
    20.     }  
    21.   
    22.   
    23.     /* 
    24.      *功能:设置最大进程数$limit,查看当前已经打开的子进程脚本(dosql.php)占用的进程数,若空闲子进程不够用,则等待1秒;否则把剩余空闲子进程数返回给run() 
    25.     */  
    26.     function work_process($p_number){  
    27.         $limit = 3000;  
    28.         while($p_number <= 0){  
    29.             //后台去查看dosql.php这个脚本占用的进程数  
    30.             $cmd = popen("ps -ef | grep "/opt/dosql.php" | grep -v grep | wc -l","r");  
    31.             $line = fread($cmd,512);  
    32.             pclose($cmd);  
    33.             $p_number = $limit - $line;  
    34.             if($p_number <= 0){  
    35.                 sleep(1);  
    36.             }  
    37.         }  
    38.         return $p_number;  
    39.     }  
    40.   
    41.       
    42.     /* 
    43.      *开始$count次mysql操作并发到$limit个子进程中执行 
    44.     */  
    45.     $count = 5000;  
    46.     for($i = 0;$i < $count;$i++){  
    47.         run();  
    48.         echo "Idle process number :" . $p_number . " ";  
    49.     }  
    50.       
    51. ?>  
    52. </span>  
  • 相关阅读:
    eri
    elasticsearch集群搜集nginx日志
    linux 常用
    如何清理Docker占用的磁盘空间?
    ubuntu1804 64位 apt源
    postgresql笔记
    web前端——02 body标签中相关标签
    web前端——01 html介绍和head标签
    python数据库——pymysql模块的使用
    MySql数据库——可视化工具Navicat的使用
  • 原文地址:https://www.cnblogs.com/zoutong/p/13522078.html
Copyright © 2020-2023  润新知