目の前に、実在するツールがある
このサイトには 住宅ローン計算ツール があります。借入額・金利・返済期間を入れると、毎月の返済額や返済表を計算して返してくれる、ごく普通のツールに見えます。
ですがこのツール、実は入力を送るたびに fetch() でページを取りに行っているわけではありません。
裏側では WebSocket接続を張り、
さらにその奥でメッセージキューを経由して計算しています。
返済表の計算くらい、その場ですぐ返せばいいのでは? —— この記事は、その素朴な疑問に答えるところから始めます。答えは、このツールを動かしている ConoHa の 2GB RAM / 3コアという小さなサーバーの事情に隠れています。
素朴に書くと、どこで壊れるか
いちばん素直な実装は「リクエストが来たら、その場で計算して返す」です。平常時はこれで何の問題もありません。 問題が牙をむくのは、次の3つの条件が同時に揃ったときだけです。
壊れる3条件
① 処理が重い — LLMの推論、大規模モンテカルロ、長期ローンの返済表生成。
1件でCPUとメモリをがっつり使う処理。
② 同時アクセスが起こりうる — 公開ツールである以上、複数人が同じ瞬間に「計算」を押す可能性は常にある。
③ サーバーが非力 — ここが本丸。潤沢なクラウドではなく、2GB RAM の小さなVPSで動かしている。
つまり「同時に3人がノックしてきたら、3つの重い処理が一斉に立ち上がってメモリを食い尽くす」。 これが直接処理の限界です。下のシミュレーターで、まさにこの瞬間を再現してみます。
並べて、順番に
解決策はシンプルです。リクエストを直接処理係に渡さず、いったん「受付箱」に入れる。 処理係は、その箱から1つずつ取り出して片付ける。郵便受けとよく似ています。
こうすると、たとえ同じ瞬間に10件が殺到しても、実際に走る処理は常に1つ。 メモリを食い潰す同時起動が起きません。ピークがならされて、サーバーは常に「1件分」の負荷で回り続けます。
この受付箱を専門に担うミドルウェアが RabbitMQ です。登場人物は3人だけ。
Producer(入れる人)— リクエストをキューに投げ込む。ここでは WebSocket サーバー。
Queue(箱)— リクエストが順番待ちで並ぶ場所。
Consumer(取り出す人)— 箱から1件取り出し、重い処理を実行して結果を返す。
直接処理 vs キュー経由
理屈より、動かすのが早い。左右でまったく同じリクエストを、直接処理とキュー経由でさばきます。 「同時リクエスト数」と「1処理の重さ」を上げていくと、どこで直接処理が崩壊するかが見えます。
軽い処理・少人数なら、直接処理(並列)のほうが速く終わります。当然です。 ですが重さと同時数を上げていくと、直接処理のメモリメーターが限界線を越え、 スワップに落ちて全処理が一斉に失速します。総処理時間は逆転し、キュー経由のほうが速く、しかも安定します。
prefetch_count=1 という選択
シミュレーターのキュー側は「一度に1件だけ」処理していました。RabbitMQ でこれを指示するのが
prefetch_count=1 の一行です。Consumer が「未処理の1件を片付けるまで、次を受け取らない」という設定です。
# consumer 側:一度に1メッセージだけ受け取る await channel.set_qos(prefetch_count=1)
「並列数を増やせばもっと速いのでは?」——2GB VPS では逆です。並列数を増やすほど、 §3で見たメモリ枯渇に近づきます。詰まって全部落ちるより、順番に確実に返すほうが速い。 これは体感の総処理時間の話であり、シミュレーターがまさに示していたことです。
同じ発想が、計算にもAIにも効く
この「並べて順番に」というパターンは、まったく毛色の違う2つの場面で、同じように効いています。
iseeit.jp の住宅ローン計算 — WebSocket で計算サーバーに繋ぎ、返済表の生成をキュー経由で捌く。
金利変更ルールを含む長期返済のシミュレーションは、地味に重い処理です。
sasagawa.tokyo の AIコンシェルジュ — LLM の推論という、桁違いに重い処理をキューで直列化する。
CPU推論のLLMは1件でRAMを大きく占有するため、直列化は必須でした。
金融計算とAI推論という、一見無関係な2つが、 「非力なサーバーで、止めずに、確実に返す」という同じ制約から、同じ設計に行き着いた。 これが Finance × ICT というこのサイトの一つの縮図です。
この記事のまとめ
- 重い・同時・非力の3条件が揃うと、直接処理はメモリ枯渇で崩壊する。
- キューは殺到したリクエストを並べ、実際に走る処理を1件に絞ってピークをならす。
- 非力なVPSでは
prefetch_count=1の直列処理が、共倒れの並列より結果的に速く・安定する。 - RabbitMQ の登場人物は Producer / Queue / Consumer の3人だけ。