PHP核心如何处理客户端连接?

fri*_*ter 8 php

据我所知,对于连接到服务器的每个客户端,PHP都会为它生成一个新线程.但是我想知道它是否真实,如果它是真的,这个线程能活多久?该线程是否正确维护所有静态变量?(像数据库连接)

当这个线程被销毁时,它是否会调用所有析构函数?

小智 8

这完全取决于如何使用服务器设置PHP.我更熟悉Apache/PHP组合(而不是用PHP设置说Nginx和FastCGI),所以关注这个领域:

  1. PHP通常作为DSO(动态共享对象)模块集成到Apache中.

  2. 现在,通常在Linux/Unix下的Apache通常被设置为"预分叉"模型 - 即,当它启动时,一堆子进程被分叉(确切的数字可以通过Apache指令配置),并且它们位于'进程池准备好处理请求.

  3. 当请求到达时,内核调度程序从池中选择一个Apache进程(如果可用),并由子进程处理请求.

  4. 基于Apache设置,如果它检测到需要执行PHP脚本,则按照(1)中的设置将其交给PHP DSO.

  5. 因此,在每个请求的基础上不涉及分叉或线程,这是有效的.所有请求上下文都传递给PHP层,后者开始编译并执行PHP脚本.

    注意:如果启用了操作码缓存,则可以绕过编译步骤 - 即,编译PHP脚本上的第一个请求,并缓存其关联的操作码以便为后续请求重用(它是所有子进程共享的全局缓存).由于编译步骤很昂贵(解析脚本等等),对于生产系统,最好启用操作码缓存.

  6. 当PHP脚本完成时,它进入清理例程(内置于PHP DSO),它将清理每个请求的内存,关闭所有文件描述,包括db句柄(基于它的打开方式).一些PHP方法具有"持久"句柄(例如,打开数据库连接,文件句柄),这些句柄可以跨请求保存,因此您用于打开特定资源的功能很重要(其各自的文档突出显示).默认情况下,大多数资源仅在PHP请求的生命周期中保留,并且在PHP请求完成后会被销毁.

    关于PHP对象dtors,这一切都取决于创建对象的范围.因此,对于全局对象,其dtors将仅在请求周期结束时被调用,而其中一些将在函数返回时超出范围时被调用.

    因此,您可以免费获得内存/资源管理.您可以通过unset()调用立即触发空闲来控制它.同样从PHP 5.3开始,也可以在请求处理阶段启用垃圾收集 - 请在此处查看更多详细信息:http: //www.php.net/manual/en/features.gc.php

  7. 现在,这个Apache子程序(运行PHP脚本)重新进入准备好处理下一个请求的进程池,如步骤3所示.

我上面描述的是Linux/Unix环境中Apache/PHP的典型特征,但我认为类似的情况也适用于Microsoft设置.

同样使用nginx和FastCGI + PHP,我认为同样的循环也适用 - 即在PHP + FastCGI模块处理的请求周期结束时清理事物.这也是当nginx启动时,它将启动由FastCGI + PHP模块处理的单独进程池,并且nginx和FastCGI + PHP之间的通信发生在unix套接字中.

希望这可以帮助.

  • +1优秀的答案,我想在持久连接上进行一些扩展.请阅读**[this](http://stackoverflow.com/questions/23432948/fully-understanding-pdo-attr-persistent/23480158#23480158)**了解更多详情. (3认同)

doc*_*doc 5

它不是PHP,而是处理请求的Web服务器.PHP本身并不运行.如果网页包含PHP代码,则此类请求将由适当的PHP SAPI模块委派给PHP.有多线程,多进程Web服务器,甚至可以想象单进程Web服务器,因此如果为请求创建单独的线程或进程,它纯粹依赖于Web服务器.

在PHP文档的许多地方,你可以遇到像这样的行umask():

避免在多线程Web服务器中使用此功能.最好在创建文件后使用chmod()更改文件权限.使用umask()可能会导致并发运行脚本和Web服务器本身的意外行为,因为它们都使用相同的umask.

......这个线程活了多久?该线程是否正确维护所有静态变量?(像数据库连接)

你听起来像一个C++背景.您可能在PHP中表示全局变量.PHP内置了对数据库连接的支持,你不必担心这些事情.它们是实现细节.大多数SAPI提供持久的数据库连接,但这只是为了您的好奇心.每个进程创建一个持久连接,用于处理请求.所以在这种情况下,它们由一个进程而不是一个进程来维护.

当这个线程被销毁时,它是否会调用所有析构函数?

在PHP中,脚本完成执行时会调用析构函数.从PHP开发人员的角度来看,脚本所处的位置无关紧要.