
DevelopersIO 2024 FUKUOKA Day2にて「Google Cloudでプロダクト開発するZennの例」をテーマとして登壇しました #devio2024 #クラスメソッド福岡 | DevelopersIO
こんにちは。Zennチームの和田です。2024年はクラスメソッド設立20周年イベントということで、Classmethod Odysseyが開催されます。先陣を切るのは福岡。6月28日(金)のDay1と、Day2の 2days開催です。 私は Day2 で「Google Cloud でプロダクト開発事業として成長させる Zennの例」というテーマで登壇しました。 現地登壇って、いいよね… オフラインならではの熱気、リアクション、リアルタイムなやりとり、運営の方々のプロフェッショナルな連携…最高です。 登壇資料 直前のセッションが Google Cloud Japan 大沼翔様のセッションで、キャリアとプロダクト開発の勘所について、ご自身の体験を交えながら共有してくださいました。バトンを受けたわたしは、ZennがGoogle Cloudをどう活用しているか、プロダクト開発をどのように進めているか、例を交えてお話させていただきました。 あゆみ これまでもさまざまなメディアで展開されていますが、Zennはもともとcatnoseさんが個人プロジェクトとしてリリースしたWebアプリです。現在は、クラスメソッドのZennチームがメインで開発・運用を行っています。 Zennのアーキテクチャ ZennのAPIはRuby on Railsで実装されており、初期リリース時点でApp Engineへデプロイしていました、その名残もありGoogle Cloudを使い続けています。App Engine をCloud Runへ移行し、スケーラブルな環境で稼働できています。 Cloud Build でデプロイする例 Google Cloud でどんなことをやっているかの例のひとつです。GitHubのmainブランチへマージされると、Cloud Buildが起動し、Cloud Run の新しいリビジョンを作成します。最後の、新しいリビジョンへトラフィックを流す部分は人間が行っています。 Cloud Tasks でオフロードする例 Cloud Tasks は、任意のパラメータをタスクキューに詰め、その実行流量を制御できるオフロード用のサービスです。ZennではMarkdownをHTMLへ一括変換する処理で活用しています。 Google Cloud まとめ 開発者にとって絶妙な抽象度で事業に集中できる ワークロードに対してベストプラクティスに沿えば困ることは少ない 迷ったら Cloud Run と Cloud SQL 中心でOK 総じて、開発者がビジネスに集中できるよう設計されているというのが、私が好きなポイントです。 統計ダッシュボードを改善した流れ Zenn の Publication Pro で提供している機能のひとつに、統計ダッシュボードがあります。先日リニューアルリリースしたのですが、その際、実際に使っていただいている方のフィードバックを大いに参考にさせていただきました。 要望から課題を探る ヒアリングのなかで、要望を聞くだけでなく、課題を深堀りすることを意識した結果、「統計情報を個人のふりかえりに使いたい」という共通課題が抽出できました。結果、ありがたい反響をいただいています。これを繰り返して、Publication Pro は、企業の皆様の大きな課題を解決することを目指しています。 さいごに Zenn Community で意見交換しましょう Zenn Community はオープンなGitHubリポジトリです。ここのISSUEで要望や不具合のやりとりを行っています。気になったISSUEなどに、リアクション❤️をいただけると嬉しいです! Zenn Community
クラスメソッド発「やってみた」系技術メディア | DevelopersIO
Cloud Tasksで複数のCloud Functionsを非同期に呼び出してみた | DevelopersIO
Google Cloudデータエンジニアのはんざわです。 前回の記事では、Cloud Tasksの簡単な概要を紹介した後に単一のCloud FunctionsをCloud Tasksで呼び出す方法を紹介しました。 今回のブログでは、Cloud Tasksで複数のCloud Functionsを非同期に呼び出してみたいと思います。 前回と同様にCloud Tasksでタスクを作成し、Cloud Functionsを呼び出しますが、複数のCloud Functionsを呼び出す場合、その呼び出す数だけタスクを作成する必要があります。 ひとつずつタスクを作成するのは現実的ではないため、Pythonのクライアントライブラリで複数のタスクをまとめて作成したいと思います。 事前準備 今回の検証では、以下のリソースを準備します。 Cloud Tasksのキュー Cloud Tasksから呼び出されるCloud Functions Cloud Tasksのタスクを作成するCloud Functions さっそく作成していきましょう。 Cloud Tasksのキュー まずは、Cloud Tasksのキューを作成します。 次のキャプチャのような構成でキューを作成しました。 名前: exec-cloud-functions 最大ディスバッチ数: 10 / 秒 最大同時ディスバッチ数: 2 最大同時ディスバッチ数で最大並列数を2に制限しているため、同時に実行されるCloud Functionsは2つのみになる想定です。 これらのオプションの詳細は前回のブログで紹介しているので、興味がある方は是非確認してみてください。 Cloud Tasksから呼び出されるCloud Functions 次にCloud Tasksから呼び出されるCloud Functionsをデプロイします。 以下のコードをexec-by-tasksという名前でデプロイしました。 見ての通り、処理はシンプルで、Cloud Functionsが受け取ったリクエストボディから変数を受け取り、出力するだけです。 また、後続で呼び出されるCloud Functionsの挙動も確認したいため、5秒間のスリープを仕込んでいます。 Cloud Tasksのタスクを作成するCloud Functions 最後にCloud Tasksのタスクを作成するCloud Functionsをデプロイします。 上記のドキュメントを参考にHTTPタスクをPythonで作成します。 処理の流れとしては、1から10までの数字をリクエストボディのパラメータに加えたタスクを順次作成し、それをキューに送信しています。 さっそく動かしてみる まずはcreate-tasksを起動してタスクをキューに送信します。 Cloud Loggingを確認すると次のキャプチャのようにログが出力されていました。 タスクがキューに送信されるとそのタスクの終了を待たず、非同期に次のタスクが送信されていることがわかると思います。 次にexec-by-tasksのログも確認します。 1番目と2番目は、ほぼ同時に呼び出されていますが、3番目と4番目は1番目と2番目が終了してから呼び出されていることがわかると思います。 これは事前にキューの設定で最大同時ディスバッチ数を2にしたため、同時に2つまでしか実行されないようにキューが制御しています。 制限事項 Cloud Tasksにもいくつか制限事項があります。詳細は、上記のドキュメントを確認してみてください。 特に気を付けるべき項目は次の2点だと思いますので実装する際は気をつけてください。 1分あたりで作成できるAPIリクエストの合計数が600万回 キューに追加できるタスクの最大サイズが1MB まとめ 今回は、Cloud Tasksで複数のCloud Functionsを非同期に呼び出してみました。 シンプルに1から10までの数字をリクエストボディに含めてみました。他の例として、バケットからファイルの一覧を取得して、それらをリクエストボディに含めて何らかの処理をさせたりすることも可能だと思います。 正確に並列数を制御したい場合、Cloud Tasksは有効なサービスだと思うので、是非利用を検討してみてください。
クラスメソッド発「やってみた」系技術メディア | DevelopersIO
Google Cloud Tasksを完全に理解する | DevelopersIO
Google Cloudデータエンジニアのはんざわです。 つい最近、Cloud Tasksを触ってみる機会があり、そこで学んだことや実際に動かしてみた内容を共有したいと思います。 今回の記事では、Cloud Tasksの概要を整理し、単一のCloud FunctionsをCloud Tasksで起動するまでの流れを実際に構築してみたいと思います。 Cloud Tasksの概要 Cloud Tasksは、大量の分散タスクの実行、ディスパッチ、配信を管理できるフルマネージドサービスです。 Cloud Tasksを使用すると非同期処理を簡単に実装でき、実行のタイミングや回数などを柔軟に制御することが可能です。 公式ドキュメントで紹介されている通り、主なユースケースとしては、次のようなものがあります。 データベースの更新のようなバックグラウンド処理に時間がかかる可能性のある処理をワーカーに委譲することで、ユーザの応答時間を短縮する 予期せぬ本番インシデントが発生した場合にリクエストを維持する メインユーザフローから非ユーザ向けタスクを削除することでトラフィックの急増をスムーズにする サードパーティのAPIコールレートを管理する もう少し詳しく Cloud Tasksには、タスクとキューが存在し、それぞれ異なる役割を持っています。 タスクとキューは以下の画像のような構成になっています。 処理の流れは以下の通りです。 「メールを送信する」や「データを加工する」などの実行したい処理を呼び出すリクエストをタスクとして登録する タスクはキューに追加され、正常に実行されるまでタスクは保持される キューはそのタスクをユーザーが定義したレートで「メールを送信する」や「データを加工する」などの実行したい処理をするターゲットにリクエストを送信する キューが正常なHTTPレスポンスコード(200〜299)を受け取ったらそのまま終了し、別のレスポンスが送信されたり、レスポンスがない場合はタスクが再試行される 続いて、タスクとキューについてもう少し詳しく見てみたいと思います。 タスクについて タスクは、 「メールを送信する」や「データを加工する」などの実行したい処理を呼び出すリクエストに該当します。 タスクで定義したリクエストの送信先は、HTTP/Sエンドポイント と App Engineアプリケーション の2つがあります。 HTTP/SエンドポイントであればCloud Functions、Cloud Run、GKE、Compute Engine、またはオンプレミスのウェブサーバーなどにリクエストを送信することが可能です。 これらのリクエストを受け取り、処理を実行するエンドポイントを ワーカー と呼びます。 HTTP/Sのタスクの場合、すべてのワーカーは、デフォルトのタイムアウトが10分で最大でも30分以内にHTTPレスポンスコード(200~299)を送信する必要があります。別のレスポンスが送信されたり、レスポンスがない場合はタスクが再試行されてしまうので注意しましょう。 キューについて キューは、タスクが追加されるとユーザーが定義したレートでワーカーにリクエストを送信し、確実に処理されるようにします。 ワーカに送信するリクエストのレートに関しては、後ほどCloud Tasksを準備するパートで紹介します。 実際に動かしてみる Cloud Functionsの準備 まずは呼び出されるCloud Functionsをデプロイします。 設定内容は次の通りです。その他の項目は全てデフォルトの設定を使用しています。 名前: exec-by-tasks リージョン: asia-northeast1 Cloud Functionsをセキュアーに呼び出すためにトリガーのタイプをHTTPSに設定し、認証は認証が必要に設定しました。 また、ソースコードは次のようなシンプルなものを用意しました。 サービスアカウントの準備 次にCloud TasksがCloud Functionsを呼び出す際に使用するサービスアカウントの準備をします。 今回の検証では、Cloud Functionsを認証が必要なHTTPSトリガーに設定しているため、HTTPリクエストに認証情報を含める必要があります。 一般的にCloud FunctionsやCloud Runにリクエストを送信するときは、OpenID Connect(OIDC)を使用して認証します。 つまり、タスクを実行するサービスアカウントがOIDCから認証情報を取得できるように適切な権限を付与する必要があります。 一見難しそうに見えますが、実際にはとても簡単です。 まずは、OIDCから認証情報を取得するサービスアカウントを作成します。名前は次の通りです。 名前: cloud-tasks さらに、このサービスアカウントが事前にデプロイした第2世代のCloud Functionsを実行するためにサービス単位でroles/run.invoker(Cloud Run 起動元)の権限を割り当てます。 これでCloud TasksからCloud FunctionsにHTTPリクエストを送信する際、OIDCで取得した認証情報を含められるようになりました。 Cloud Tasksのキューの準備 次にCloud Tasksのキューを作成します。 名前とリージョンは次の通りです。 名前: exec-cloud-functions リージョン: asia-northeast1 キューの詳細設定は、以下のキャプチャの通りです。 ディスパッチとは、キューのタスクをワーカーに送信することを指します。 つまり、最大ディスパッチ数は、1秒間にキューからタスクをワーカーに送信する最大レート数を指します。 同様に最大同時ディスパッチ数は、Cloud Tasksがキューからタスクをワーカーに送信することを許可する最大数に該当します。 これらのパラメータを適切に設定することでAPIコールレートなどを管理し、バックエンドシステムへの負荷の調整が可能になります。 また、各パラメータの詳細は以下のドキュメントで確認してください。 タスクを作成してCloud Functionsを実行してみる 次に作成したキューからCREATE HTTP TASKを選択し、タスクを作成します。 入力内容は以下のキャプチャの通りです。 注意点として、AuthヘッダーにOIDC トークンを追加を選択し、事前に作成したサービスアカウントを割り当てるようにしましょう。 しかし、Cloud Functionsのログを確認すると415エラーが発生していました。。。 …
クラスメソッド発「やってみた」系技術メディア | DevelopersIO