background
運用
開発

Varnishを利用したWEBサイト高速化について(3)

2018/11/01公開
運用カテゴリ

前回Varnishの活用例をご紹介しましたので、最後にVarnish、eZ Publishを使った事例のご紹介をさせて頂きます。

今回ご説明するにあたり、重要な要素はESIを利用したキャッシュハンドリングです。

varnish

予備知識

backend

eZ Systems社が開発・提供するPHPベースのオープンソースCMS。

Webブラウザからの要求に対して要求毎にページを生成して応答する動的なCMSに分類されます。

このeZ Publishはバージョン5.0よりPHPのフレームワークであるSymfony2で構築が可能となったため、Varnishとの親和性が高くなりました。

Symfony2とは

PHPのフレームワーク。

ESIに対応しており、リバースプロキシの機能を有しておりいるため、Varnishへのシームレスなアップグレードが可能になりました。

ESIとは

Edge Side Includesの略で、XMLベースのマークアップ言語です。

VarnishとESIを利用することで、Webページ単位ではなく、Webページを構成するパーツ単位でのキャッシュも可能となります。Webページのパーツ(ブロック)をキャッシュする、キャッシュしないに区別することができ、区別された情報をリバースプロキシにて1つのWebページとして動的に組み立ててWebブラウザからの要求に対して応答することができます。

VarnishとESIの関わり方

前回までのおさらいですが、VarnishはHTTPで得られたページをキャッシュします。

ESIを利用することでパーツ単位でキャッシュの要否やTTL(キャッシュ更新間隔)の設定を変えることができます。

認証情報はキャッシュできないため、キャッシュ対象外のパーツとして分け、各パーツ毎にキャッシュ時間を変えることで、バックエンドサーバへの負荷を軽減させることができます。

メモリ上にキャッシュされたESIブロックをIncludeしてWebページを組み立てるのはリバースプロキシとして利用してるVarnishの役割です。

イメージとしては各パーツがそれぞれURLを持っており、ユーザがサイトを閲覧すると、サーバ側では複数のリクエストが発生します。

各パーツ毎にVarnishがキャッシュで返すか、バックエンドに取りに行くか判定し、各パーツが揃ったらVarnishが組み立てユーザに返します。

VarnishとESIの関わり方

弊社事例としては、認種情報を持つパーツを最小限に集約し、キャッシュしないパーツとして生成しました。

ランキングなどを表示する右カラム(ASPサービスなどからPV情報を取って表示する箇所)はキャッシュ時間を短めにするなどして、パーツ毎に制御しています。

もちろんトップページで利用しているパーツを別のページで使いまわせるため、同じパーツへのリクエストはキャッシュが効いている間はバックエンドサーバにリクエストは発生しません。

結果として、DBへのアクセス頻度を抑えられると共に、DBから抽出するデータ量も全体として抑えることが出来ます。

速報など注目されるコンテンツへアクセスが集中してもほとんどのユーザは高速で提供されます。

各ユーザ毎にユニークな内容はキャッシュすることが出来ませんが、毎回同じ内容、更新頻度も少ないパーツは積極的にキャッシュします。

キャッシュの更新方法

バックエンドサーバに導入するeZ Publishは、ESIの機構を備えており、コンテンツを更新する際にこれらのESIに対してPurgeのリクエストを行うことで反映することができます。

Varnish側

Purgeリクエストを受けるバックエンドサーバを指定します。eZ Publishでコンテンツを更新した際に発生するPurgeリクエストをVarnishに認識させることで、ESIを含め指定したページやパーツのキャッシュをクリアします。

  • VCL(Varnish Configuration Language)
      
      acl purgers {
         .host = "XXX.YYY.ZZZ.CCC";
      }
      

eZ Publish側

eZ Publish側はVarnishが導入されたキャッシュサーバを指定します。

      
      ezpublish:
      ????http_cache:
      ????????# Use multiple_http method for purging content
      ????????purge_type: multiple_http
      ?
      ????system:
      ????????# Assuming that my_siteaccess_group your frontend AND backend siteaccesses
      ????????my_siteaccess_group:
      ????????????http_cache:
      ????????????????# Fill in your Varnish server(s) address(es).
      ????????????????purge_servers: [http://my.varnish.server:6081]
      

参考:https://doc.ez.no/display/EZP/Using+Varnish+with+eZ+Publish+5.2-5.3

ではどのようにコンテンツとESIを含め指定したページやパーツを紐づけているのでしょうか。

答えは各ページやパーツのHTMLのレスポンスヘッダにマークアップ用のIDを紐づけることです。

Symfony2でページを生成する際に、レスポンスヘッダーに以下の通り設定します。

      
      setSharedMaxAge('10');
              $response->setPublic();
              $response->headers->set( 'X-Location-Id', '111' );
      

'X-Location-Id'の値が極めて重要で、今回のケースではeZ Publishがコンテンツ管理する際に持つ各コンテンツの番地(ノードID)を指定します。

eZ Publishにてコンテンツを更新した場合に、Purgeの情報としてノードIDがVarnishに連携され、同じノードIDを持つキャッシュクリアします。

最後に

駆け足となりましたが、VarnishとeZ Publishを利用したWEBサイト高速化のお話は以上です。

今回はeZ Publishで触れさせて頂きましたが、他の動的CMSであるDrupalもSymfony2で構成されているため、Varnishとの連携が可能と想定されます。

また、昨今サイトのグローバル化も活発となり、CDNを利用したサイト構成も目立ちます。

Varnishは単一ロケーションで威力を発揮しますが、世界中からアクセスがあるようなサイトだとロケーションによるレイテンシーが発生してしまいます。

そこで、CDNとしてのメリットと、Varnishのメリットを兼ね備えて構築されたCDNとしてFastlyがあります。

徐々に注目されているため、今後のVarnishを利用したサイト構築に期待したいです。

※CDNとは、コンテンツデリバリネットワーク(Content Delivery Network)の略で、世界中に張り巡らされたCDN専用の配信ネットワークを利用して、Webサイトにアクセスしようとするエンドユーザに最も近いPoP(配信拠点)から効率的かつ高速にWebを配信する仕組み。