Manual:File cache

From MediaWiki.org
Jump to navigation Jump to search
This page is a translated version of the page Manual:File cache and the translation is 96% complete.
Other languages:
English • ‎español • ‎français • ‎中文 • ‎日本語

MediaWikiには、記事ページのレンダリングされたHTMLをキャッシュするためのオプションの単純なスキームがあります。

操作と使用

The file cache serves anonymous users only and they see the same HTML rendered. Logged-in users don't benefit from this cache because their page contains user name, selected skin, etc.

ファイル キャッシュを有効にするには、LocalSettings.php 内で3つの変数に設定します:

$wgUseFileCache  = true; /* 既定値: false */
$wgFileCacheDirectory  = "$IP/cache"; # または既定値のままにしておきます: "{$wgUploadDirectory}/cache"の既定値は"$IP/images/cache"

これにより、ウィキの各ページのレンダリングされたHTML Webページがハードディスク上の個々のファイルに保存されます。その後の匿名ユーザーのリクエストは、ページを再表示するのではなく、ディスクに保存されているHTMLバージョンを送信するだけで満たされます。これにより時間が節約されます。

生成したHTMLウェブテキストはディスク上の$wgFileCacheDirectoryの下位ディレクトリに保存されます。

-rw-r--r-- 1 apache apache 57421 Jan  7 01:58 cache/0/04/P%C3%A1gina_principal.html
-rw-r--r-- 1 apache apache 29608 Jan  4 16:37 cache/1/17/P%C3%A1gina_Riscada.html
-rw-r--r-- 1 apache apache 21592 Jan  3 07:27 cache/1/1c/P%C3%A1gina_Duplicada.html
-rw-r--r-- 1 apache apache 36088 Jan  7 02:03 cache/2/24/P%C3%A1gina_principal_alternativa.html
-rw-r--r-- 1 apache apache 44205 Jan  7 06:10 cache/a/a4/P%C3%A1gina_linkada.html
-rw-r--r-- 1 apache apache 24686 Jan  3 07:27 cache/d/db/P%C3%A1gina_Invertida.html
-rw-r--r-- 1 apache apache 17222 Jan  3 06:28 cache/f/f0/P%C3%A1gina_n%C3%A3o_encontrada.html

この例ではファイルはcache/ ディレクトリにキャッシュされ、保存されたウィキのページにはPágina ... という一連の名称が与えられ1件ずつPágina_....htmlを取得します。これらのファイルは、ユーザーがウィキ上のファイルにアクセスするたびに生成されるもので、rebuildFileCache.phpmaintenance scriptを使用すると一括して生成できます。

ファイルキャッシュは積極的にキャッシュする傾向があり、キャッシュされたページに有効期限は設定されておらず、ページに変数、拡張子およびその他の変更可能な出力が含まれていても、無条件にキャッシュします。特定の拡張機能は、動的コンテンツを持つページのファイルキャッシュを無効にします。

より効果的な結果を得るには$wgUseGzipを代用するか、組み合わせて使用することを検討してください。

規模が大きなサイトでは、ファイルキャッシュにSquidあるいはVarnish等、外部のキャッシュの利用が望まれます。

ファイルキャッシュが機能していないと思ったら、指定したディレクトリがウェブサーバの書き込みを許可しているかどうか確認してください。

制限

キャッシュファイルのファイル名は、ページのタイトルに従って決定されます。 ページ題名の使用言語により、ファイルシステムにおいて有効なファイル名を生成するため、特定の文字のエンコードが必要な場合があります。 アラビア語、中国語などの言語の場合、次のようなPHP警告が表示されることがあります:

PHP Warning:  file_put_contents(cache/......html.gz): failed to open stream: File name too long in includes/cache/FileCacheBase.php on line 171

これは既知の制限です。 タスク T148684 を参照してください。

カテゴリおよび画像の説明ページは、ファイルキャッシュからパージされません。 たとえば、カテゴリからページを追加または削除してもカテゴリページは更新されないため、ログインしていないユーザーはカテゴリページの変更を見ることができません。 これは既知の制限です。 タスク T26575 を参照してください。

ドメインと範囲

キャッシュ処理が可能なユーザーの対象:

  • ログインしていない。
  • user_newtalkのフラグを無効にしてある。

キャッシュする対象のページとは:

  • 特別ページではない。
  • リダイレクトではない。
  • 現在のバージョンで閲覧でき、明示され、urlパラメータを使用していない。

これでウィキに対する要求の大部分をカバーできるものの、その他の項目の処理にはバイトコードとソフトウェアのキャッシュ処理の設定が重要です。

検証

キャッシュしたファイルの変更時刻は、各ビューの LocalSettings.php で設定されたグローバルな $wgCacheEpoch タイムスタンプと比較されます。

もしファイルの保存費付けがこれらと同じであれば有効と判断され、クライアントへ直接送られます。日付が古いもしくは存在しない場合、パーシングとレンダリングが続行して将来の利用のために記録されます。

無効化

$wgCacheEpochを現在時刻に設定するか、キャッシュのファイルをすべて削除すると、全キャッシュを無効にできます。

個々のページの無効化には page.page_touched フィールドの更新を行い、Title::invalidateCache() を呼び出すと簡便に実行できます。 (編集リンクの更新のため) 新規記事の作成や編集の保存、改名やリンク記事の作成・削除のたびに、これを必ず行ってください。 例えばテンプレートの編集による無効化の操作は、page_touched とキャッシュ日付を照合するテンプレートを採用するページを確認します。

事例によっては以下のように、まだ適切に処理されていません。

  • ブラウザの〈再読み込み〉あるいは〈リフレッシュ〉(更新せずに同じページをリロードする)
  • Extension:DynamicPageListなど拡張機能からの出力変数は、該当するページのファイルキャッシュを無効化、古いデータを回避します。 そうしないと、ブラウザの更新時に古いデータが返されます。
  • 特定の長いエラーメッセージは、あたかも有効なページコンテンツであるかのように無期限にキャッシュされてしまうかもしれません。保存されたファイルキャッシュからこれらを削除するのは ?action=purge に限定されます。 最小出力サイズのしきい値を使用し、致命的な PHP エラー等、ほとんどのエラーをキャッシュしないようにしています。

関連項目: Manual:$wgInvalidateCacheOnLocalSettingsChange

有効期限

特に変数を含むページの場合、おそらくはキャッシュページの有効期限が切れる方法があるはずです(X日間に記事X件がある等)。

$parserOutput->getCacheTime()-1 のとき、ページ出力のファイルキャッシュを無効にします。 有効期限設定の規定がないため、全ページの全HTMLは永久にキャッシュされ続けます。 明示的な ?action=purge コマンド (またはページの編集) によって特定のページは再生成されますが、有効期限切れの拡張機能の出力がファイルをキャッシュしたページの一部として記録されると、MediaWiki 内部の no-cache フラグまたはブラウザーの更新でもそれを削除しません。

更新タブ

Purge page extensionを当てて?action=purgeを実行すると、特定の個別のページを強制的に無効化して更新するタブを追加できます。

圧縮

選択肢として、キャッシュを圧縮して空間と帯域を節約できます。(前提としてPHP configにおいてzlibが有効。)

$wgUseGzip = true;

If compression is enabled, the cache files are saved as .html.gz. Browsers that advertise support for gzip in their Accept-Encoding field will be given the gzipped version straight; for those browsers that don't, we unzip the data on the fly and send them the plaintext.

"Vary: User-agent" ヘッダを渡して、データをレンダリングする相手を慎重に選ぶようプロキシキャッシュに伝えます。 (「Vary: Accept-encoding」のほうが適合性が高いのですが、それでマークしたページはInternet Explorerでキャッシュできません。)

警告 警告: 出力のバッファにより(ob_gzhandler または zlib.output_compression を経由し)コンテンツの gzip 処理を行う設定にしている場合は、$wgUseGzip を有効にしてはいけません。もし有効にすると、利用者への見た目がぎこちなくなってしまいます。

緊急時のフォールバック

ウィキからデータベース サーバーにつながらなくなった場合、要求されたどのページも「database is down」というメッセージを付けて、最新であってもなくてもキャッシュした版を表示しようとします。

ただし以下の限界があります:

  • 特別ページはこの方法では扱えないため、警告メッセージを表示するのみ
  • リダイレクト ページはキャッシュしないため、リダイレクトされたページへのリンクをクリックすると最終的なページに行き着かない
  • 題名にコロン (:) を含む場合 (それが有効な名前空間は例外として)、MediaWiki がその題名に有効なインターウィキ接頭辞があるかどうかデータベースを調べるため、読み込みに失敗する。そのページにインターウィキ接頭辞に対するインターウィキのキャッシュ項目がない場合 ($wgInterwikiExpiry を参照)、または $wgMainCacheType DB_CACHE にフォールバックした (または設定された) 場合のみ発生。
  • non-view 操作を使用しようと試みると、プレーンなページビューとなり混乱を招きやすい
  • MySQL 接続のタイムアウトに問題があると、特に永続的な接続を使用していてデータベースが後で終了する場合、処理中止までに容認できないほど長い時間がかかってしまいます。php.ini で mysql.connect_timeout を調整し (3 以上に設定) この問題に対処します。調整する php.ini は、クライアントではなくウェブサーバの php.ini です。
  • $wgDisableCounters true を設定していないと、データベースのクエリを実行しようとしてフォールバックが失敗する場合があります。
  • $wgStatsMethod cache に設定していて、$wgMainCacheType が DB_CACHE にフォールバックする (またはするように設定してある) 場合は、フォールバックに失敗する場合があります。

キャッシュされたページを直接提供する

MediaWikiは既定ではページのPHPをキャッシュに渡します。 ここではWebサーバの設定方法を利用し、MediaWikiやPHPをまったく呼び出すことなく、キャッシュされたファイルを直接処理する方法を示します。

最初に$wgFileCacheDepth = 0;を設定、続いてリライトの規則を追加します。詳細は次のとおり。

Apache

次のmod_rewriteルールは、Apache 2.2を実行している共有Webホストの.htaccessファイルで動作することが確認されています。

RewriteBase /
# If a cached page exists under /w/html_cache, do an internal redirect to it:
RewriteCond %{HTTP_COOKIE} !UserID=
RewriteCond %{QUERY_STRING} !.
RewriteCond %{DOCUMENT_ROOT}/w/html_cache/$1.html -s
RewriteRule ^wiki/(.+)$ /w/html_cache/$1.html [B,L,NS]

ただしこの書き換えルールは、題名に句読点や非ASCII文字が含まれたページでは正しく機能しません。 RewriteMapを使うきちんとした解決策はあるものの、.htaccessコンテキストではサポートされていません。 非ASCIIタイトルの処理の代替策として次のトリックを使用すると、URLをエスケープした題名を直接、生の要求行から取り出すことができます。

RewriteBase /
# If a cached page exists under /w/html_cache, do an internal redirect to it: 
RewriteCond %{HTTP_COOKIE} !UserID=
RewriteCond %{QUERY_STRING} !.
ReWriteCond %{THE_REQUEST} ^GET\x20/wiki/([^\x20/]+)\x20HTTP
RewriteCond %{DOCUMENT_ROOT}/w/html_cache/%1.html -s
RewriteRule ^wiki/(.+)$ /w/html_cache/%1.html [B,L,NS]

この方法でも題名にピリオドやスラッシュ(「.」「/」)他、ファイルキャッシュがエスケープできてもブラウザが回避しない句読点を含むと、処理できません(またはその逆も真)。 また適切なVaryヘッダーを渡すようにする必要があります:

Header append Vary Cookie

もう1点、このリダイレクトのトリックでは MediaWiki を完全に回避するため、$wgCacheEpoch を反映しません。 そこで必要に応じて、手動でキャッシュを再構成する場面が生じることがあります。

Nginx

設定言語がかなり限定される(例えばif文は入れ子にできない)nginxは、必ずngx_lua moduleと組んで使います。

前提条件を確認して下記の設定をサーバブロックに組み込んでください:

  • example.com/Page のような展開したURLを使用している。
  • キャッシュ フォルダーは (既定の) MediaWiki フォルダー内にある。
  • 既に最後のロケーション ブロック内で *.php ファイルを php-fpm (またはその他) にプロキシしている。

そして、以下の制限があります:

  • Apacheソリューションと同様に、cronジョブを実行するか、キャッシュファイルが変更されたときに手動で再構築する必要がある。
  • タイトルに非 ASCII 文字を含むと PHP を使用して提供 (どの場合も利用者には透過的)。

必要に応じてパスを変更してください。

 location ~ /cache/(.*) {
     internal;
 }
 
 location / {
     default_type 'text/html';
     rewrite_by_lua '
         local cookie = ngx.req.get_headers()["Cookie"] or ""
         if string.match(cookie, "UserID") then  -- if we are logged in...
             ngx.exec("@rewrite")
         else
             local page = string.sub(ngx.var.request_uri, 2, -1)  -- get the page name without the leading slash
             local filename = page .. ".html"
             local f = io.open("/var/www/w/cache/" .. filename, "r")
             if f ~= nil then  -- if the file exists, close it and serve it directly
                 io.close(f)
                 ngx.header["x-wiki-cache"] = "via nginx"  -- headers to help you debug
                 ngx.exec("/cache/" .. filename)
             else
                 ngx.header["x-wiki-cache"] = "via mediawiki"
                 ngx.exec("@rewrite")
             end
         end
     ';
 }
  
 location @rewrite {
     rewrite ^/([^?]*)(?:\?(.*))? /index.php?title=$1&$2 last;
 }

関連項目