We’re sorry we missed you at re:Invent, but we can still meet!

おっと、MomentoがGCP Cloud RunとFirestoreのレイテンシの98%を削減した!

サーバーレス・キャッシングにより、Cloud RunとFirestoreのレイテンシーを簡単に削減できます。

Ellery Addington-White
著者

Share

前回のブログ記事では、Amazon Web Services(AWS)のサーバーレスLambda APIのレイテンシを削減するためにMomento Cacheを活用する方法について深く掘り下げました。今回は趣向を変えて、MomentoをGoogle Cloud Platform(GCP)と統合することで、Cloud RunとFirestoreのレイテンシをどのように削減できるかについて説明します。

Test Setup

Service

このテストのセットアップを簡単にまとめると、各ユーザーがフォロワーを持つソーシャルネットワークを構築しています。あなたのフロントエンドアプリは、現在のユーザーの各フォロワーの名前をダウンロードして、デバイス上でレンダリングする必要があります。以下のAPIを公開します:

GET /users and /cached-users

Makes 1 call to Firestore (/users) or Momento (/cached-users)

Example response:

{
    "id": "1",
    "followers": [
   	 "26",
   	 "65",
   	 "49",
   	 "25",
   	 "6"
    ],
    "name": "Lazy Lion"
}

GET /followers and /cached-followers

渡されたユーザーIDに対して、Firestore (/followers)またはMomento (/cached-followers)のいずれかに1回コールし、その後、FirestoreまたはMomentoのいずれかにN回(このテストでは5回)コールして、各フォロワー名を検索します。

Example response:

{
    "id": "1",
    "followers": [
   	 "26",
   	 "65",
   	 "49",
   	 "25",
   	 "6"
    ],
    "name": "Lazy Lion"
}

私はGCPの経験が浅く、これまでのキャリアではほぼAWSのみにフォーカスしてきたので、GCPの開発者エクスペリエンスを掘り下げることにとても興奮していました。私は、GCPを有効にするために、AWSで実行している既存の基本ユーザーサービスから何を変更しなければならないかを見つけることから始めました。

私が代替を必要としていた主なサービスは以下の通りです:

・データベース
・メトリクス
・ランタイム
・インフラストラクチャー・アズ・コード(IaC)

データベース

私は信頼できる検索エンジン(DuckDuckGo ftw)を起動し、”Best GCP alternative to DynamoDB “と検索するという非常に科学的なアプローチから始めました。私が見た主な結果は、AWS DynamoDBの代替NoSQLデータベースとしてGCP Firestoreを使うことでした。簡単だ。試してみましょう!

メトリックス

AWSでは、aws-embedded-metricsを使ってメトリクスを収集し、cloudwatchログ経由でエクスポートしていました。検索してみると、GCPのGoogle Cloud MetricsがGCloud Watch Metricsに相当することがわかりました。これは簡単そうだし、node.js SDKもあります。

ランタイム

ここにはいくつかの選択肢がりました。Google Cloudには、Cloud RunCloud FunctionsAppEngine(マネージドk8s)、そして基本的なVMがあります。私はVMやオペレーティング・システムやネットワークの管理に伴うオーバーヘッドを扱いたくなかったし、単純なREST APIのためにk8sの缶を開けなければならないような気もしませんでした。AWSでLambdaを使っていたので、Google Cloud Functionsも検討しましたが、自分のシンプルなAPIをコンテナに移植するだけで、将来的に異なるクラウド環境で動作する結果についてもっと簡単に実験できるようにしたかったのです。それで結局、Cloud Runに落ち着きました。最もシンプルで素早く立ち上げることができ、将来的にGCP上で自分のサービスをよりポータブルにする道筋を与えてくれるように思えたからです。

Infrastructure as Code

私はIaCライブラリの大ファンです。2022年にクラウドで仕事をする唯一の方法だと思うし、プラットフォームエンジニアとしてYAMLで直接仕事をすることに戻ることは想像できません。私は現在AWSでCloud Development Kit (CDK)を使っており、過去にはCDKのTerraformエクステンション(CDK-TF)を使ってGCPでのインフラのプロビジョニングを手伝ってもらったことがあります。しかし今回、私は何か新しいことを試してみたかったのです。PulumiのCloud Run TypeScriptのサンプルはシンプルでクリーンなものに見えました。また、コードベースがうまく整理されている限り、仕事に最適なツールを使い、ランタイム間で簡単に切り替えることが可能であることを紹介したかったのです。

テクノロジーを選択した後、私はサービスの実装と運用を開始しました。マルチクラウドのベストプラクティスや、異なるGCPテクノロジーを比較するためのいくつかの特別なフォローアップ記事にご期待ください。

GCP専用チューニング

デフォルトのPulumi Cloud Runサービスの構成からあまり変更しませんでした。主なことは、私が使っているAWS Lambdaランタイムと同じように見えるように、いくつかの設定を微調整したことだです。

デフォルトからいじった設定は以下の通りです:

CPU: AWSの2vCPUに相当する各コンテナの上限を2000mにしました。私はAWSで2GBのメモリをLambdasに使用しており、これも2vCPUを使用していました。
メモリ: AWSでラムダ用に使っていたメモリ量と同じになるように、各コンテナに2Giに設定しました。
タイムアウト: 最大5分🤯から最大15秒に短縮しました。
コンテナの同時実行数: AWSのLambdaがフード下の各Firecracker microVMに対して最大同時実行数をどのように処理するかに合わせるため、これを1に減らし、それぞれが一度に1つのリクエストを処理するように制限しました。Cloud Runはボンネットの下でKnativeを使用しているので、AWS Lambdaと同じように機能しています。

Plumi・CloudRunのコンストラクトコードはこちらでご覧いただけます:

const service = new gcp.cloudrun.Service("ts-api-svc", {
   location,
   template: {
       spec: {
           timeoutSeconds: 15,
           containerConcurrency: 1, 
           containers: [{
               envs: [
                   {
                       name: "RUNTIME",
                       value: "GCP"
                   },
                   {
                       name: "PROJECT_ID",
                       value: project
                   }
               ],
               image: myImage.imageName,
               resources: {
                   limits: {
                       cpu: "2000m",
                       memory: "2Gi",
                   },
               },
           }],
       },
   },
});

パフォーマンスはどうだったか?

AWSと同じように、私はLocustを使ってラップトップからいくつかの基本的な負荷を実行しました。GCPリージョンのus-east1でAPIを実行し、us-east1でMomentoキャッシュとFirestoreも使用しました。APIエンドポイント全体のレイテンシーと、nodejsコンテナから見たMomentoやFirestoreへのリクエストに費やされた時間の両方を計測しましたた。そして、Google Cloud Metricsにタイミング結果を記録しました。

/usersと/cached-users(厳密にはp99)のFirestoreのレイテンシとMomentoのレイテンシを比較すると、433.2msから6.0msへと98%削減されました。

Y axis is milliseconds (logarithmic scale)

1つのAPIからデータベースへの複数の呼び出しを開始すると、テールレイテンシが積み重なり、高速化がさらに極端になることがよくわかります。FirestoreのレイテンシーとMomentoのレイテンシーを/followersと/cached-followers(厳密にはp99)で比較すると、4610.0msから14.1msへと99.7%削減されました!

教訓

Momentoは、ほんの数分の作業でp99 Firestoreのレイテンシーを98%以上低下させました。これは、クラウド運用コストの削減、ユーザーの満足度向上、拡張性の高いシステムを意味します。GCPの開発者エクスペリエンスと、立ち上げと運用の速さには本当に感心しました。今では、AWSと同じように、APIのレスポンスタイムを一貫して10ms以下にすることができます!他のキャッシュを比較したり、他のランタイムを試したりするのが楽しみです。

現在Firestoreを使用しているエンジニアや、GCPでアプリケーションを実行しているエンジニアは、特にワークロードが爆発的で予測が難しい場合(ゲームなど)、Momentoを試してみて、どのようにコストを削減し、ユーザーを幸せにできるかを確認することを強くお勧めします。

Share