Amazon Web Services ブログ

CloudFront Functions 用の低レイテンシーデータストア、Amazon CloudFront KeyValueStore の紹介

Amazon CloudFront は、静的コンテンツと動的コンテンツを、低レイテンシーかつ高速な転送速度でセキュアに配信することを可能にします。CloudFront Functions では、1 秒あたり何百万ものリクエストにレイテンシーの影響を受けやすいカスタマイゼーションを実行できます。例えば、CloudFront Functions は、ヘッダーの変更、キャッシュキーの正規化、URL の書き換え、またはリクエストの承認を実行するために使用できます。

11月21日は、CloudFront KeyValueStore を皆さんにご紹介します。CloudFront KeyValueStore は、CloudFront Functions 内からの読み取りアクセスを可能にするセキュアでグローバルな低レイテンシーキーバリューデータストアで、高度なカスタマイズ対応のロジックを CloudFront エッジロケーションで実行できるようにします。

これまで、設定データは関数コード内に埋め込む必要がありました。例えば、URL をリダイレクトするべきかどうか、およびビューワーをどの URL にリダイレクトするかを判断するためのデータです。設定データを関数コードに埋め込むと、設定を少し変更するだけでも、そのたびにコード変更を行って、関数コードを再デプロイする必要があります。新しいルックアップが追加されるたびにコードを更新してデプロイすることにより、コードを誤って変更するリスクが生じます。また、最大関数サイズは 10 KB であるため、多くのユースケースにおいて、すべてのデータをコード内に収めることが困難になります。

CloudFront KeyValueStore を使用することで、関数に関連付けられたデータと関数コードを、それぞれ単独に更新できるようになります。この機能は、関数コードを簡素化するとともに、コード変更をデプロイすることなくデータを簡単に更新できるようにします。

では、これが実際にどのように機能するのかを見てみましょう。

CloudFront キーバリューストアの作成
CloudFront コンソールのナビゲーションペインから [関数] を選択します。[KeyValueStores] タブで、[KeyValueStore を作成] を選択します。

ここには、Amazon Simple Storage Service (Amazon S3) バケット内の JSON ファイルからキーバリューペアをインポートするオプションがあります。キーがない状態で始めたいので、今はインポートしません。名前と説明を入力して、キーバリューストアの作成を完了します。

コンソールのスクリーンショット。

キーバリューストアが作成されたら、[キーバリューペア] セクションで [編集] を選択してから、[ペアを追加] を選択します。キーに hello、値に Hello World と入力して、変更を保存します。キーと値をさらに追加することもできますが、今は 1 つのキーで十分です。

コンソールのスクリーンショット。

キーバリューストアを更新すると、キーバリューストアに関連付けられている関数がそれを低レイテンシーで使用できるように、変更がすべての CloudFront エッジロケーションに数秒で伝播されます。その仕組みを見てみましょう。

CloudFront Functions からの CloudFront KeyValueStore の使用
CloudFront コンソールのナビゲーションペインから [関数] を選択し、次に [関数を作成] を選択します。関数の名前を入力してから、cloudfront-js-2.0 ランタイムを選択して、関数の作成を完了します。次に、キーバリューストアをこの関数に関連付けるための新しいオプションを使用します。

コンソールのスクリーンショット。

コンソールからキーバリューストア ID をコピーして、以下の関数コードで使用します。

import cf from 'cloudfront';

const kvsId = '<KEY_VALUE_STORE_ID>';

// This fails if the key value store is not associated with the function
const kvsHandle = cf.kvs(kvsId);

async function handler(event) {
    // Use the first part of the pathname as key, for example http(s)://domain/<key>/something/else
    const key = event.request.uri.split('/')[1]
    let value = "Not found" // Default value
    try {
        value = await kvsHandle.get(key);
    } catch (err) {
        console.log(`Kvs key lookup failed for ${key}: ${err}`);
    }
    var response = {
        statusCode: 200,
        statusDescription: 'OK',
        body: {
            encoding: 'text',
            data: `Key: ${key} Value: ${value}\n`
        }
    };
    return response;
}

この関数は、リクエストのパスの最初の部分をキーとして使用し、キーの名前とその値を使って応答します。

変更を保存して関数を発行します。関数の [発行] タブで、先ほど作成した CloudFront ディストリビューションに関数を関連付けます。[ビューワーリクエスト] イベントタイプと、[デフォルト (*)] キャッシュ動作を使用して、ディストリビューションに対するすべてのリクエストをインターセプトします。

コンソールにある関数のリストに戻り、関数がデプロイされるのを待ちます。次に、コマンドラインから curl を使用して、ディストリビューションからコンテンツをダウンロードし、関数の結果をテストします。

まず、関数を呼び出して、先ほど作成したキー (hello) をルックアップするパスをいくつか試してみます。

curl https://distribution-domain.cloudfront.net/hello
Key: hello Value: Hello World

curl https://distribution-domain.cloudfront.net/hello/world
Key: hello Value: Hello World

機能していますね! 次に、別のパスを試して、キーが見つからなかった場合に、コードで使用しているデフォルト値が返されることを確認します。

curl https://distribution-domain.cloudfront.net/hi
Key: hi Value: Not found

この最初の例が機能するのを確認したところで、次はもっと高度で便利な関数を試してみましょう。

CloudFront KeyValueStore 内の設定データを使用した URL の書き換え
CloudFront が実際のリクエストの実行で使用する必要があるカスタムパスをキーバリューストアでルックアップするために、HTTP リクエスト内の URL のコンテンツを使用する関数を作成してみましょう。この関数は、ウェブサイトの一部である複数のサービスを管理するために役立ちます。

例えば、私のウェブサイトに使用しているブログプラットフォームを更新したいとします。古いブログにはオリジンパス /blog-v1 があり、新しいブログにはオリジンパス /blog-v2 があります。

アーキテクチャ図。

最初は、まだ古いブログを使っています。CloudFormation コンソールで、 blog-v1 という値を持つキーバリューストアに blog キーを追加します。

次に、以下の関数を作成してから、ディストリビューションに対するすべてのリクエストをインターセプトするために [ビューワーリクエスト] イベントと [デフォルト (*)] キャッシュ動作を使用するディストリビューションにその関数を関連付けます。

import cf from 'cloudfront';

const kvsId = "<KEY_VALUE_STORE_ID>";

// This fails if the key value store is not associated with the function
const kvsHandle = cf.kvs(kvsId);

async function handler(event) {
    const request = event.request;
    // Use the first segment of the pathname as key
    // For example http(s)://domain/<key>/something/else
    const pathSegments = request.uri.split('/')
    const key = pathSegments[1]
    try {
        // Replace the first path of the pathname with the value of the key
        // For example http(s)://domain/<value>/something/else
        pathSegments[1] = await kvsHandle.get(key);
        const newUri = pathSegments.join('/');
        console.log(`${request.uri} -> ${newUri}`)
        request.uri = newUri;
    } catch (err) {
        // No change to the pathname if the key is not found
        console.log(`${request.uri} | ${err}`);
    }
    return request;
}

ここで、URL パスの先頭に blog と入力すると、リクエストが実際に blog-v1 パスに送られます。blog-v1 は古いブログで使用されるオリジンパスであるため、CloudFront は古いブログに対して HTTP リクエストを行います。

例えば、ブラウザに https://distribution-domain.cloudfront.net/blog/index.html と入力すると、古いブログ (V1) が表示されます。

ブログ V1 が表示されたブラウザのスクリーンショット。

コンソールで、blog-v2 という値で blog キーを更新します。数秒後に同じ URL にアクセスすると、今度は新しいブログ (V2) が表示されます。

ブログ V2 が表示されたブラウザのスクリーンショット。

ご覧のとおり、パブリック URL は同じですが、コンテンツが変更されています。より全般的に言うと、この関数は 2 つのブログバージョン間で URL が変更されないことを前提としています。

これで、私のウェブサイトの一部であるさまざまなサービスのキー (blog、support、help、commerce など) をさらに追加して、正しい URL パスを使用するための値を各キーに設定できるようになりました。そのうちの 1 つに新しいバージョンを追加するとき (新しいコマースプラットフォームに移行するなど) は、新しいオリジンを設定し、対応するキーを新しいオリジンパスを使用するように更新できます。

これは、コードから設定データを分離するときに得られる柔軟性の一例に過ぎません。すでに CloudFront Functions を使用している場合は、CloudFront KeyValueStore を使用してコードを簡素化できます。

知っておくべきこと
CloudFront KeyValueStore は、11月21日から世界中のすべてのエッジロケーションでご利用いただけます。CloudFront KeyValueStore では、パブリック API からの読み取り/書き込み操作と、CloudFront Functions 内からの読み取り操作に基づく使用量に対する料金のみを支払います。詳細については、「CloudFront の料金」を参照してください。

キーバリューストアは、AWS マネジメントコンソールAWS コマンドラインインターフェイス (AWS CLI)、および AWS SDK を使用して管理できます。AWS CloudFormation のサポートも近日提供される予定です。キーバリューストアの最大サイズは 5 MB で、各関数には単一のキーバリューストアを関連付けることができます。キーの最大サイズは 512 バイトです。値のサイズは最大 1 KB にすることができます。キーバリューストアを作成するときは、以下の JSON 構造を持つ Amazon S3 上のソースファイルを使用して、作成中にキーと値のデータをインポートできます。

{
  "data":[
    {
      "key":"key1",
      "value":"val1"
    },
    {
      "key":"key2",
      "value":"val2"
    }
  ]
}

作成時にキーと値のデータをインポートしておくと、新しい環境 (テストや開発など) のセットアップを自動化し、1 つの環境から別の環境 (本番前環境から本番環境など) に設定を簡単にレプリケートするために役立ちます。

CloudFront KeyValueStore を使用して、エッジにカスタムロジックを追加する方法を簡素化しましょう。

Danilo

原文はこちらです。