加入收藏 | 设为首页 | 会员中心 | 我要投稿 东莞站长网 (https://www.0769zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

基于PHP-FPM进程池探秘

发布时间:2021-03-15 12:25:25 所属栏目:PHP教程 来源:网络整理
导读:PHP 支持多进程而不支持多线程;PHP-FPM 在进程池中运行多个子进程并发处理所有连接请求。通过 ps 查看PHP-FPM进程池(pm.start_servers = 2)状态如下: 从列表中可以看出,进程池www中有两个尚处于空闲状态的子进程PID 8和 PID 9。注:NLWP指轻量级进程数量
副标题[/!--empirenews.page--]

PHP 支持多进程而不支持多线程;PHP-FPM 在进程池中运行多个子进程并发处理所有连接请求。通过 ps 查看PHP-FPM进程池(pm.start_servers = 2)状态如下:

从列表中可以看出,进程池www中有两个尚处于空闲状态的子进程PID 8和 PID 9。注:NLWP指轻量级进程数量,即线程数量。

PHP-FPM(FastCGI Process Manager)是什么?PHP-FPM为PHP-CGI提供进程管理方式,可以有效控制内存和进程,可以平滑重载PHP配置,其master process是常驻内存的。FastCGI是语言无关的、可伸缩架构的CGI开放扩展,其主要行为是将CGI解释器进程保持在内存中更长时间,不是fork-and-execute,并因此获得较高的性能。FastCGI支持分布式部署,可以部署在WEB服务器以外的多个主机上。

探秘手段:模拟多线程并发执行

1. 什么是线程:

线程有时又称轻量级进程(Lightweight Process,LWP),通常由线程ID、当前指令指针(PC)、寄存器集合和堆栈组成,是进程中的一个实体,是被系统独立调度的基本单位;线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,与同属一个进程的其它线程共享进程所拥有的全部资源。 由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪、阻塞和运行三种基本状态。由于进程是资源拥有者,创建、撤消与切换开销过大,在对称多处理机(SMP)上同时运行多个线程(Threads)才是更合适的选择。线程的实体包括程序、数据和线程控制块(Thread Control Block,TCB),TCB包括以下信息:

(1)线程状态;

(2)当线程不运行时,被保存的现场资源;

(3)一组执行堆栈;

(4)存放每个线程的局部变量主存;

(5)访问同一个进程中的主存和其它资源。

但使用多个进程会使得应用程序在出现进程池内的进程崩溃或被攻击的情况下变得更加健壮。

2. 模拟多线程:

class SimulatedThread
{
//模拟线程
private $thread;

//主机名
private $host = 'tcp://172.17.0.5';

//端口号
private $port = 80;

public function __construct()
{
//采用当前时间给线程编号
$this->thread = microtime(true);
}

/**

  • 通过socket发送一个新的HTTP连接请求到本机,
  • 此时当前模拟线程既是服务端又是模拟客户端
  • 当前(程序)子进程sleep(1)后会延迟1s才继续执行,但其持有的连接是继续有效的,
  • 不能处理新的连接请求,故这种做法会降低进程池处理并发连接请求的能力,
  • 类似延迟处理还有time_nanosleep()、time_sleep_until()、usleep()。
  • 而且sleep(1)这种做法并不安全,nginx依然可能出现如下错误:
  • “epoll_wait() reported that client prematurely closed connection,* so upstream connection is closed too while connecting to upstream”
  • @return void
    */
    public function simulate()
    {
    $run = $_GET['run'] ?? 0;
    if ($run++ < 9) {//最多模拟10个线程
    $fp = fsockopen($this->host,$this->port);
    fputs($fp,"GET {$_SERVER['PHP_SELF']}?run={$run}rnrn");
    sleep(1);//usleep(500)
    fclose($fp);
    }

$this->log();
}

/**

  • 日志记录当前模拟线程运行时间
  • @return void
    */
    private function log()
    {
    $fp = fopen('simulated.thread','a');
    fputs($fp,"Log thread {$this->thread} at " . microtime(true) . "(s)rn");

fclose($fp);
}
}

$thread = new SimulatedThread();
$thread->simulate();
echo "Started to simulate threads...";

探秘汇总:本人通过运行上述脚本后,发现一些可预料但却不是我曾想到的结果

1. PHP-FPM配置项pm.max_children = 5,simulated.thread记录如下:

最新生成的(模拟)线程登记出现在红色标示条目位置是因为进程池的并发连接处理能力上限为5,因此它只可能出现在第六条以后的位置。

有意思的是绿色条目代表的(模拟)线程和红色条目代表的(模拟)线程的登记时间是一样的,说明两个(模拟)线程是并发执行的。

(编辑:东莞站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读