1

PHP 有一些著名函数的持久版本,例如mysql_pconnect(已弃用)或pfsockopen

根据我的阅读,我了解到此类函数会缓存第一次调用产生的资源并在需要时重用。

  • 但是例如 pfsockopen 缓存时套接字会发生什么?
  • 它仍然打开并连接吗?
  • 如果是这样,在“睡眠”时间收到的潜在数据会发生什么?
  • 这种缓存连接的 TTL 是多少?

长话短说,所有“p”功能如何在后台真正起作用?关于这一切的官方文档几乎为零

4

2 回答 2

1

有问题的资源并没有真正缓存,不是缓存的真正含义。连接一直保持打开状态,直到脚本终止或调用适当的函数来关闭它(所以不要调用,例如mysql_close(),如果你想使用持久连接)。

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

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

我希望这对你有意义,为了完全理解它是如何工作的,我花了几个小时的试验。您可以在php.net上阅读有关它的更多信息- 文章名为“持久数据库连接”,但这只是因为最初持久连接仅适用于数据库 - 所描述的行为对于所有其他等价物都是正确的。

编辑:

忘记回答您更具体的问题:

  • 但是例如 pfsockopen 缓存时套接字会发生什么?

    什么都没有——它只是保持活力,正如上面已经解释的那样。

  • 它仍然打开并连接吗?

    是的

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

    它等着你来阅读。

  • 这种缓存连接的 TTL 是多少?

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

于 2012-12-05T10:44:11.903 回答
1

当一个请求被处理时,有几个“层”的关闭机制会进行一些垃圾收集。如果您使用的 SAPI 不会在每次请求后丢弃所有内容(例如 fcgi 或 apache 处理程序),则某些数据结构会在请求之间“存活”。其中之一是 hashmap "称为" EG(persistent_list),只需将其视为在请求之间未删除的 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_list["mysql_$host_$port..."] 的条目,如果不是则在其中放置一个新条目展示)。

在请求之间,套接字没有任何反应,或多或少就像您的脚本执行了sleep($n)一样。如果在下次返回缓存资源时查找资源时,流的处理程序实现说“它可能仍然可以”。

看:

于 2012-12-05T11:00:26.623 回答