4

動的コンテンツをキャッシュするためのこの単純な方法はregister_shutdown_function()、スクリプトの終了後に、出力バッファーをディスク上のファイルにプッシュするために使用します。ただし、私はこれが機能しないPHP-FPMを使用しています。関数に 5 秒間のスリープを追加すると、ブラウザからのスクリプトの実行に 5 秒間の遅延が発生します。PHP ドキュメントのコメント投稿者は、PHP-FPM ユーザー向けの特別な関数、つまりfastcgi_finish_request(). ただし、この特定の機能に関するドキュメントはあまりありません。

のポイントは、fastcgi_finish_request()すべてのデータをフラッシュして他のタスクを続行することのようですが、私が達成したいのは、通常register_shutdown_function().終わる。

fastcgi_finish_request()または別の関数を使用して、PHP-FPMでこれを達成する方法はありますか?

$timeout = 3600; // cache time-out
$file = '/home/example.com/public_html/cache/' . md5($_SERVER['REQUEST_URI']); // unique id for this page
if (file_exists($file) && (filemtime($file) + $timeout) > time()) {
  readfile($file);
  exit();
} else {
  ob_start();
  register_shutdown_function(function () use ($file) {
    // sleep(5);
    $content = ob_get_flush();
    file_put_contents($file, $content);
  });
}
4

3 に答える 3

3

はい、そのために使用することは可能fastcgi_finish_requestです。このファイルを保存して、動作することを確認できます。

<?php

$timeout = 3600; // cache time-out
$file = '/home/galymzhan/www/ps/' . md5($_SERVER['REQUEST_URI']); // unique id for this page
if (file_exists($file) && (filemtime($file) + $timeout) > time()) {
  echo "Got this from cache<br>";
  readfile($file);
  exit();
} else {
  ob_start();
  echo "Content to be cached<br>";

  $content = ob_get_flush();
  fastcgi_finish_request();
  // sleep(5);

  file_put_contents($file, $content);
}

で行のコメントを外しても、データをブラウザに送り返し、その後に記述されたコードに進むsleep(5)ため、ページがまだすぐに開くことがわかります。fastcgi_finish_request

于 2013-02-23T10:33:07.070 に答える
1

まず、この方法で動的コンテンツをキャッシュすると、間違っています。確かにこの方法で使用でき、機能する可能性がありますが、アプローチ自体によって完全に麻痺しています。

コンテンツを効率的にキャッシュして処理する場合は、1 つのクラスを作成し、すべてのキャッシュ関数をラップします。

fast_cgi_finish_request()はい、のように使用できますregister_shutdown()。唯一の違いは、fast_cgi_finish_request()は出力 (存在する場合) を送信し、スクリプトを終了しませんが、スクリプトの終了時に のコールバックregister_shutdown()が呼び出されることです。

于 2013-03-01T23:08:31.187 に答える
0

これは古い質問ですが、どの回答も問題を正しく解決しているとは思いません。

私が理解しているように、問題は、シャットダウン関数中に発生する ob_get_flush() 呼び出しまで、出力がクライアントに送信されないことです。

この問題を修正するには、出力をチャンクで処理するために、関数とチャンク サイズを ob_start() に渡す必要があります。

あなたのelse句には次のようなものがあります:

$content = '';

$write_buffer_func = function($buffer, $phase) use ($file, &$content) {
  $content .= $buffer;
  if ($phase & PHP_OUTPUT_HANDLER_FINAL) {
    file_put_contents($file, $content);
  }
  return $buffer;
};

ob_start($write_buffer_func, 1024);
于 2015-08-12T14:01:59.617 に答える