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 が必要です。これは、ステートレス プロトコルとしてはかなり奇妙なことです。ページにアクセスすると、Apache はスレッドまたは新しいシステム プロセスの下で PHP スクリプトを実行します。ここにキャッチがあります-スクリプトは完全に実行されますが、Apacheは問題のスレッドまたはプロセスを終了せず、開いたままのリソースの永続性を維持できます. 正確にどのように行われるかはわかりませんが、Keep-Alive を使用すると、次の HTTP リクエストが Apache によって同じスレッドまたはプロセス ID にアタッチされ、そのリソースを再利用できるようになります。2 番目の部分は、基本的な健全性チェックにすぎません。永続的な接続を作成するために使用したのと同じ「オプション」や資格情報を使用している場合にのみ、永続的な接続に接続できます。mysql_connect()別のユーザー名で - 新しい接続を作成し、古い接続を再利用しません (署名が一致しません)。しかし、おそらく同じスクリプトが再実行されることを考えると、これはほとんどの場合「形式的」にすぎません。

理解していただけると幸いです。そのしくみを完全に理解するには、数時間の実験が必要でした。詳細については、php.netを参照してください。この記事の名前は「永続的なデータベース接続」ですが、それは、もともと永続的な接続がデータベースでしか利用できなかったからです。説明されている動作は、他の同等のものすべてに当てはまります。

編集:

より具体的な質問に答えるのを忘れました:

  • しかし、たとえば pfsockopen の場合、ソケットがキャッシュされるとどうなるでしょうか?

    何もありません - すでに上で説明したように、それは生き続けています。

  • まだ開いていて接続されていますか?

    はい

  • その場合、「スリープ」時間中に受信した潜在的なデータはどうなりますか?

    あなたがそれを読むのを待っています。

  • そのようなキャッシュされた接続の TTL は何ですか?

    特に私は答えられません - p* 関数に渡すオプション、php.ini 設定、および/または接続先に依存する場合があります。また、ハードコードされた値であり、すべての値が異なる場合もあります。

于 2012-12-05T10:44:11.903 に答える
1

リクエストが処理されると、いくつかのガベージ コレクションを実行するシャットダウン メカニズムの「レイヤー」がいくつかあります。各リクエストの後にすべてをスローしない SAPI (例: fcgi や apache ハンドラ) を使用すると、いくつかのデータ構造がリクエスト間で「存続」します。そのうちの 1 つは「呼び出された」ハッシュマップ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 に答える