1K Views
March 28, 24
スライド概要
Azure サーバーレスでLINE Botを進化させるハンズオン【BOT AWARDS 2024】のハンズオン補足説明資料です。
https://linedevelopercommunity.connpass.com/event/313077/
C#やAzureなどMS関連技術とLINE関連技術が好きです。
Azure サーバーレスで LINE Botを進化させるハンズオン 【BOT AWARDS 2024】関連イベント 2024/3/28 平林 拓将(ひらりん) himarin269 / himanago
LINE Bot C# Azure Functions ハンズオン ✓GitHub Codespaces で開くだけで、LINE Bot 開発 に活かせる Azure の便利な機能を体験できます。 https://github.com/himanago/line-bot-csharp-azure-functions-handson-blob-cosmos-tricks
体験できる内容 ① LINE Bot C# Azure Functions Starter による 高速環境構築 ② Azure Cosmos DB+Azure Functionsで実現する 安全なメッセージ配信機能 ③ Durable Functions(Durable Entity)を使って "返信までに時間がかかる処理"を効果的にさばくアイ ディア ④ Azure Blob Storage の SAS トークンでセキュアに 画像を送る
① LINE Bot C# Azure Functions Starter による高速環境構築 ✓GitHub Codespaces で開く • リポジトリの Use this template > Open in a codespace から開けます。
① LINE Bot C# Azure Functions Starter による高速環境構築 ✓準備完了するまで待つ • Codespace の画面が表示されたあと、 いくつかのコマンドが実行されます。 • openapi-generator-cli により LINE OpenAPI の 定義から SDK を sdk フォルダに生成するので、 出来上がりを待ちます。 • 待っている間に、次を進めます。
① LINE Bot C# Azure Functions Starter による高速環境構築
① LINE Bot C# Azure Functions Starter による高速環境構築 SDKを生成しています
① LINE Bot C# Azure Functions Starter による高速環境構築 ✓LINE Messagng API チャネルの作成 • LINE Developers のド キュメント、Messaging APIを始めよう を参考に、 Messaging API チャネル を作成します。
① LINE Bot C# Azure Functions Starter による高速環境構築 ✓Azure Developer CLI のログイン • ターミナルで以下のコマンドを実行し、azd で Azure にロ グインします。 • azd auth login --use-device-code
① LINE Bot C# Azure Functions Starter による高速環境構築 ✓ Azure Developer CLI によるリソースの作成とデプロイ • azure.yaml ファイルを右クリックし、Azure Developer CLI (azd) > Package, Provision and Deploy (up) を選択します。 • または、ターミナルで以下のコマンドを実行します。 • azd up
① LINE Bot C# Azure Functions Starter による高速環境構築 ✓続き • ターミナルでサブスクリプションとリージョンを選んでください。
① LINE Bot C# Azure Functions Starter による高速環境構築 ✓続き • LINE Messaging API との接続のために、チャネルアクセストークン を入力するように言われるので、先ほど作成した LINE Messaging API チャネルのチャネルアクセストークンをコピーしてきて、貼り付 けてください。 • リソースの作成とコードのデプロイが開始するので、完了するまで待 ちます。
① LINE Bot C# Azure Functions Starter による高速環境構築 ✓この URL から、Azure ポータルでも デプロイの進捗状況が確認できます。 • もし失敗したら、もう一度 azd up を実行してください。 (作成に失敗したリソースを削除してから実行すると無難)
補足:Azure Developer CLI (azd) について ✓アプリケーションをローカル開発環境から Azure に移動させ るのにかかる時間を短縮するオープンソースのツール • https://learn.microsoft.com/ja-jp/azure/developer/azuredeveloper-cli/overview ✓Bicep を使い、Azure リソースの展開をコードで管理 ✓「awesome-azd」で豊富なサンプルが公開されており、 すぐに展開して動作確認可能 • https://azure.github.io/awesome-azd/
① LINE Bot C# Azure Functions Starter による高速環境構築 ✓LINE Bot の Webhook URL の設定 • デプロイが完了したら、Azure Functions の WebhookEndpoint 関数 の URL をコピーして LINE Messaging API チャネルの Webhook URL に設定します。
① LINE Bot C# Azure Functions Starter による高速環境構築 ✓Webhook URL 入力後に検証を行い、「Webhookの利用もオ ンにします。」 ✓このとき、あわせて LINE 公式アカウントの設定で 応答メッセージをオフに しておいてください。
① LINE Bot C# Azure Functions Starter による高速環境構築 ✓オウム返しの動作確認と Bot の実装 • Messaging API の管理画面の QR コードを読み取っ て Bot を LINE に友だち追加して、テキストメッ セージを送ってください。 • オウム返しで同じ内容を返信してくれたら成功です。 • コードの中身も確認してみましょう。
② Azure Cosmos DB+Azure Functionsで実現する 安全なメッセージ配信機能 ✓Functions のリソースを Azure ポータルで開きます。 ✓CosmosTrigger 関数の「モニター」を開き、 「ログ」タブを選択しておきます。
② Azure Cosmos DB+Azure Functionsで実現する 安全なメッセージ配信機能 ✓次に別のブラウザタブで Cosmos DB のリソースを Azure ポータルから開き、メニューの「データエクスプローラー」を 開きます。 ✓messagedb にある messages コンテナーの Items を開き、 「New Item」をクリックします。
② Azure Cosmos DB+Azure Functionsで実現する 安全なメッセージ配信機能 ✓登録するデータを編集するエディターが開くので、 そこに { "text": "送信したいメッセージ" } と入力してください。 • 送信したいメッセージ は 好きなメッセージを 入れてください。
② Azure Cosmos DB+Azure Functionsで実現する 安全なメッセージ配信機能 ✓LINE Bot の友だち全員にそのメッセージが送信 されます。 • 内部的にわざと 50 % の確率でエラーが出るように しているのですが、Azure Functions のリトライ機 能によって自動で再実行されます。モニターに表示 されるログを確認してみてください。 • エラーの出方やリトライの様子を確認するために、 Cosmos DB にデータをさらに追加することで何度 か繰り返し試してみてください。
② Azure Cosmos DB+Azure Functionsで実現する 安全なメッセージ配信機能
補足:LINE Botのメッセージ配信機能 たとえば… • 友だち全員にブロードキャスト • 一部の友だちにマルチキャスト/ナローキャスト • 特定の友だちにプッシュ
Messaging APIでできる ※オーディエンス関連 API も使用できる https://developers.line.biz/ja/docs/messaging-api/sending-messages/
Cosmos DB & Functions が相性抜群 Cosmos DB&Functions LINE Platform Bot Messaging API
Azure Cosmos DB の特徴 ✓マルチモデル/マルチ API なNoSQLデータベース • コア(SQL), MongoDB, Cassandra, Azure Table, Gremlin から選択 • 基本はドキュメント型のコア(SQL) ✓Free Tier(無期限無料枠)あり • サブスクリプションあたり1アカウントに適用可能 • 1000RU/秒・25GBが無料 ✓Change Feed による連携 今回注目するのはこれ!
Change Feed(変更フィード) • データの変更があった場合にFunctionをトリガー • 追加・変更に対応(順序保証あり) ★ Azure Cosmos DB の変更フィードの設計パターン https://docs.microsoft.com/ja-jp/azure/cosmos-db/change-feed-design-patterns
連携先は Azure Functions ✓サーバーレスなコード実行環境 • さまざまな言語に対応 ✓豊富なトリガー・入出力バインディングで実装が楽々 • 他のAzureサービスとの連携もコード記述量を削減できる • HTTPトリガーが単体で動くため LINE Bot のバックエンド に適している • Change Feed で呼び出せる(Cosmos DB トリガー) 今回使うのはこれ
Cosmos DB × Functions × Messaging API <構成イメージ> Bot データ 登録 Change Feed メッセージ 配信 DBに登録した内容をもとにして メッセージを配信システムを構築!
Cosmos DB を用いるメリット ✓Change Feed で構成がシンプルに • イベントドリブンに実装できる • コード実装量を大幅に削減できる ✓データの書き込みと読み込みの処理を分離できる • コマンド・クエリ責任分離パターン(CQRS) ✓ドキュメント型のため Messaging API で送信する メッセージの JSON をそのまま格納できる • 好きな形式のメッセージJSONをDBに登録すれば それが送られるという仕組みにできる ✓DB登録内容がそのままメッセージ送信履歴になる
Cosmos DB × Functions の落とし穴 もしMessaging APIのサーバーが落ちていたら? ✓API 呼び出しに失敗し関数の処理がそこで止まる ✓Change Feedは実行されたことになる • そのままでは再実行できない • メッセージがロストしてしまう ✓失敗したら再送信…を手作りしてもいいけど…
Azure Functions の再試行ポリシー ✓正常に実行されるまでor最大回数まで再実行す る ✓再試行間隔は2種類から選べる 固定間隔 エクスポネンシャル バックオフ 指定した時間が経過するたびに再試行 再試行間隔が施行のたび指数関数的に増えていく (負荷軽減につながる) ★ ドキュメント https://docs.microsoft.com/ja-jp/azure/azure-functions/functions-bindings-error-pages
実は本当に送信失敗したのか判断できない タイムアウトしたように見えるが、 リクエストは正常に飛んでいて ユーザーへの送信は行われていることがある 送信できているのにリトライしてしまえば、 同じメッセージがユーザーに 2度送られてしまうことに…
Messaging API の「リトライキー」 ✓プッシュ系の API で安全にリトライできるよう にするための方法が提供されている • 比較的最近の新機能(2020年5月) ✓リクエストヘッダーに「X-Line-Retry-Key」 として16進表記のUUIDをセット • 同じUUIDのリクエストを再送信とみなしてくれる • すでに送信成功していればユーザーに送信されない https://developers.line.biz/ja/docs/messaging-api/retrying-api-request/
通常のリトライ このとき送信が成功したことを アプリ側で知ることができない https://developers.line.biz/ja/docs/messaging-api/retrying-api-request/
安全なリトライ方法 同一のリトライキーで送った メッセージはまだ送信成功 していないときのみ送信される! https://developers.line.biz/ja/docs/messaging-api/retrying-api-request/
エクスポネンシャルバックオフ Azure Functionsの再試行ポリシーで選択できる! 固定間隔 指定した時間が経過するたびに再試行 エクスポネンシャル バックオフ 再試行間隔が施行のたび指数関数的に増えていく (負荷軽減につながる) https://developers.line.biz/ja/docs/messaging-api/retrying-api-request/
③ Durable Functions(Durable Entity)を使って"返信までに時間がかかる処理"を効果的 にさばくアイディア + ④ Azure Blob Storage の SAS トークンでセキュアに画像を送る ✓WebhookEndpoint のコードを確認すると、「○○の画像を 送って」というメッセージにのみ、反応する分岐が用意されて います。 ✓Functions のリソースを Azure ポータルで開き、 WebhookEndpoint 関数の「モニター」を開き、 「ログ」タブを選択しておきます。
③ Durable Functions(Durable Entity)を使って"返信までに時間がかかる処理"を効果的 にさばくアイディア + ④ Azure Blob Storage の SAS トークンでセキュアに画像を送る ✓たとえば「鳥の画像を送って」と LINE から送ると、 のようなログが出力されます。 • Bot は返信をしません。
③ Durable Functions(Durable Entity)を使って"返信までに時間がかかる処理"を効果的 にさばくアイディア + ④ Azure Blob Storage の SAS トークンでセキュアに画像を送る ✓その状態で LINE でさらに任意のメッセージを 送ると、「準備中だよ。ちょっとまってね。」と 返信が返ってきます。 ✓このとき、実は裏でリプライトークンがリレー され、常に最新のトークンがエンティティ関数に 保持されるようになっています。
③ Durable Functions(Durable Entity)を使って"返信までに時間がかかる処理"を効果的 にさばくアイディア + ④ Azure Blob Storage の SAS トークンでセキュアに画像を送る ✓次に、Blob Storage のリソースを Azure ポータルで開き、 「コンテナー」で新しいコンテナーを images という名前で作 成してください。
③ Durable Functions(Durable Entity)を使って"返信までに時間がかかる処理"を効果的 にさばくアイディア + ④ Azure Blob Storage の SAS トークンでセキュアに画像を送る ✓これを開き、アップロードから画像をアップロードしていきま す。 • 画像は拡張子が jpg または png のものを用意し、 ファイル名を LINEユーザーID_任意の名前.png のようにしてくださ い。 • LINE ユーザー ID は、ログ出力されたものを使います。 (例:U7298s71491b0e24f4a106res215e19_tori.png)
③ Durable Functions(Durable Entity)を使って"返信までに時間がかかる処理"を効果的 にさばくアイディア + ④ Azure Blob Storage の SAS トークンでセキュアに画像を送る ✓アップロードが完了すると、LINE にその画像が届きます。こ れはエンティティ関数に保持されていた最後のリプライトーク ンを使って送信されています。 • BlobTrigger では SAS トークンつきの URL でこの送信処理を 行っています。 • その URL を含んだメッセージオブジェクトがログ出力するように しているので、BlobTrigger のモニターで確認してみてください。 • その後はまた任意のメッセージに対してオウム返しが動くようにな ります。 ✓コードの流れも追ってみてください。
エンティティ関数(Durable Entities) ✓Durable Functions の機能(2.0~) ✓サーバーレスな関数でありながら、一意なIDを 持って単独で状態を保持できる
補足:SAS でセキュアに運用する ✓SAS(Shared Access Signatures)で Azure Storage のへ のアクセス制限をかける • リクエストの有効性を確認する「SAS トークン」をBlob単位・アクセ ス単位で生成し、URL に付与して使う • Blob コンテナーのパブリックアクセスレベルが「プライベート」に なっていても SAS トークンがあればアクセス可 ★ ブログ:Azure Blob Storage の SAS トークンを使って LINE Bot でセキュアに画像を送る https://himanago.hatenablog.com/entry/2020/11/09/103926 ★ ドキュメント https://docs.microsoft.com/ja-jp/azure/storage/common/storage-sas-overview