Discord Botのホスト先
Discord Bot楽しいですよね。
というわけで色々動かしておきたいわけですが、実際どこにホスティングするかは結構悩みどころです。
完全無料でやりたい場合によくやられているのはGlitchやHerokuだと思いますが、Glitchは定期的に叩き続けるHackが必要になるのでちょっとトリッキー、Herokuは無料プランが廃止となるために移行が必要となっています。
というわけで、もうちょいシンプルな方法として、Google Application Engine(GAE)の無料枠内でなんとかする方法を考えましょう。
なお、Discord.jsを前提に書いていますが、他のフレームワークでも基本的な考え方は同じだと思います。
GAEの無料枠を使う上での制限
GAEの無料枠は一日あたり28時間、なのでずっと動かしていても原理的には問題ありません。ただしこの28時間にはいくつかの制限があります。
1. 無料枠が大きいインスタンスではスケーリングが勝手に行われる
無料枠が大きいのは'F'インスタンス(おそらくフロントエンドインスタンス)のみです。
これは一体何かというと、以下の表の通りで 自動スケーリングのみが有効 なインスタンスとなります。
出典: https://cloud.google.com/appengine/docs/standard#instance_classes
自動スケーリングとは何かというと、主に以下の2つの制限になります。
- アクセスが少ない場合にインスタンスがシャットダウンされる
- 勝手にインスタンスが入れ替わる
2. フロントエンドがないとそもそも立ち上がってくれない
GAEはいわゆるPaaSで、Webサイトをホスティングするものというのがユースケースです。したがって、アプリケーションが正常に立ち上がっているかどうかの確認の一つに、アプリケーションルートが正常に立ち上がっている(アクセスに対し200番を返す)というのが必要になります。
それぞれの制限の回避方法
1. 無料枠でもスケーリングをある程度制御する
無料枠でのスケーリングは基本的には自動スケーリングのみですが、その自動スケーリングに対してある程度の制限をかけることは可能となっています。
以下の公式ドキュメントに記載されているように、app.yaml
設定ファイル内に automatic_scaling
の設定を記述することで、オートスケール時の動作をカスタマイズできます。
その中でも重要なのが min_instances
で、これを指定すると実行されるインスタンス数がこの数を下回りません。つまり、常に 最低一つは起動 していることが保証されます。
ただし、ドキュメントの以下の記載のように、この設定を有効にするにはウォームアップリクエストのハンドリングが必要です。
警告: この機能を適正に機能させるには、ウォームアップ リクエストが有効であることを確認する必要があります。また、アプリケーションでウォームアップ リクエストが処理されることも確認する必要があります。
これについてですが、単に常時起動しておきたいだけならあんまり難しいこと考える必要はなく、以下の記事にあるように /_ah/warmup
にサービスを構えておけば問題はありません。
2. フロントエンドをダミーで構える
次にフロントエンドを構えるという点ですが、こちらも要はルートのリクエストに何らかの正常レスポンスを返すようにダミーを構えてやればいいわけです。例えばExpressとかだと以下のように書いておけば問題ありません。
const app = express();
app.get('/', (_req, res) => {
res.send('🤖Bot is running!!🤖');
});
ちょっと厄介な問題
というわけで、比較的簡単にGAEでの無料ホスティングは実現できるのですが、ちょっと厄介な問題が一つ残っており、これは現在の対応(と最後に公開している実装例)では解消できていません。
GAEのF系インスタンスの場合、インスタンスが入れ替わるわけですが、無停止にするために2台が同時に立ち上がっている時間帯が発生します。このとき、Botの種類によっては問題は発生してしまいます。
一般的なDiscord Botは、最近はSlash Command によって処理を起動する場合が多いと思いますが、この場合は複数インスタンスがいても(同時に応答したとしても)、うまいこと単一の処理しか返さないようになっています。
しかし、Discordのメッセージを常に監視し、特定の文字列があった場合などに処理を実行するようなBotの場合、複数インスタンスがいる時は二重応答になってしまいます。
これを止めるには、なんらかのMutex的なものを実装する必要があります(データストア系のサービスを使えばそんなに難しくはないはずですが、、、)
シンプルな実装例
最後にこの辺の設定を入れたDiscord Botのコードを置いておきます。
基本的には、./app.yaml
と src/createDummyServer.ts
の二箇所にここで書いている設定は入れてあります。
先述したように、多重起動による多重応答問題は放置してあります。
ちなみに、Organization名とかからもわかるように、これはゆる言語学ラジオのサポーターコミュニティ内でちょろちょろと作っているもので(ゆるOSSプロジェクト)、興味ある人はまずはゆる言語学ラジオを聞いてみてください。