discord.jsのシャーディングの仕組みがイマイチ分かりにくかったので、自身の備忘録も兼ねてまとめたいと思う。
ちなみに、公式のガイドのほうの解説はこちらにある。
シャーディングの方法
discord.jsではShardingManagerを用いてシャードを一元管理できる。
シャーディング用のソースコード上でShardingManagerのインスタンスを作成。
その際、BOT本体が記述されているソースコードファイルを指定することで、それを元に各シャードを初期化できる。
注意しなければならないのは、そのBOT本体が記述されているソースコード単体で実行しても動作するように設計しておかなければならないということだ。
公式ガイドではShardingManagerのインスタンスを作成する際にBOTのトークンを渡しているが、あらかじめ環境変数にDISCORD_TOKEN
としてトークンを登録しておけば、自動的にトークンが渡されるようになっている。
シャーディングの仕組み
discord.jsのShardingManagerでは各シャードを子プロセス(デフォルト)かワーカースレッドとして実行されるようになっている。
この際、BOT本体が記述されたソースコード側で特にシャードIDやシャード数に関する値を指定する必要が無いため、不思議に感じると思う。
これはShardingManagerのインスタンスが作成された際にNode.js側の環境変数(要するにprocess.env
)に以下のような値が与えられているからだ。
SHARDING_MANAGER // シャーディングマネージャを使用していることを示す
SHARDS // シャードID(何番目のシャードか)
SHARD_COUNT // シャードの総数
DISCORD_TOKEN // BOTのトークン(ShardingManagerで改めて指定すると上書きされる)
Clientのインスタンスを作成する際、これらの環境変数が参照されるためBOT本体を記述しているソースコード側ではClientのオプションとしてシャーディング周りの値を指定する必要が無くなっている。
ただし、それ以外のオプション値(partials
やws
など)は指定する必要があるので、注意が必要だ。
また、ShardingManagerのインスタンスを作成する際に、totalShards
オプションを与えずとも、spawn()
メソッドを実行した時点でtotalShards
プロパティの値が上書きされるため、例えばshardCreate
イベント内でtotalShards
プロパティの値を参照したとしても、問題なく値を得られる。
参考リンク
/discord.js/src/sharding/ShardingManager.js#L138
/discord.js/src/sharding/Shard.js#L55
/discord.js/src/client/Client.js#L47
あとがき
走り書きに近い備忘録ゆえに内容は推敲されていませんが、未来の自分を含め、参考になれば幸いです。