Skip to main content
舞台裏
舞台裏EngineeringDecisions

2,000 以上の Discord サーバーで Bot を運用して学んだこと

コードを書いているときに想定するのとは、規模が大きくなると違う動きをする4つのこと。

公開日 著者: AlphaCloud5 分で読めます

3つのサーバーで動く Discord Bot と、2,000以上のサーバーで動く同じ Bot は、同じプログラムが大きくなっただけのものではありません。小規模ではまったく無害ないくつかの前提が、ある規模を超えると、まさに最も見つけにくいバグになります。

ここでは、実際の障害につながった4つを紹介します。

1. 障害は均等には広がらず、隠れる

AlphaCloud は、シャードと呼ばれる複数のプロセスに分かれて動いています。どのサーバーがどのシャードに入るかは Discord が決め、各シャードは自分のサーバーしか知りません。

そこから、外から見るとランダムに見える種類の障害が生まれます。あるサーバーでは歓迎メッセージが届くのに、別のサーバーでは届かない。ログにエラーはなく、アラートもなく、何もありません。原因は、タイムアウトのない1つのネットワーク呼び出しでした。相手が接続を受け入れたあとで黙ってしまうと、コードはプロセスが終わるまで待ち続けます。その後に続く処理は一切実行されず、エラーが投げられないので、何もエラーを報告しません。

教訓は地味で、どこにでも当てはまります。外に出ていく呼び出しには、すべて上限が必要です。永遠に待ち続ける呼び出しは、失敗する呼び出しよりも悪いのです。失敗なら、少なくとも目に見えるからです。

2. 再起動は修正ではなく、期限である

原因が分からない間、影響を受けたシャードを再起動すれば確実に直りました。まさにそれが再起動の問題です。再起動は効きます。そして、それによって原因を探す動機がなくなってしまうのです。

今では「再起動で直るか」を、対処ではなく診断として扱っています。直るなら、壊れた状態はメモリの中にあり、コードのどこかに、その状態を作り上げては決して片付けない場所があるということです。

その逆も成り立ちます。再起動を越えて残らなければならないものは、すべてデータベースに入れるべきです。複数の段階からなる処理、たとえば何千人ものメンバーにまたがるロールの変更が進行中で、その途中でプロセスが落ちた場合、その処理がただ消えてしまってはいけません。次の起動時に検出され、続きから実行されなければなりません。

3. Discord の制限は、プロセスごとではなく Bot ごと

Discord は、Bot が1秒間に送れるリクエスト数を制限しています。すぐに思いつく前提は、プロセスを増やせば処理量も増える、というものです。間違いです。制限がかかるのはプロセスではなく Bot です。それぞれに満額の予算を持つ3つのシャードは、合計で許容量の3倍になり、Discord は3つすべてを抑制します。

そのため、私たちの各プロセスは、全部でいくつのプロセスがあるかを計算し、自分の取り分だけを使います。当たり前に聞こえますが、当たり前ではありませんでした。個々のプロセスは単体で見ればまったく行儀よく見えていたので、このバグは長い間見えないままでした。

関連する落とし穴もあります。定期的なジョブは、たとえば5分ごとといった固定の間隔で動きます。すべてのシャードが同時に起動すると、それらのジョブはずっと同じ瞬間に実行されることになります。それ以来、各プロセスは起動時にランダムなずれを受け取るようにしています。

4. 実際に設定される内容は、予想どおりではない

技術的な部分は半分にすぎません。もう半分はこうです。ほとんどのサーバーにとって、初期設定がそのまま設定になります。初期設定が間違っているモジュールは、設定ページがどれほど良くても、大多数のサーバーで誤った設定のまま使われます。

そこから私たちにとって2つのことが導かれます。1つ目に、初期値には設定そのものよりも多くの検討が必要です。2つ目に、新しいモジュールについて問うべきなのは「ここで何を設定できるか」ではなく、「誰も何も設定しないとき、このモジュールは何をするのか、そしてそれは普通のサーバーにとって正しいのか」です。

これは、一見正反対に聞こえるある判断の理由でもあります。v1.8.0 以降、Bot が送るほぼすべてのメッセージは自由にデザインできます。ただし、警告 DM に書かれる理由や、チケットパネルのカテゴリーメニューのような必須ブロックは、移動はできても削除はできません。デザインの自由は認めます。ただし、動いているように見えて実際には動かないものを、サーバーがうっかり作ってしまうところまでは認めません。

共通点

4つのうち3つは、同じ考えが違う衣装をまとったものです。この規模では、静かな失敗は騒がしい失敗よりも高くつきます。クラッシュは報告され、修正されます。何もしなくなっただけの機能は、何か月もそのままになることがあり、わざわざ書いてくれた誰かのバグ報告で初めて知ることになります。

だから今、新しいコードについて最初に問うのは「これは動くか」ではありません。「動かないとき、それはどう見えるのか。そして私たちはそれに気づけるのか」です。

その他の記事