エックスサーバーのキャッシュを理解する

エックスサーバーには、Webサイトの表示速度・同時アクセス数を大幅に向上させることができる「キャッシュ機能」が用意されています。ですが、今まで中身を理解していなかったので利用していませんでした。知らないというだけで利用しないのはもったいないので、今回はエックスサーバーのキャッシュについて調べていきます。

環境
PHP
7.4

キャッシュ機能は3種類

ブラウザキャッシュについては、名称通り一般的なブラウザキャッシュ(クライアント側)であり、エックスサーバー固有のものではないので省略します。

キャッシュの組み合わせは5種類

サーバーの詳細は公開されていないので、あくまで推測であることをご留意ください。エックスサーバーで用いられているキャッシュ機能(サーバー側)は2種類で、ユーザーはそれを組み合わせて使用します。組み合わせは以下となります。

  1. 「サーバーキャッシュ オフ」 x 「Xアクセラレータ オフ
  2. 「サーバーキャッシュ オフ」 x 「Xアクセラレータ ver.1
  3. 「サーバーキャッシュ オフ」 x 「Xアクセラレータ ver.2
  4. 「サーバーキャッシュ オン」 x 「Xアクセラレータ ver.1
  5. 「サーバーキャッシュ オン」 x 「Xアクセラレータ ver.2

「サーバーキャッシュ」をオンにすると、強制的に「Xアクセラレータver.1」がオンになりますので、「サーバーキャッシュ オン」 x 「Xアクセラレータ オフ」の組み合わせはできません。

これだけ見ると複雑なようですが、実質的には……

  • Nginx リバースプロキシキャッシュ
  • PHP OPcache

の組み合わせと思われます。どれを選択するかで、「Nginxのキャッシュ対象」と「OPcache設定値」が変わります。詳細に入る前に、表にまとめます。

キャッシュ機能 Nginx キャッシュ対象 Opcache 設定値
オフ 無し
X Ver.1 静的ファイル(.htmlは除く)
X Ver.2 静的ファイル(.htmlは除く)
サーバー、 X ver.1 全ファイル
サーバー、 X ver.2 全ファイル

キャッシュ対象詳細は公式サイトに書かれています。

次にキャッシュの中身についてみていきます。

Xアクセラレータの中身を見る

Opcache

Xアクセラレータを「オフ、Ver.1、Ver.2」にして、phpinfo()で確認してみました。
まず、どの設定でもOpcache は有効化されていました。

Ver.2のみ、Used memoryFree memoryMax keysなどが高く設定されていました。また、Manual restartsvalidate_permissionvalidate_rootにも違いがありました。

「Xアクセラレータ Ver.2」の「PHPプログラムの高速化」とは「Opcache」の設定を高設定にしたものと思われます。ただ、OPcache設定の知識がないのでその違いを具体的には理解できてはいません。また、Opcache以外の違いを調べてはいません。

Nginx キャッシュ

Xアクセラレータのキャッシュ対象を公式サイトで見ると、画像やCSS、Webフォントなどの静的ファイルが対象にありますが、HTMLファイルは入っていません。

確かめるため、以下の内容のファイルをサーバーにおいてみました。

HTML

<html>
<head>
    <meta charset="utf-8">
</head>
<body>
    <p>1</p>
</body>
</html>

そして、数字の部分を別の数字に変更(HTML書き換え)し、アクセス(F5、Ctrl+F5)を繰り返してみたところ、変更は即時反映されました。やはり、Xアクセラレータのみの場合、HTMLファイルのキャッシュは効いていないようです。

サーバーキャッシュの中身を見る

次に、サーバーキャッシュを見ていきます。

HTML

サーバーキャッシュをオンにして先ほどと同じことをしてみました。結果、一度目のアクセス時のHTMLファイルがキャッシュされ、更新(F5)しても数字が変更されなくなりました。キャッシュ有効期限である1分を過ぎると更新が反映(キャッシュ破棄)され、次のファイルがキャッシュされました。スーパーリロード(Ctrl+F5)を行うと、キャッシュの有無に関係なく即時反映されました。

PHP

次にPHPでも試してみました。以下の内容のファイルを作りアクセスしてみます。

// 1から10000までの数字をランダムで1つ表示
echo rand(1, 10000);

結果、初回アクセス時に生成された数字(ファイル)がキャッシュされ、更新(F5)しても、1分間変化はありませんでした。こちらも、スーパーリロード(Ctrl+F5)を行うと、キャッシュの有無に関係なく即時反映されました。動的に生成したファイルもキャッシュされることが確認できました。

サーバーキャッシュ有無をコントロールする

さて、非常に強力なサーバーキャッシュ機能ですが、動的に生成したファイルもキャッシュされるとなると、注意書きにあるように意図しない内容が表示されてしまう恐れがあります。例えば、WordPressのログイン画面など、本来はログインユーザーのみに表示される内容がキャッシュされることで、非ログインユーザーにも見えてしまう可能性などです。

無効化

公式サイトには、レスポンスヘッダが以下の条件を満たす場合にはキャッシュが生成されないとあります。

  • Cache-Controlに「no-cache」「no-store」「private」「must-validate」のいずれかを含む場合
  • Set-Cookieを含む場合

試しに、WordPressのソースを見てみますと

function wp_get_nocache_headers() {
    $headers = array(
        'Expires'       => 'Wed, 11 Jan 1984 05:00:00 GMT',
        'Cache-Control' => 'no-cache, must-revalidate, max-age=0',
    );

    ........
}

public function send_headers() {
    $headers       = array();
    $status        = null;
    $exit_required = false;

    if ( is_user_logged_in() ) {
        $headers = array_merge( $headers, wp_get_nocache_headers() );
    }

    ........
}

とあり、アクセスしたユーザーがログインしている場合、サーバーにキャッシュをしないよう指示を出しているが分かります。このことによって、サーバーキャッシュ機能を有効にしていても、意図しない表示を防ぐことが可能となっています。

自分で設定する場合

HTML

先ほどのHTMLと同ディレクトリに.htaccessを作成しました。

<Files index.html>
    Header set Cache-Control "no-cache"
</Files>

# 複数ファイル
# <Files ~ "^(index|file_name)\.html$">
#     Header set Cache-Control "no-cache"
# </Files>

更新(F5)でアクセス毎に数値が変わり、キャッシュが生成されていないことが確認できました。

php

先ほどのPHPに修正を加えてみました。

+    header('Cache-Control: no-cache');

     // 1から10000までの数字をランダムで1つ表示
     echo rand(1, 10000);

更新(F5)でアクセス毎に数値が変わり、キャッシュが生成されていないことが確認できました。

おわりに

ざっくりとですが、エックスサーバーのキャッシュについての理解はできたように思います。今後は「サーバーキャッシュ」「XアクセラレータVer.2」を常時オンにしていこうと思います。