持久性功能如何工作?

时间:2012-12-05 10:20:41

标签: php persistent-connection

PHP有一些众所周知的功能的持久版本,例如mysql_pconnect(已弃用)或pfsockopen

据我所知,我了解这些函数会缓存第一次调用产生的资源,并在需要时重用。

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

长话短说,所有“p”功能如何真正在后台运行?关于这一切的官方文件接近于零

2 个答案:

答案 0 :(得分: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设置和/或您要连接的内容。它也可能是一个硬编码的值,并且对所有这些值都不同。

答案 1 :(得分:1)

当请求被提供时,有几个关闭机制的“层”将进行一些垃圾收集。如果您使用的SAPI在每次请求后都没有丢弃所有内容(例如fcgi或apache处理程序),则某些数据结构会在请求之间“生存”。其中一个是一个“调用”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)一样。如果在下次返回缓存资源时查找资源,则流的处理程序实现会说“它可能仍然可以”。

见: