Question

PHP has some persistent version of well-known functions such as mysql_pconnect (deprecated) or pfsockopen

From what I've read, I understand that such functions cache the resource produced by the first call and reused when needed.

  • But for exemple with pfsockopen what happen to the socket when it's cached ?
  • is it still open and connected ?
  • If so , what happen to the potential data received during the "sleep" time ?
  • What is the TTL of such cached connection ?

Long story short , how does all the "p" functions really works in background ? The official doc about all this is close to nil

Was it helpful?

Solution

The resource in question isn't really cached, not in the true meaning of cache that is. The connections are just kept open until the script terminates or until you call the appropriate function that closes it (so don't call e.g. mysql_close() if you want to use a persistent connection).

Now, the real question is - what does "until the script is terminated" mean. This may vary or may not be possible, depending on the PHP SAPI that's currently used, but let's take Apache with support for HTTP/1.1 + mod_php as an example - it's the most popular and easiest to explain ...

HTTP/1.1 is required, because it has Keep-Alive - something rather strange for a stateless protocol. When you access a page, Apache runs your PHP script under a thread or a new system process. And here's the catch - your script does execute in it's entirety, but Apache does NOT terminate the thread or process in question, allowing it to maintain persistency for resources that are left open. How exactly it's done I'm not sure I can explain, but with Keep-Alive your next HTTP request will be attached by Apache to the same thread or process id, allowing possibility to reuse that resource. The second part is more of just a basic sanity check - you can only attach to a persistent connection if you're using the same "options" and/or credentials that you've used to create it. So if you call mysql_connect() with a different username - it will create a new connection and won't reuse the old one (it's signature doesn't match). But given that supposedly the same script is re-executed, this is only a "fomality" in most cases.

I hope that makes sense to you, it took me a few hours of experimenting in order to fully understand how it works. You can read more about it on php.net - the article is named "Persistent Database Connections", but that's only because originally persistent connections were only available for databases - the described behavior is true for all other equivalents.

Edit:

Forgot to answer your more specific questions:

  • But for exemple with pfsockopen what happen to the socket when it's cached ?

    Nothing - it's just kept alive, as already explained above.

  • Is it still open and connected ?

    Yes

  • If so , what happen to the potential data received during the "sleep" time ?

    It waits for you to read it.

  • What is the TTL of such cached connection ?

    That in particular I can't answer - it may depend on the options that you pass to the p* function, your php.ini settings and/or what you're connecting to. It may also be a hard-coded value and to be different for all of them.

OTHER TIPS

When a request is served there are several "layers" of shutdown mechanisms that will do some garbage collection. If you use a SAPI that doesn't throw out everything after each request (e.g. fcgi or the apache handler) some data structures "survive" between the requests. One of them is a hashmap "called" EG(persistent_list), just think of it as an php array $EG_presistent_list that isn't removed between requests.
Now when your script call pfosckopen($host, $port, ...) the implementation does (more or less - sorry for the oversimplification) the following

$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;

(the mysql_pconnect() implementation works a little bit different - but only a little; it still looks up an entry like $EG_persistent_list["mysql_$host_$port..."] and puts a new one in there if it isn't present).

Inbetween requests nothing happens to the socket, it's more or less as if your script does a sleep($n). If the handler implementations of the stream say "it may still be ok" when the resource is looked up the next time the cached resource is returned.

see:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top