はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【GCP, C#】Google Cloud Functions(.NET) + Cloud Scheduler + Cloud Pub/Subを用いてSlack通知ツールを作る

はじめに

今回はGoogle Cloud Functions(.NET) + Cloud Scheduler + Cloud Pub/Subを用いて定期的にSlackにメッセージを投稿するシステムを作ってみようと思います。

実際に動作させている様子

概要

以下のような構成図で実装します。

構成図

Slackでの操作

Slackアプリを作成する

対象のワークスペースにて、Slackアプリを作成する必要があります。以下のURLにアクセスをし、Create an Appを選択します。
https://api.slack.com/apps

api.slack.com/apps
  1. From scratchを選択
  2. App Nameに適当な名前を入力し、Pick a workspace to develop your app inに対象ワークスペースを選択

Appが作成できたら、Incoming Webhooksの設定をしていきます。

  1. タブバーからIncoming Webhooksを選択し、Activate Incoming Webhooksをオンにする
  2. Webhook URLs for Your WorkspaceWebhook URLに対象のワークスペースを設定する
  3. 生成したWebhook URLをメモしておく
Incoming Webhooks/Activate Incoming Webhooksをオンにする
Webhooks URLにワークスペース&チャンネルを設定する

GCPでの操作

Cloud Pub/Subの設定

Cloud Pub/Subは非同期のメッセージングサービスです。Cloud Schedulerからイベントを受け取り、Cloud Functionsにイベントを送信します。

Pub/Sub は、メッセージを生成するサービスを、それらのメッセージを処理するサービスと切り離す、非同期のスケーラブルなメッセージング サービスです。

...

Pub/Sub は、ストリーミング分析と、データを読み込んで配布するためのデータ統合パイプラインに使用されます。これは、サービスの統合を目的としたメッセージング指向のミドルウェア、または、タスクを同時に読み込むキューとしても使用されます。

Pub/Sub を使用すると、イベント プロデューサー(パブリッシャー)とコンシューマー(サブスクライバー)のシステムを作成できます。パブリッシャーは、同期リモート プロシージャ コール(RPC)ではなく、イベントをブロードキャストすることによってサブスクライバーと非同期に通信します。

パブリッシャーは、イベントが処理される方法やタイミングとは無関係に、Pub/Sub サービスにイベントを送信します。その後、Pub/Sub によって、イベントに反応するすべてのサービスにイベントが配信されます。RPC を介して通信するシステムでは、パブリッシャーはサブスクライバーがデータを受信するのを待つ必要があります。ただし、Pub/Sub で非同期統合を行うと、システム全体の柔軟性と堅牢性が向上します。

Pub/Sub とは  |  Cloud Pub/Sub ドキュメント  |  Google Cloud


ここからはGoogle Cloud Consoleを利用しながら進めていきます。Consoleを開いたらPub/Subを開いてください。
console.cloud.google.com

  1. トピックを作成を選択
  2. トピックIDを入力し、デフォルトのサブスクリプションを追加するを有効の状態で作成
トピックを作成を選択する
トピックを作成

Cloud Functionsの設定

Google Cloud Functionsはサーバーレスのランタイム環境です。Slackへの投稿内容を生成し、Webhook URLsへリクエストを送ります。

Google Cloud Functions は、クラウド サービスの構築と接続に使用するサーバーレスのランタイム環境です。Cloud Functions を使用すると、クラウドのインフラストラクチャやサービスで生じたイベントに関連する、単一目的のシンプルな関数を作成できます。対象のイベントが発生すると、Cloud Functions がトリガーされ、コードがフルマネージドの環境で実行されます。インフラストラクチャをプロビジョニングする必要はなく、サーバーの管理に悩まされることもありません。

Cloud ConsoleからCloud Functionsを開き、以下の操作を行ってください。

  1. ファンクションを作成を選択
  2. 環境は第2世代、関数名に任意も文字列を入力、リージョンをasia-northeast1を選択
  3. トリガーのタイプをCloud Pub/Subに選択し、Cloud Pub/Sub トピックを先ほど作成したトピックを選択
  4. ランタイムを.NET8.0を選択し、コードを記述
  5. デプロイを選択する
ファンクションを作成を選択
ファンクションを作成している様子1
ファンクションを作成している様子2
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using CloudNative.CloudEvents;
using Google.Cloud.Functions.Framework;
using Google.Events.Protobuf.Cloud.PubSub.V1;
using Microsoft.Extensions.Logging;
using System.Threading;
using System.Threading.Tasks;


namespace HelloPubSub
{
    public class Function : ICloudEventFunction<MessagePublishedData>
    {
        private const string WebHookUrl =
            "https://hooks.slack.com/services/---------";

        private readonly ILogger _logger;
        private readonly HttpClient _httpClient;

        public Function(ILogger<Function> logger)
        {
            _logger = logger;
            _httpClient = new HttpClient();
        } 

        public async Task HandleAsync(CloudEvent cloudEvent, MessagePublishedData data,
            CancellationToken cancellationToken)
        {
            // リクエスト内容の生成
            var payload = new Payload { Text = "Cloud Functionsから投稿しています。" };
            var json = JsonSerializer.Serialize(payload);
            var content = new StringContent(json, Encoding.UTF8, "application/json");
            
            // リクエストを送る
            var result = await _httpClient.PostAsync(WebHookUrl, content, cancellationToken);
            
            // MessageTemplateを用いてログに結果を出力
            _logger.LogInformation("{result}", result);
        }

        public class Payload
        {
            [JsonPropertyName("text")] public string Text { get; set; }
        }
    }
}

一つ注意点としてエントリポイントを作成時に記述できる(例. HelloPubSub.FunctionHelloPubSubというnamespaceFunctionというクラス名)のですが、これが一致していないとエラーになるので注意してください。

Cloud Schedulerの設定

Cloud Schedulerはフルマネージド cron ジョブ スケジューラです。一定間隔でCloud Pub/Subにイベントを送信します。

Cloud Scheduler は、エンタープライズ クラスのフルマネージド cron ジョブ スケジューラです。バッチ処理、ビッグデータ ジョブ、クラウド インフラストラクチャ オペレーションなど、実質的にほぼすべてのジョブをスケジューリングできます。

Cloud Scheduler  |  Google Cloud

Cloud ConsoleからCloud Schedulerを開き、以下の操作を行ってください。

  1. ジョブを作成を選択
  2. 名前リージョン頻度タイムゾーンを入力
  3. ターゲットタイプをPub/Subに設定、Cloud Pub/Sub トピックに作成したトピックを選択、メッセージ本文に任意の文字列を入力

頻度の入力にはunix-cron形式で指定する必要があります。

|------------------------------- Minute (0-59)
|     |------------------------- Hour (0-23)
|     |     |------------------- Day of the month (1-31)
|     |     |     |------------- Month (1-12; or JAN to DEC)
|     |     |     |     |------- Day of the week (0-6; or SUN to SAT; or 7 for Sunday)
|     |     |     |     |
|     |     |     |     |
*     *     *     *     *

cron ジョブの形式とタイムゾーン  |  Cloud Scheduler のドキュメント  |  Google Cloud

ジョブを作成を選択
ジョブを作成1
ジョブを作成2

動作確認

指定時間になる(めんどくさい場合はGoogle Schedulerから手動で強制実行させることができます)と、Slackにメッセージが送られてくるはずです。

Slackに送られてきたメッセージ