Php 持久性函数是如何工作的?

Php 持久性函数是如何工作的?,php,persistent-connection,Php,Persistent Connection,PHP有一些已知函数的持久版本,例如(不推荐使用)或 通过阅读,我了解到这些函数缓存第一次调用生成的资源,并在需要时重用 但以pfsockopen为例,当插座打开时会发生什么情况 缓存 它是否仍然打开并连接 如果是这样,在测试过程中接收到的潜在数据会发生什么变化 “睡觉”时间 这种缓存连接的TTL是什么 长话短说,所有的“p”函数在后台是如何工作的?关于这一切的官方文档几乎为零所讨论的资源并不是真正的缓存,也不是真正意义上的缓存。连接一直保持打开状态,直到脚本终止或调用相应的函数关闭它(因此

PHP有一些已知函数的持久版本,例如(不推荐使用)或

通过阅读,我了解到这些函数缓存第一次调用生成的资源,并在需要时重用

  • 但以pfsockopen为例,当插座打开时会发生什么情况 缓存
  • 它是否仍然打开并连接
  • 如果是这样,在测试过程中接收到的潜在数据会发生什么变化 “睡觉”时间
  • 这种缓存连接的TTL是什么

长话短说,所有的“p”函数在后台是如何工作的?关于这一切的官方文档几乎为零

所讨论的资源并不是真正的缓存,也不是真正意义上的缓存。连接一直保持打开状态,直到脚本终止或调用相应的函数关闭它(因此,如果要使用持久连接,请不要调用例如
mysql\u close()

现在,真正的问题是,“直到脚本终止”是什么意思。这可能会有所不同,也可能不可能,这取决于当前使用的PHP SAPI,但让我们以支持HTTP/1.1+mod_PHP的Apache为例—它是最流行、最容易解释的

HTTP/1.1是必需的,因为它具有Keep-Alive特性——对于无状态协议来说,这是相当奇怪的。访问页面时,Apache会在线程或新系统进程下运行PHP脚本。 这里有一个问题——您的脚本确实完整地执行,但Apache不会终止有问题的线程或进程,从而允许它对保持打开状态的资源保持持久性。具体是如何完成的,我不确定能否解释清楚,但使用Keep Alive,Apache会将您的下一个HTTP请求附加到相同的线程或进程id,从而允许重用该资源。 第二部分只是一个基本的健全性检查——只有在使用与创建持久性连接相同的“选项”和/或凭据时,才能连接到持久性连接。因此,如果您使用不同的用户名调用
mysql\u connect()
,它将创建一个新的连接,并且不会重用旧的连接(它的签名不匹配)。但考虑到假定相同的脚本被重新执行,这在大多数情况下只是一种“恶意”

我希望这对你们来说是有意义的,我花了几个小时的时间进行实验,以便完全理解它是如何工作的。您可以在上阅读更多关于它的内容—文章名为“持久数据库连接”,但这只是因为最初的持久连接仅适用于数据库—所描述的行为适用于所有其他等价物

编辑:

忘记回答更具体的问题:

  • 但以pfsockopen为例,缓存套接字时会发生什么情况

    没什么-它只是保持活着,正如上面已经解释过的

  • 它是否仍然打开并连接

  • 如果是这样,在“睡眠”时间内接收到的潜在数据会发生什么变化

    它等待着你去阅读它

  • 这种缓存连接的TTL是什么

    这一点我尤其无法回答——这可能取决于传递给p*函数的选项、php.ini设置和/或连接的对象。它也可能是一个硬编码的值,并且对于所有这些值都是不同的


当服务请求时,有几个“层”的关闭机制将执行一些垃圾收集。如果您使用的SAPI不会在每次请求后抛出所有内容(例如fcgi或apache处理程序),则某些数据结构会在请求之间“存活”。其中一个是hashmap“called”,只需将其视为一个php数组$EG_presistent_list,在请求之间不会被删除。
现在,当您的脚本调用pfosckopen($host,$port,…)时,实现会执行以下操作(多多少少,很抱歉过于简化):

$persistentKey = "pfsockopen__$host:$port";
$stream= $EG_persistent_list[$persistentKey];
if ( $stream ) {
    // this one looks up which module creates such a stream
    // and "asks" it to check whether this stream may still be working
    if ( !CHECK_LIVENESS($stream) ) {
        $stream = null;
    }
}

if ( !$stream ) {
    $stream = createANewOne(...);
    $EG_persistent_list[$persistentKey] = $stream;
}
return $stream;
(mysql_pconnect()实现的工作原理稍有不同,但只有一点不同;它仍然会查找一个类似$EG_persistent_ulist[“mysql_$host_$port…”的条目,如果它不存在,则在其中放入一个新条目)

在两个请求之间,套接字不会发生任何变化,就好像您的脚本执行了一个命令一样。如果流的处理程序实现在下次返回缓存资源时查找资源时说“它可能仍然正常”

见:

  • 中的php_fsockopen_流(内部函数参数,int persistent)
  • _php\u流\u导出\u在中创建(…)
  • php_stream_from_persistent_id(…)in