$30 off During Our Annual Pro Sale. View Details »

ZennにみるCloudRunとBigQueryによるアプリケーション構築 / zenn-cloudrun-bigquery-serverless

Yusuke Wada
September 23, 2023

ZennにみるCloudRunとBigQueryによるアプリケーション構築 / zenn-cloudrun-bigquery-serverless

Zennは、クラスメソッドが展開する技術者向けの知識共有プラットフォームです。Cloud Runを中心としたGoogle Cloudのソリューションをメインで使用しており、スケーラブルなWebアプリケーションとなっています。

このセッションでは、「サーバーレスとはなにか」という部分から改めてディスカッションし、アプリケーションをスケーラブルに、ビジネスに集中するという目的に対してZennがどうアプローチしているかを解説します。

また、Google Cloud を利用するモチベーションのひとつにBigQueryの存在があると思います。Zennでも統計機能に利用しており、アプリケーションとどのように統合しているか紹介、それがどの程度 Google Cloud を使う理由になるか議論します。

サーバーレスアプリケーションを組むときに、みなさまの選択肢をひとつ増やし、結果的によりニーズに合致したアーキテクチャを選定できる手助けとなることを期待しています。

Yusuke Wada

September 23, 2023
Tweet

More Decks by Yusuke Wada

Other Decks in Programming

Transcript

  1. Cloud Run を中心としたWebアプリケーション構築事例
    BigQueryとの統合解説
    #serverlessdays
    #serverlesstokyo

    View Slide

  2. クラメソZennチームで働いている和田といいます
    クラスメソッドへ入社
    2016年2月
    AWS EC2、Scala、Backend API
    サーバーレス(FaaSベース)アプリ開発
    2018年7月
    AWS Lambda、Node.js、Backend API, React SPA
    Zennをきっかけに Google Cloud の世界へ
    2021年7月
    Cloud Run、Next.js、Ruby on Rails、Zenn全般
    福岡県北九州市出身です!

    View Slide

  3. サーバーレスといえば…

    View Slide

  4. サーバーレスといえば…
    API Gateway AWS Lambda DynamoDB

    View Slide

  5. クラスメソッドでも お客様の課題解決に活用しています
    サーバーレスソリューションを駆使してきた
    アプリケーション開発メンバーに
    「変化」を探るべく
    アンケートをとってみました

    View Slide

  6. 開発者へのアンケート
    AWS、Azure、Google Cloud 問わず
    Q1. これまでアプリ開発で使ってきたコンピューティングサービス
    Q2. これから使ってみたいコンピューティングサービス
    ※ クラウドプラットフォームやサービスを比較するものではありません

    View Slide

  7. View Slide

  8. View Slide

  9. コメント紹介(一部)
    > LambdaのSnapStartも追い風となり、かつてはバットプ
    ラクティスだったLambdaにWebフレームワークのデプロイ
    が推奨される時代が来ていると感じています。
    > APIGWやStepFunctionsを前段に置いて適切な粒度で処理
    を区切れば多くの場合、コンピューティングはLambdaで問
    題ないのかなと思っています。一方で、(中略)App Runner
    も主要な検討対象になってきたかなと思っています。
    > 潮流的にFaaS->コンテナへの回帰を感じるが、FaaSは上記
    の点でやはり優れたプラットフォームだと思う

    View Slide

  10. サーバーレスの選択肢が確実に広がっている
    サーバーレスのどんな要素に我々は心打たれたのか?
    使った分だけ課金
    素早い市場投入
    無限のスケール
    これらの特性を取り入れたサービス・ソリューションが増えている
    コンテナもそのひとつ

    View Slide

  11. 「サーバーレスってこう」ではなく…
    Zennを動かしているのは:
    Cloud Run
    Cloud SQL
    BigQuery
    なにを考えて選んだか?結果どれくらいサーバーレスなのか?
    選択肢のひとつとしてポケットに入れていただきたい

    View Slide

  12. Zenn / Cloud Run

    View Slide

  13. とは
    Zennは「知見を共有するエンジニアに対価を」
    というコンセプトでつくられた
    技術情報共有コミュニティです。

    View Slide

  14. 3種類の投稿形式で、その時々に合った粒度で知見を残すことができます
    ひとまず
    雑にメモ
    したい
    あのテーマ
    で誰かと
    議論したい
    最近学んだ
    あの話を記事
    にしよう
    労力が
    かかった分
    有料で販売
    しよう
    あの話を
    まとめて
    本にしよう

    View Slide

  15. View Slide

  16. Webアプリフレームワーク + DB でシンプルに構築したい
    フレームワーク
    => Next.js と Ruby on Rails
    データベース
    読み込みが多いワークロード
    ユーザーごとの投稿一覧を取得したり、新着順で投稿を取得したり
    Ruby on Rails の恩恵を受けられる
    => RDB(PostgreSQL)にきまり

    View Slide

  17. デプロイ先どうするか
    Next.js や Rails を簡単にデプロイしたい
    Cloud Load Balancing
    App Engine
    Cloud SQL
    VMインスタンスではなくコンテナで運用したい
    ので Cloud Run へ移行した経緯あり
    https://zenn.dev/team_zenn/articles/migrate-appengine-to-cloudrun

    View Slide

  18. View Slide

  19. Web3層構成

    View Slide

  20. Web3層構成でサーバーレス!?
    構成をシンプルに保ちつつも、ネットワークやインスタンスはあまり意識せずに済んでい

    View Slide

  21. ネットワーク
    Google Cloud のリソース群によりIAMによるアクセス制御が可能、ほとんど意識して
    いいない
    Serverless NEG
    Cloud SQL Auth Proxy
    Identity Aware Proxy
    個々のリソースについてはぜひフリートークしましょう👍

    View Slide

  22. インスタンス
    Cloud Run の力で意識せずに済んでいる
    使用したリソースに対してのみ課金
    RailsやNext.jsの恩恵を受けつつコンテナデプロイ
    ステートレス、エフェメラル、自動スケール

    View Slide

  23. もちろん課題もある
    コールドスタート問題
    非同期タスクの実行時間上限問題

    View Slide

  24. 変更デプロイ時のコールドスタート対策
    リクエスト
    現行リビジョン
    インスタンス1
    現行リビジョン
    インスタンス2
    現行リビジョン
    インスタンス1
    現行リビジョン
    インスタンス2

    View Slide

  25. 変更デプロイ時のコールドスタート対策
    リクエスト
    現行リビジョン
    インスタンス1
    現行リビジョン
    インスタンス2
    現行リビジョン
    インスタンス1
    現行リビジョン
    インスタンス2
    gcloud run deploy backend-user-api
    --quiet
    --project=$PROJECT_ID
    --region=${_REGION}
    --image=$_ARTIFACT_REPOSITORY_IMAGE_TAG
    --service-account=$_CLOUD_RUN_SERVICE_ACCOUNT
    --add-cloudsql-instances=$_CLOUDSQL_INSTANCE_FULL_NAME
    --revision-suffix=${SHORT_SHA}-${_SHORT_BUILD_ID}
    --concurrency=1000
    --cpu=1
    --memory=4Gi
    --max-instances=150
    --min-instances=2
    --no-use-http2
    --allow-unauthenticated
    --no-cpu-throttling
    --ingress=internal-and-cloud-load-balancing

    View Slide

  26. 変更デプロイ時のコールドスタート対策
    現行リビジョン
    インスタンス1
    現行リビジョン
    インスタンス2
    新リビジョン
    インスタンス1
    新リビジョン
    インスタンス2
    現行リビジョン
    インスタンス1
    現行リビジョン
    インスタンス2
    新リビジョン
    インスタンス1
    新リビジョン
    インスタンス2
    コールド
    スタート
    gcloud run deploy backend-user-api
    --quiet
    --project=$PROJECT_ID
    --region=${_REGION}
    --image=$_ARTIFACT_REPOSITORY_IMAGE_TAG
    --service-account=$_CLOUD_RUN_SERVICE_ACCOUNT
    --add-cloudsql-instances=$_CLOUDSQL_INSTANCE_FULL_NAME
    --revision-suffix=${SHORT_SHA}-${_SHORT_BUILD_ID}
    --concurrency=1000
    --cpu=1
    --memory=4Gi
    --max-instances=150
    --min-instances=2
    --no-use-http2
    --allow-unauthenticated
    --no-cpu-throttling
    --ingress=internal-and-cloud-load-balancing

    View Slide

  27. 変更デプロイ時のコールドスタート対策
    リクエスト
    現行リビジョン
    インスタンス1
    現行リビジョン
    インスタンス2
    現行リビジョン
    インスタンス1
    現行リビジョン
    インスタンス2
    gcloud run deploy backend-user-api
    --quiet
    --project=$PROJECT_ID
    --region=${_REGION}
    --image=$_ARTIFACT_REPOSITORY_IMAGE_TAG
    --service-account=$_CLOUD_RUN_SERVICE_ACCOUNT
    --add-cloudsql-instances=$_CLOUDSQL_INSTANCE_FULL_NAME
    --revision-suffix=${SHORT_SHA}-${_SHORT_BUILD_ID}
    --tag=latest
    --concurrency=1000
    --cpu=1
    --memory=4Gi
    --max-instances=150
    --min-instances=2
    --no-traffic
    --no-use-http2
    --allow-unauthenticated
    --no-cpu-throttling
    --ingress=internal-and-cloud-load-balancing

    View Slide

  28. 変更デプロイ時のコールドスタート対策
    リクエスト
    現行リビジョン
    インスタンス1
    現行リビジョン
    インスタンス2
    現行リビジョン
    インスタンス1
    現行リビジョン
    インスタンス2
    gcloud run deploy backend-user-api
    --quiet
    --project=$PROJECT_ID
    --region=${_REGION}
    --image=$_ARTIFACT_REPOSITORY_IMAGE_TAG
    --service-account=$_CLOUD_RUN_SERVICE_ACCOUNT
    --add-cloudsql-instances=$_CLOUDSQL_INSTANCE_FULL_NAME
    --revision-suffix=${SHORT_SHA}-${_SHORT_BUILD_ID}
    --tag=latest
    --concurrency=1000
    --cpu=1
    --memory=4Gi
    --max-instances=150
    --min-instances=2
    --no-traffic
    --no-use-http2
    --allow-unauthenticated
    --no-cpu-throttling
    --ingress=internal-and-cloud-load-balancing
    新リビジョン
    インスタンス2
    新リビジョン
    インスタンス1
    latest
    latest

    View Slide

  29. 変更デプロイ時のコールドスタート対策
    現行リビジョン
    インスタンス1
    現行リビジョン
    インスタンス2
    リクエスト
    現行リビジョン
    インスタンス1
    現行リビジョン
    インスタンス2
    新リビジョン
    インスタンス2
    新リビジョン
    インスタンス1
    latest
    latest
    gcloud run services
    update-traffic
    backend-user-api
    --quiet
    --region=asia-northeast1
    --to-revisions=latest=100

    View Slide

  30. 非同期タスクの実行時間対策(デフォルト10分)
    Markdown の一括変換
    ⇒ 変換処理に破壊的変更を入れる場合などに、保存済みの記事を変換する

    View Slide

  31. 非同期タスクの実行時間対策(デフォルト10分)
    Markdown の一括変換
    ⇒ 変換処理に破壊的変更を入れる場合などに、保存済みの記事を変換する
    出典:
    https://en.wikipedia.org/wiki/Scheduling_(computing)#task_queue

    View Slide

  32. ここまでのまとめ
    Zennは、サーバーレスの特性を意識しぎず、ビジネス・ワークロードに合ったアーキテク
    チャをシンプルに寄せて選択
    Google Cloud の高抽象度なリソースのおかげで、サーバーレスの特性を享受してい

    メリットのかわりに手間をかけているところもある
    どれくらいサーバーレスといえるのか?を最後にふりかえる

    View Slide

  33. BigQuery

    View Slide

  34. BigQuery: フルマネージドデータレイク
    Zennでの利用例をいくつか紹介します
    アクセスログ、BigQuery、Looker Studio
    アクセスログ、BigQuery、Cloud Armor
    Google Analytics4、BigQuery、Looker Studio
    統計ダッシュボード

    View Slide

  35. アクセスログ、BigQuery、Looker Studio
    Cloud Load
    Balancing
    Cloud Logging BigQuery
    Looker
    レイテンシ集計レポートを作成して潜在的なパフォーマンス問題がないか確認

    View Slide

  36. アクセスログ、BigQuery、Cloud Armor
    Cloud Load
    Balancing
    Cloud Logging BigQuery
    攻撃の疑いがあるとき、IPアドレスを特定してブロック
    Cloud Armor

    View Slide

  37. Google Analytics4、BigQuery、Looker Studio
    BigQuery
    Looker
    PVなどのレポート
    Google Analytics4

    View Slide

  38. アプリケーションとの統合例: 統計ダッシュボード
    ログインユーザーが表示できる
    公開した記事の閲覧数などをみられる
    ログインユーザーの認証・認可
    Google Analytics4 のイベントデータとCloud
    SQL のデータをどうにかJOINする必要がある
    不特定多数のユーザーに呼ばれるため、クエリ課金
    を回避したい

    View Slide

  39. BigQuery BI Engine を使いました
    キャッシュ容量をあらかじめ購入し、キャッシュに入れ
    たいBigQueryのテーブルを指定する
    1GBあたり約$36/月
    キャッシュ内のデータに対するクエリには課金が発生し
    ない
    統計ダッシュボードで利用するデータがすべてキャッ
    シュに収まれば…?
    BigQueryクライアントからみたときの使い方は全く変
    わらない
    BigQuery BI Engine
    PV table, master table
    BigQuery
    Zenn User
    Ruby on Rails
    Cloud Run

    View Slide

  40. いかにキャッシュ領域に統計データをおさめるか
    スケジュールクエリで、PVイベントとマスタ(記事)
    データで必要なものだけ事前に集計、テーブルを
    用意しておく
    それらのテーブルをBI Engineの対象にする
    BigQuery BI Engine
    PV table, master table
    BigQuery
    Zenn User
    Ruby on Rails
    Cloud Run
    スケジュール
    クエリ
    master table
    PV table

    View Slide

  41. BigQueryのまとめ
    アプリケーションとは独立して利用できるケースと、アプリケーションと統合して利用する
    ケースを示した
    BigQuery はフルマネージドサービスで、クエリを使った分だけ課金される
    しかしZennの統計ダッシュボードでは使った分だけ課金だと青天井になる恐れがあった
    BI Engineを使い、コミットメント料金とすることで解決した
    データ容量の問題はエンジニアリングでカバー

    View Slide

  42. Serverless

    View Slide

  43. 特性をどれくらい満たせているか
    使った分だけ課金
    素早い市場投入
    スケーラビリティ

    View Slide

  44. 使った分だけ課金
    一部のリソースでは定常課金あり(Cloud Load Balancing、Cloud SQL、
    BigQuery BI Engine など)
    Cloud Run もコールドスタートを防ぐためにゼロスケールはせず、最低2台イン
    スタンスが立ち上がるよう設定
    => 常に一定以上のアクセスがあるためその分の固定料金と思えば気にならない
    => 大事なのは、使った分だけ課金というよりは、月当たりのトータル金額

    View Slide

  45. 市場投入
    最初のデプロイは時間がかかる
    が、Zennの場合は繰り返し変更をデリバリーするタイプ
    変更容易性という点では助かっている
    ⇒ 典型的なWeb3層構成 Ruby on Rails + PostgreSQL(Cloud SQL)
    ⇒ ローカルでのテストが充実

    View Slide

  46. スケーラビリティ
    Cloud Run は満たせる
    Cloud SQL は満たせない…?

    View Slide

  47. スケーラビリティ
    Cloud Run は満たせる
    Cloud SQL は満たせない…?でもちょっと待って!

    View Slide

  48. スケーラビリティ
    スケールを考えるシーンはふたつ
    1.スパイクアクセス
    => 特定の記事がバズったとき
    => 特定のレコードへのアクセスにはキャッシュが効く (DB、Rails)
    => Cloud Run さえスケールできていれば気にしすぎることはない
    2.アクティブユーザーの増加
    => Cloud SQL への負荷も予測できる
    => 手動での垂直スケール(メンテして性能強化)で対応

    View Slide

  49. オンデマンド
    課金特性
    デプロイ特性
    スケール特性
    圧倒的初速
    自動水平
    エクストリームサーバーレス

    View Slide

  50. オンデマンド
    コミットメント
    課金特性
    デプロイ特性
    スケール特性
    圧倒的初速
    継続容易性
    自動水平
    手動垂直
    エクストリームサーバーレス

    View Slide

  51. オンデマンド
    コミットメント
    課金特性
    デプロイ特性
    スケール特性
    圧倒的初速
    継続容易性
    自動水平
    手動垂直
    Zenn

    View Slide

  52. オンデマンド
    コミットメント
    課金特性
    デプロイ特性
    スケール特性
    圧倒的初速
    継続容易性
    自動水平
    手動垂直
    Zenn

    View Slide

  53. オンデマンド
    コミットメント
    課金特性
    デプロイ特性
    スケール特性
    圧倒的初速
    継続容易性
    自動水平
    手動垂直
    Zenn

    View Slide

  54. オンデマンド
    コミットメント
    課金特性
    デプロイ特性
    スケール特性
    圧倒的初速
    継続容易性
    自動水平
    手動垂直
    コスト効率、ビジネス効率が最大になるよう
    にサーバーレス特性を取り入れていく
    Zenn

    View Slide

  55. まとめ
    サーバーレスの特性を備えた実行環境が選べるようになってきた
    振り切った特性を最初に目指すよりは、まずビジネスに対するワークロードを考え、それ
    を満たせるシンプルなアーキテクチャを選択するほうが楽
    その後、デリバリー速度、コスト効率が最大になるようにサーバーレス特性を取り入れて
    いく(場合によっては手間をかけるシーンも許容する)
    このようなアプリ構築も一つの手

    View Slide

  56. View Slide