OpenResty Edge はゲートウェイ(Edge Node)で HTTP レスポンスをキャッシュするため、キャッシュにヒットしたリクエストはバックエンドに到達せず、オリジンの負荷とレスポンス遅延を削減できます。ページルールでプロキシキャッシュのスイッチを入れ、キャッシュキーを設定し、各ゲートウェイノードにリリースするだけで、Nginx の設定変更もリロードも不要です。本記事ではその全手順を示し、curlCache-Status: HITMISS を一つずつ確認したうえで、オリジンが Cache-Control ヘッダーを返さない場合でもキャッシュを強制する方法を解説します。

キャッシュミス時、Edge ノードはリクエストをバックエンドサーバーに転送する

クライアントのリクエストが Edge Node サーバー上のキャッシュにヒットした場合、バックエンドサーバーへのリクエストは不要となります。これにより、レスポンス遅延を削減し、ネットワーク帯域幅を節約することができます。これは、OpenResty Edge によるプライベート CDN 構築の中核となる仕組みでもあります。

キャッシュヒット時、Edge ノードはバックエンドに問い合わせずレスポンスを返す

ページルールでのプロキシキャッシュの有効化とキャッシュキーの設定

OpenResty Edge の Admin Web コンソールにアクセスしましょう。これはコンソールのサンプルデプロイメントです。各ユーザーには独自のローカルデプロイメントがあります。

前回のアプリケーション例 test-edge.com を引き続き使用します。

OpenResty Edge Admin Web コンソールのトップページ

すでにアップストリームを定義しています。

バックエンドアップストリームが定義済みのアップストリーム一覧

この my_backend アップストリームには 1 つのバックエンドサーバーがあります。

バックエンドサーバーが 1 台の my_backend アップストリーム

バックエンドサーバーの IP アドレスが 191 で終わっていることに注目してください。後ほどこの IP アドレスを使用します。

191 で終わるバックエンドサーバーの IP アドレス

また、ページルールも定義済みです。

ルールが定義済みのページルール一覧

このページルールは、このアップストリームを指すリバースプロキシを設定しています。

アップストリームへのリバースプロキシとして設定されたページルール

明らかに、このページルールではまだプロキシキャッシュを有効にしていません。

では、このページルールを編集して、ゲートウェイにレスポンスキャッシュを追加しましょう。

プロキシキャッシュを追加するためのページルール編集画面

プロキシキャッシュを有効にします。

ページルールでプロキシキャッシュのスイッチを有効化

ここでキャッシュキーを設定できます。

プロキシキャッシュのキャッシュキー設定画面

デフォルトでは、キャッシュキーは URI とクエリ文字列(URI パラメータ)の 2 つの部分で構成されています。

他の種類のキーコンポーネントを選択することもできます。

追加のキャッシュキーコンポーネントの選択

選択可能なキャッシュキーコンポーネントの種類一覧

または、クエリ文字列全体をキーから削除することもできます。

クエリ文字列をキャッシュキーから削除

さらにキーコンポーネントを追加することもできます。

キャッシュキーへのコンポーネント追加

この例では、デフォルトのキャッシュキー定義のみを保持します。

このページルールを保存します。

プロキシキャッシュを有効化したページルールの保存

新しい設定をリリースしましょう。

保留中の変更に対する新しいリリースの作成

先ほどの変更をプッシュします。

プッシュ前に保留中の変更を確認

リリースします!

リリースを確定して変更を反映

新しいバージョンの設定が、すべてのゲートウェイサーバーに同期されました。

新しいリリースが全ゲートウェイサーバーに同期された状態

設定の変更には、サーバーのリロード、再起動、またはサーバープロセスのバイナリアップグレードは必要ありません。そのため、非常に効率的です。

リロードなしで設定変更がゲートウェイノードへ配信される様子

curl によるキャッシュのテストと Cache-Status HIT/MISS の確認

ゲートウェイサーバーのキャッシュをテストしてみましょう。

OpenResty Edge コンソールのゲートウェイサーバー一覧

このサンフランシスコのゲートウェイサーバーの IP アドレスをコピーします。

サンフランシスコのゲートウェイサーバーの IP アドレスをコピー

この IP アドレスの最後の数字が 133 であることに注意してください。

ターミナルで、curl コマンドラインツールを使用してこのゲートウェイサーバーに HTTP リクエストを送信します。

curl -I -H 'Host: test-edge.com' http://138.68.231.133/

返された Cache-Status: MISS レスポンスヘッダーに注目してください。

curl レスポンスに返された Cache-Status: MISS ヘッダー

もう一度試してみます。

curl -I -H 'Host: test-edge.com' http://138.68.231.133/

まだ Cache-Status: MISS ヘッダーが返ってきます。これは、キャッシュがまったく使用されていないことを意味します。なぜでしょうか?実は、バックエンドサーバーの元のレスポンスヘッダーに ExpiresCache-Control などのヘッダーが欠けているためです。

2 回目のリクエストでも Cache-Status: MISS が返る

バックエンドサーバーにログインしてみましょう。

ssh ec2-user@54.213.103.191

バックエンドサーバーの IP アドレスが 191 で終わっています。

IP が 191 で終わるバックエンドサーバーへのログイン

このバックエンドサーバーはオープンソースの OpenResty ソフトウェアを実行しています。

ps aux | grep nginx

オープンソース OpenResty の nginx プロセスが動くバックエンド

バックエンドサーバーは、HTTP プロトコルを使用する他のソフトウェアを実行することもできます。

HTTP を話すソフトウェアなら何でも Edge バックエンドになれる

このバックエンドサーバーに直接テストリクエストを送信できます。

curl -I -H 'Host: test-edge.com' http://127.0.0.1/

ローカルホストにアクセスしていることに注意してください。

curl でローカルホストのバックエンドへ直接リクエスト送信

確かに、ExpiresCache-Control のレスポンスヘッダーは提供されていません。

Expires も Cache-Control も返さないバックエンドのレスポンス

では、バックエンドサーバーを再設定しましょう。

cd /usr/local/openresty/nginx/

nginx 設定ファイルを開きます。

sudo vim conf/nginx.conf

ルートの location / を見つけます。

nginx 設定ファイル内のルート location ブロックを探す

1 時間の有効期限を追加します。

expires 1h;

バックエンドサーバーは、異なる location に対して異なる有効期限を定義したり、特定のレスポンスに対してキャッシュを完全に無効にしたりすることができます。

バックエンドの location ブロックに expires 1h を追加

ファイルを保存して終了します。

nginx 設定ファイルが正しいかテストします。

sudo ./sbin/nginx -t

問題ありません。

nginx -t で nginx 設定ファイルをテスト

バックエンドサーバープロセスをリロードします。

sudo kill -HUP `cat logs/nginx.pid`

HUP シグナルでバックエンド nginx サーバーをリロード

オープンソースの Nginx サーバーの場合も、設定方法は同じです。

バックエンドサーバーをテストしてみましょう。

curl -I -H 'Host: test-edge.com' http://127.0.0.1/

今度は ExpiresCache-Control の両方のヘッダーがレスポンスに含まれています。

バックエンドが Expires と Cache-Control ヘッダーを返すようになった状態

ゲートウェイサーバーにリクエストを送信してみましょう。

curl -I -H 'Host: test-edge.com' http://138.68.231.133/

まだ Cache-Status: MISS ヘッダーが表示されています。

ゲートウェイへの最初のリクエストが Cache-Status: MISS を返す

これは予想されたキャッシュミスです。最初のリクエストだからです。

最初のリクエストがキャッシュミスしてバックエンドに届く図

もう一度リクエストを送信してみます。

curl -I -H 'Host: test-edge.com' http://138.68.231.133/

素晴らしい!ついに Cache-Status: HIT ヘッダーが表示されました!

ゲートウェイへの 2 回目のリクエストが Cache-Status: HIT を返す

ようやく期待通りにキャッシュにヒットしました。

2 回目のリクエストがバックエンドに届かずキャッシュから返る図

クエリ文字列を追加してみましょう。

curl -I -H 'Host: test-edge.com' 'http://138.68.231.133/?a=3'

a=3 の部分に注目してください。

a=3 クエリ文字列付きのリクエストがキャッシュミスを返す

すると、再びキャッシュミスが発生します。

これは、デフォルトのキャッシュキーにクエリ文字列が含まれているためです。

クエリ文字列がデフォルトのキャッシュキーに含まれミスの原因になる

同じリクエストを再度実行すると、キャッシュにヒットするはずです。

curl -I -H 'Host: test-edge.com' 'http://138.68.231.133/?a=3'

確かにキャッシュにヒットしました。このクエリ文字列を気にしない場合は、キャッシュキーから削除することができます。

クエリ文字列付きリクエストの再送でキャッシュヒットが返る

Cache-Control ヘッダーなしでのキャッシュ強制

時には、バックエンドサーバーの設定を変更するのが面倒な場合があります。 そのような場合、オリジンレスポンスにキャッシュ制御ヘッダーが存在しない場合でも、デフォルトでレスポンスを強制的にキャッシュすることができます。

この機能を実現するために、元のページルールを修正することができます。

デフォルトの強制キャッシュを有効にします。

ページルールでデフォルトの強制キャッシュを有効化

キャッシュ可能なレスポンスステータスコードのデフォルトの有効期限も設定できます。

キャッシュ可能なレスポンスステータスコードのデフォルト有効期限の設定

この機能については、別の動画でデモンストレーションを行います。レスポンスがキャッシュされた後、オリジンのコンテンツが変わったときにはHTTP キャッシュをリアルタイムでパージすることもできます。

よくある質問

プロキシキャッシュを有効化しても OpenResty Edge が Cache-Status: MISS を返すのはなぜですか?

プロキシキャッシュを有効化しても Cache-Status: MISS が返る場合、通常はオリジンのレスポンス自体がキャッシュ不可であることを意味します。本デモではバックエンドが ExpiresCache-Control ヘッダーを返さないため、ゲートウェイはキャッシュしません。バックエンドの location に expires 1h; を追加するとオリジンがこれらのヘッダーを返すようになり、以降は 2 回目のリクエストで Cache-Status: HIT が返ります。

バックエンドが Cache-Control ヘッダーを返さない場合、どうやってキャッシュしますか?

ページルールを編集して強制キャッシュを有効にすると、オリジンがキャッシュ制御ヘッダーを返さない場合でもゲートウェイがレスポンスをキャッシュします。続いてキャッシュ可能なレスポンスステータスコードにデフォルトの有効期限を設定します。これにより、バックエンドサーバーの設定を一切変更せずにエッジでキャッシュできます。

クエリ文字列を追加するとキャッシュミスになるのはなぜですか?

デフォルトのキャッシュキーは URI とクエリ文字列で構成されるため、?a=3 を付けたリクエストは付けないものとは別のキーになり、初回はキャッシュミスになります。同じクエリ文字列付きリクエストを再送すればヒットします。クエリ文字列がレスポンス内容に影響しない場合は、キャッシュキーから削除してすべてのバリエーションで 1 つのキャッシュを共有させることができます。

OpenResty Edge のキャッシュ設定の変更に Nginx のリロードや再起動は必要ですか?

不要です。プロキシキャッシュを有効化して変更をリリースすると、設定は各ゲートウェイサーバーに同期され、サーバーのリロード・再起動・バイナリアップグレードは一切不要で、新しいキャッシュ動作がダウンタイムなく即座に反映されます。

OpenResty Edge について

OpenResty Edge は、マイクロサービスと分散トラフィックアーキテクチャ向けに設計された多機能ゲートウェイソフトウェアで、当社が独自に開発しました。トラフィック管理、プライベート CDN 構築、API ゲートウェイ、セキュリティ保護などの機能を統合し、現代のアプリケーションの構築、管理、保護を容易にします。OpenResty Edge は業界をリードする性能と拡張性を持ち、高同時接続・高負荷シナリオの厳しい要求を満たすことができます。K8s などのコンテナアプリケーショントラフィックのスケジューリングをサポートし、大量のドメイン名を管理できるため、大規模ウェブサイトや複雑なアプリケーションのニーズを容易に満たすことができます。

著者について

章亦春(Zhang Yichun)は、オープンソースの OpenResty® プロジェクトの創始者であり、OpenResty Inc. の CEO および創業者です。

章亦春(GitHub ID: agentzh)は中国江蘇省生まれで、現在は米国ベイエリアに在住しております。彼は中国における初期のオープンソース技術と文化の提唱者およびリーダーの一人であり、Cloudflare、Yahoo!、Alibaba など、国際的に有名なハイテク企業に勤務した経験があります。「エッジコンピューティング」、「動的トレーシング」、「機械プログラミング」 の先駆者であり、22 年以上のプログラミング経験と 16 年以上のオープンソース経験を持っております。世界中で 4000 万以上のドメイン名を持つユーザーを抱えるオープンソースプロジェクトのリーダーとして、彼は OpenResty® オープンソースプロジェクトをベースに、米国シリコンバレーの中心部にハイテク企業 OpenResty Inc. を設立いたしました。同社の主力製品である OpenResty XRay動的トレーシング技術を利用した非侵襲的な障害分析および排除ツール)と OpenResty Edge(マイクロサービスおよび分散トラフィックに最適化された多機能ゲートウェイソフトウェア)は、世界中の多くの上場企業および大企業から高い評価を得ております。OpenResty 以外にも、章亦春は Linux カーネル、Nginx、LuaJITGDBSystemTapLLVM、Perl など、複数のオープンソースプロジェクトに累計 100 万行以上のコードを寄与し、60 以上のオープンソースソフトウェアライブラリを執筆しております。

翻訳

英文版の原文と日本語訳版(本文)をご用意しております。読者の皆様による他の言語への翻訳版も歓迎いたします。全文翻訳で省略がなければ、採用を検討させていただきます。心より感謝申し上げます!