0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AkamaiのEdgeWorkers/EdgeKVで動的にキャッシュのオン/オフを切り替えてみる

Posted at

はじめに

通常時はCDNのWebキャッシュ設定がno-storeであるコンテンツに対して、必要な時だけ動的にキャッシュ設定をオンにする方法を考えます。
前提として、情報の更新頻度が高いため普段はキャッシュさせたくないが、ユーザーアクセスのピークが発生してオリジンサーバーのリソースが逼迫した時など、一定の条件を満たす場合だけ一時的にキャッシュを有効化し、ピークがおさまればすぐにキャッシュ設定をオフにすることも可能とします。
ユースケースとしてたとえば、スポーツ中継の得点表示やゲームアプリのスコアボード、ニュースサイトを想定してみます。これらのコンテンツはユーザーに対して最新情報を提供するためキャッシュ設定をno-storeとするケースが多いが、イベントやキャンペーン等による大量アクセスの発生により高負荷状態になったオリジンサーバーが応答ができなくなると、そもそもユーザーにコンテンツを提供できなくなる状況に陥ってしまうことが考えられます。対策として、ピークが発生しているコンテンツに対して短いキャッシュTTLで一時的にキャッシュをオンにすることで、オリジンを保護しながら、なるべく新鮮な情報をユーザーに届けることができるようになります。

EdgeWorkers/EdgeKVとは

Akamaiのエッジサーバー上で独自に開発したJavaScriptのプログラムコードを実行できるサービスがEdgeWorkers、EdgeWorkersと組み合わせて使用可能なKey-Value型のデータベースがEdgeKVです。

参考:EdgeWorkers:Akamaiのエッジサーバー上でJavascriptで書いたコードが実行可能に

成果物のイメージ

通常はキャッシュ設定がno-storeとなっている2つのサービスが存在し、それぞれ共通のオリジンサーバーを共有しているものとします。基本的にこれらのサービスは情報の更新頻度が高いためno-storeとしていますが、いずれかのサービス(例:サービス1)においてピークが発生しオリジンへの負荷がかかることで、他サービス(例:サービス2)への影響が発生しうるような環境を想定しています。

  • サービス1 - リクエストパスは /qiita-test/service1/* とする
  • サービス2 - リクエストパスは /qiita-test/service2/* とする

今回はゴールとして、サービス1でピークが発生した時を想定し、オリジンサーバーを保護するためにサービス1向けのリクエストだけキャッシュ設定をオン(30秒TTL)にすることを目指します。

配信アーキテクチャ

配信のしくみは、以下のとおりです。

① クライアントからエッジに着信したリクエストが、配信設定によりno-storeとして扱われる
② EdgeWorkersのonClientRequestで処理に入る。リクエストパスの2階層目の値(service1 or service2)を抽出し、どのサービスへのリクエストかを判断する
③ 上記②で抽出したリクエスト先のサービスがキャッシュされるべきかどうかEdgeKVの値をチェックする ※
④ EdgeKVが0か1をEdgeWorkersに返す (0はキャッシュなし、1はキャッシュありとする)
⑤ 0であればEdgeWorkersで追加処理はせずに配信設定に戻してリクエストをオリジンへフォワードする。1であればCaching_Flag(Variable)に1を立て、配信設定側でCaching_Flag=1を条件にキャッシュ(30秒TTL)をオンにする

※ 下図の青い矢印のように、オリジンサーバー側で(例えばサーバー負荷に応じて)EdgeKVのValueの値を書き換えることで、サービス単位でキャッシュのオン/オフを行うことを前提とする

image.png

配信設定

親ルールの設定は以下の通りです。
image.png
子ルールの設定は以下の通りです。
image.png

EdgeKVのデータ

EdgeKVのnamespace名"demo"の中に、グループ名"services"を定義します。"servcies"配下に各サービスをItemとして定義し、それぞれキャッシュをするかしないか判断するためのValueを埋め込んでおきます。

  • Value = 0: キャッシュなし(デフォルト)
  • Value = 1: キャッシュあり

以下の出力例はEdgeKV向けのAkamai CLIを利用したものです。

サービス一覧の表示
% akamai edgekv list items production demo services
----------------------------------------------------------------
--- 2 items from group services were retrieved successfully. ---
----------------------------------------------------------------
service1
service2
各サービスのValueの表示
% akamai edgekv read item production demo services service1
---------------------------------------------------------------------------------------------------------------
--- Item service1 from group services, namespace demo and environment production retrieved successfully. ---
---------------------------------------------------------------------------------------------------------------
0
% akamai edgekv read item production demo services service2
---------------------------------------------------------------------------------------------------------------
--- Item service2 from group services, namespace demo and environment production retrieved successfully. ---
---------------------------------------------------------------------------------------------------------------
0

EdgeWorkersのコード

リクエストパスの2階層目の値(service1 or service2)から対象サービスを抽出し、そのサービスに対するキャッシュの必要有無をEdgeKVへチェックしにいき、キャッシュが必要であればCaching Flagを1に変更するためのJavaScriptコードを実装しました。(こちらのGithubからサンプルをダウンロード可能)

import { EdgeKV } from './edgekv.js';

export async function onClientRequest(request) {
        var default_cachingFlag = 0;
        var cachingFlagFromEdgeKv = 0;
        var servicePath = request.path.split('/')[2];

        const edgeKv = new EdgeKV({namespace: "demo", group: "services"});

        try {
        cachingFlagFromEdgeKv = await edgeKv.getText({ item: servicePath, default_value: default_cachingFlag });
        } catch (error) {
            }

        if (cachingFlagFromEdgeKv == 1){
                request.setVariable('PMUSER_CACHING_FLG',1);
                }else{
                }
}

動作確認

通常時、サービス1およびサービス2はno-storeでありキャッシュヒットはしません。以下はサービス1にリクエストを送ったときのログです。

キャッシュヒットなし
% curl -i -H "Pragma:akamai-x-cache-on"  https://www.example.com/qiita-test/service1/sample.json
HTTP/1.1 200 OK
<SNIP>
X-Cache: TCP_MISS from a23-195-88-204.deploy.akamaitechnologies.com 
<SNIP>

サービス1でピークが発生し、オリジンサーバーのリソースが逼迫した場合に、サービス1だけキャッシュをオンになるよう、EdgeKVのサービス1向けのValueを1に変更します。

EdgeKVのサービス1向けのValueを1に変更
% akamai edgekv write text production demo services service1 1
-------------------------------------------------------------------------------------------------------------------------
--- Item service1 was successfully created into the environment: production, namespace: msuzuki and groupid: services ---
-------------------------------------------------------------------------------------------------------------------------

この状態でサービス1にリクエストが送られるとキャッシュが有効化されています。つまりオリジンサーバーのワークロードを保護できている状態です。
※最初はキャッシュが無いため、2回目以降のリクエストからキャッシュから返される

キャッシュヒットあり
% curl -i -H "Pragma:akamai-x-cache-on"  https://www.example.com/qiita-test/service1/sample.json
HTTP/1.1 200 OK
<SNIP>
X-Cache: TCP_MEM_HIT from a23-195-88-204.deploy.akamaitechnologies.com 
<SNIP>

さいごに

今回ご紹介したユースケースは、CDNプラットフォームならではのEdgeComputingの使い方です。簡単なので、ぜひいろいろな応用例を考えてみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?