Open main menu

Manual:File cache

This page is a translated version of the page Manual:File cache and the translation is 55% complete.

Outdated translations are marked like this.
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とキャッシュ日付を照合するテンプレートを採用するページを確認します。

This should be done on article creation, edit saves, renames, and creation and deletion of linked articles (in order to update edit links). Invalidation operations that occur when editing templates, for example, check pages that use template to compare the cache date against page_touched.

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

  • ブラウザの〈再読み込み〉あるいは〈リフレッシュ〉(更新せずに同じページをリロードする)
  • Extension:DynamicPageListなど拡張機能からの出力変数は、該当するページのファイルキャッシュを無効化、古いデータを回避します。そうしないと、ブラウザの更新時に古いデータが返されます。

Those that don't will return stale data even on browser refresh.

  • 特定の長いエラーメッセージは、あたかも有効なページコンテンツであるかのように無期限にキャッシュされてしまうかもしれません。保存されたファイルキャッシュからこれらを削除するのは?action=purgeに限定されます。最小出力サイズのしきい値を使用し、致命的なPHPエラー等、ほとんどのエラーをキャッシュしないようにしています。

A minimum output size threshold is used to avoid caching most errors, like fatal PHP errors.

関連項目: Manual:$wgInvalidateCacheOnLocalSettingsChange

有効期限

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

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

There is no provision to set an expiry time, so all HTML for all pages is cached forever. An explicit ?action=purge command (or an edit to the page) will regenerate that one page, but neither the MediaWiki internal no-cache flags nor the browser refresh will remove outdated extension output once it has been stored as part of a file-cached page.

更新タブ

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

圧縮

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

$wgUseGzip = true;

匿名ユーザーが投稿をしなくても、キャッシュのパージ機能を利用できるように割り当てるには、この拡張機能を起動した直後に「LocalSettings.php」ファイルに以下のコードを追加してください:

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でキャッシュできません。)

("Vary: Accept-encoding" would be more appropriate, but Internet Explorer refuses to cache pages so marked.)

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

緊急時のフォールバック

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

ただし限界があります。

  • 特別ページはこの方法では扱えないため、警告メッセージを表示するのみ
  • リダイレクトしたページはキャッシュしないため、リダイレクトされたページへのリンクをクリックすると最終的なページに行き着かない
  • 題名にコロン(:)を含む場合(それが有効な名前空間は例外として)、MediaWikiがその題名に有効なウィキ間の接頭辞があるかどうかデータベースを調べるため、読み込みに失敗する。そのページにウィキ間の接頭辞に対するウィキ間のキャッシュがない場合($InterwikiExpiryを参照)、あるいは$MainCacheTypeがDB_CACHEにフォールバックした(あるいは設定された)場合のみ発生。
  • non-view操作を使用しようと試みると、プレーンなページビューとなり混乱を招きやすい
  • MySQL接続のタイムアウトに問題があると、特に永続的な接続を使用していてデータベースが後で終了する場合、処理中止までに容認できないほど長い時間がかかってしまいます。php.iniでmysql.connect_timeoutを調整し(3以上に設定)この問題に対処します。調整するphp.iniは、クライアントではなくウェブサーバのphp.iniです。
  • $DisableCountersを「真」に設定していないと、データベースノクエリを実行しようとしてフォールバックが成立しません。
  • $StatsMethodが「キャッシュ」に設定され、$MainCacheTypeがDB_CACHEにフォールバックする(もしくはするように設定してある)と、フォールバックに失敗します。
  • special pages are not covered in any way, there's just a warning message
  • redirect pages are not cached, so clicking a link to a redirect doesn't go through to the final destination
  • pages with colons in the title (other than for a valid namespace) may still fail due to MediaWiki checking the DB to see if the title has a valid interwiki prefix. This occurs only if there is no interwiki cache entry for the page's prefix (see $wgInterwikiExpiry ) or $wgMainCacheType is falling back (or set to) DB_CACHE.
  • attempts to use non-view actions result in a plain page view, which may be confusing
  • there may be issues with the MySQL connection timeout which make it take prohibitively long before giving up, particularly if using persistent connections and the db dies later. Adjust mysql.connect_timeout (set to 3 or more) in php.ini to deal with this. Edit the webserver's php.ini not the cli php.ini.
  • fallback may fail if $wgDisableCounters is not true due to attempting a DB query
  • fallback may fail if $wgStatsMethod is set to cache and $wgMainCacheType is falling back (or set to) 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をエスケープした題名を直接、生の要求行から取り出すことができます。

A tidy solution would be to use a RewriteMap, but this is not supported in .htaccess context. Instead, the following trick can be used to handle non-ASCII titles by pulling the URL-escaped title directly from the raw request line:

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ヘッダーを渡すようにする必要があります。

One should also ensure that the appropriate Vary header gets sent:

Header append Vary Cookie

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

You may need to clear or rebuild the cache manually as needed instead.

Nginx

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

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

  • example.com/Pageのような展開したURLを使用している。
  • キャッシュフォルダは(既定の)MediaWikiフォルダ内にある。
  • すでに最後のロケーションブロック内で* .phpファイルをphp-fpm(またはその他)に代入している。
  • you're using fancy urls like example.com/Page;
  • your cache folder is inside your MediaWiki folder (default);
  • you're already proxying *.php files to php-fpm (or whatever) in the last location block.

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

  • Apacheソリューションと同様に、cronジョブを実行するか、キャッシュファイルが変更されたときに手動で再構築する必要がある。
  • タイトルに非ASCII文字を含むとPHPを使用して提供(どの場合もユーザーには透過的)。
  • as with the Apache solution, you have to run a cron job or manually rebuild the cache files when they change;
  • pages whose title include non-ASCII characters are served through PHP (which should be transparent to the user anyway).

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

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

関連項目