ゲームラグ白書
日本語

ゲームラグ
白書

画面がカクつく、キャラクターがワープする、接続が切れるといった現象の原因を、自分のゲーム画面からサーバーのデータベースまで13の層に分けて説明します。原因ごとに確認方法と担当チームを記載しており、実験で条件を変えながら確かめられます。MMOの事例を中心に書いていますが、ほとんどはジャンルを問わずオンラインゲーム全般に当てはまります。

00はじめに

ラグを生む4つの要因

原因は100を超えますが、ラグを生む要因は大きく4つにまとめられます。パケットが遅れて届く、ばらばらの間隔で届く、まったく届かない、そして誰かが計算を止める。ゲームはこれらの要因を隠すためにさまざまな技術を使っていて、隠しきれなかった跡が、私たちが目にするラグの「形」です。

MMOで自分の画面に見えている世界は、サーバーから届いたパケットをもとに描き直した画面です。サーバーはゲームによって異なりますが、通常1秒に10〜30回ゲームの状態を計算し(この1回をティックと呼びます)、その結果のうち各プレイヤーの周囲の変化だけを選んでパケットで送ります。自分のPCは届いたパケットを読んで画面を描きます。つまりラグの大半は、「パケットが時間どおりに届かなかったこと」をゲームがどう見せるかの問題です。

4つの要因に当てはまらないケースもあります。サーバーと自分のPCで同じ処理の計算結果が食い違うと(移動ルールの違い、バグ)、回線が正常でも引き戻しや表示されない現象が起きます。こうしたラグは、Pingに関係なく同じ場所・同じ操作で繰り返し起きることが手がかりです。

要因から症状まで

たとえ

宅配便で考えてみてください。配送にいつも3日かかるなら遅延、1日で届くものもあれば5日かかるものもあるならジッター、荷物が消えたらパケットロス、物流センターが閉まってしまったらストールです。ゲームは「荷物が遅れたり届かなかったりしたら、前後の荷物から推測して埋める(補間・外挿)」「届かなければもう一度送ってもらう(再送)」といった方法でしのぎます。

まずは時間の感覚をそろえる

ラグの話はほとんどがミリ秒(ms、1/1000秒)単位です。下の表の数字をいくつか覚えておくだけで、ゲーム開発チームやインフラチームの話がずっと分かりやすくなります。

基準時間意味

すべての層に共通する待ち行列の性質

CPU、ディスク、データベース、ルーター、通信事業者の回線。層は違っても構造は同じです。リクエストを処理するワーカー(CPUコア、スレッド、DBコネクションなど)があり、その手前にキューができます。ワーカーが空いていればキューは空ですが、忙しさ(利用率)が80〜90%を超えるとキューは急激に長くなります。ワーカー1つにリクエストがランダムに届く場合、平均待ち時間は利用率50%で処理時間と同じ、80%で4倍、90%で9倍になります。「CPUはまだ10%余っているのに、なぜラグるんですか?」の答えがここにあります。しかも監視画面のCPU値はふつう複数コアと1〜5分間を平均した値なので、1つのコアだけが100%になっている状況や、数秒間だけ負荷が集中した瞬間は見えなくなります。

この白書で扱うもの、扱わないもの

ゲーム画面を描く自分のPC・スマホから、家庭内ネットワーク、通信事業者、データセンター、サーバーとデータベースまで、オンラインゲームのプレイ中にラグを生む原因を扱います。ゲーム画面を映像として受け取るクラウドゲーミング、別サービスとして動くボイスチャット、アップデート・ダウンロードの速度は仕組みが異なるため扱いません。ただし、その中のネットワーク側の原因(Wi-Fi、バッファブロート、回線の混雑など)はここにある原因と同じです。

01全体マップ

パケットの経路:入力からサーバーのDBまで

スキルボタンを押すと、その信号は自分のPC、家庭内ネットワーク、通信事業者、データセンターを通ってサーバーに届きます。サーバー内の複数の層で処理された結果は、同じ層を逆にたどって画面に描かれます。全部で13の層があり、どの層で詰まってもラグになります。下のマップで層を押すと、その章に移動します。

02試してみる

ラグ実験室

サーバー1台、回線1本、自分のPC1台でできた小さなシミュレーションです。条件を1つずつ壊しながら、カクつき、ワープ、引き戻し、早送り、スローモーション、入力遅延、フリーズ、切断がそれぞれどうやって生まれるのかを確かめてください。パケットタイムラインは、パケットがいつ送られていつ届いたかを線で示します。線が傾いているほど時間がかかったことを表し、×は消えたパケットです。

03見た目から探す

症状辞典

プレイヤーは「ラグい」としか言いませんが、ラグの形は原因についてかなり多くのことを教えてくれます。各症状の小さな図は、画面内のキャラクターが通った跡です。点が重なっていれば止まったこと、間隔が開いていれば速くなったか位置が飛んだことを表します。

カクつき

動きが滑らかでなく、短く止まっては動くのを繰り返します。 Ping値に問題がなければ自分のPCのフレーム(クライアント・OS)の問題、PingがばらつくならWi-Fi・回線のジッターの可能性が高いです。ただしゲーム内のPing表示はたいていフレームごとに回るゲームループの中で計測しているため、フレームが跳ねるとPingの数値も一緒に跳ねることがあります。

ワープ

キャラクターが途中の移動なしに、離れた位置へ一瞬で移ります。 たいていは、しばらくパケットが途切れたことを意味します。パケットロス、回線の瞬断、サーバーの停止、外挿の失敗を疑います。ほかの人は問題ないのに一人だけワープするなら、まずその人の回線を疑います。

引き戻し

自分のキャラクターが前に進んでいたのに、今通ってきた位置へ引き戻されます。 自分の画面(予測)とサーバーの判定が食い違っています。自分の入力がサーバーに届かなかったか(パケットロス)、サーバーの移動検証に弾かれたか、双方の移動計算が一致していません。

早送り

止まっていた画面が動き出すと同時に、たまっていた動き・ヒット・ダメージが一気に早回しで流れます。 どこかでたまっていたパケットが、一度に解放されました。TCPの再送待ち、サーバーの追いつき処理、クライアントの処理遅れが代表的です。

スローモーション

すべてがゆっくり動きます。スキルの発動やモンスターの移動が間延びして見えます。サーバーの設計によっては、速度はそのままでカクつき・ワープとして現れることもあります。 サーバーがティックを時間内に終えられていません。回線は正常なのでゲームの外で測ったPingは変わらず、ゲーム内のPingはサーバーの処理待ちが含まれていると少し上がることがあります。人数の急増、視界計算、ブロードキャスト、メモリ不足を確認します。

入力遅延

押してから結果が出るまでに時間がかかります。画面そのものは滑らかな場合もあります。 往復時間(Ping)が長いか、どこかでキューが詰まっています。距離、ルーターのキュー、Nagle(小さなパケットをまとめて送るTCPの機能)、サーバーのキューを確認します。Pingが低いのにいつも操作が重いなら、V-Sync・低いFPSのような自分のPC側か、操作のたびにサーバーの確認を待つ設計(同期方式の章)を疑います。

フリーズ

画面内のすべてが少しの間(0.5秒〜数秒)止まってから、また動き出します。 サーバーが丸ごと止まったか(GC、デッドロック、同期呼び出し)、回線が一瞬切れたか、自分のPCが止まりました。

不発・ロールバック

確かにやったはずの行動がなかったことになるか、結果がしばらく経ってから覆ります。 リクエストが消えたか(パケットロス、キューのあふれ)、サーバーが自分の画面とは違う判定をしたか(判定タイミングのずれ、先行演出の後の拒否)、保存の途中で失敗しました(DBのロック・障害、サーバーのクラッシュ)。

切断

プレイ中に接続が切れ、ログイン画面や再接続の画面に戻されます。 タイムアウト時間内にパケットが一つも届きませんでした。長い回線断、アイドルタイムアウト、サーバーのクラッシュ・再起動、タイムアウトより長く止まったサーバーや自分のPC(長いロード)を確認します。案内なしにゲーム自体が終了したなら、接続よりもクライアントの強制終了(クラッシュ、メモリ不足)を先に疑います。

接続不可・無限ロード

ゲームに入れない、またはロード・入場画面で止まったままになります。 新しい接続を受け付ける場所(サーバーの接続待ちキュー、ファイアウォール、ログインサーバー、DB)が満杯になっています。メンテ明けに特に多く起きます。

表示されない・ゴースト

いるはずのNPC・モンスター・プレイヤーが自分の画面にだけいない、またはすでに消えたオブジェクトが自分の画面にだけ残っています。 速度の問題というより、パケットが一つ抜けたか描画に失敗した状態です。チャンネル・フェーズの違い、出現・消滅通知の欠落、ロード中の破棄、アセットのロード失敗を確認します。視界から外れて戻ってきたときに表示されるかどうかが、決定的な手がかりです。

04同期設計

同期方式と体感

Ping 150msでもまったく気にならないゲームもあれば、60msでももっさりするゲームもあります。アクションゲームに限った話ではありません。同じ回線なら、この差はたいていクライアントとサーバーが「何を、いつ、誰が決めるか」の取り決め、つまり同期設計から生まれます。そして、その一部は意図した選択で、一部は本当に作りが悪いものです。

ネットワークゲームはどれも同じ問題を解いています。サーバーと自分のPCの間には必ず時間差があり、どちらかが「まだ確定していないもの」をどう扱うかを決めなければなりません。選択肢は大きく4つです。

  • 待つ:サーバーが確定するまで何も見せない。正確ですが、Pingがそのまま反応速度になります。
  • 先に見せて後で直す:自分の行動はすぐに演出し、サーバーの結果が違えば修正する。速いですが、ときどき引き戻しやキャンセルが見えます。
  • あらかじめ予約しておく:「1.5秒後に叩きつけ」のように未来の時刻と一緒に知らせる。演出時間がPingより長ければ、Pingはまったく見えません。
  • 全員が同じ計算をする:入力だけをやり取りし、それぞれがまったく同じ計算をする(ロックステップ、ロールバック)。送信量は少ないですが、1人の遅延が全員に波及します。

そのため、Pingへの敏感さを大きく左右するのは、ジャンルよりも次の2つの問いです。核となる1つの行動が、サーバーとの往復を何回待つか。そして、ゲームのルールが許す時間が「Ping+人の反応時間」より十分に長いかです。

よく使われる同期方式

方式どう動くかよく使われる場面Ping 150msでの見え方弱点
リクエスト・レスポンス
サーバー確認後に表示
押すとサーバーに問い合わせ、応答が来てから演出する。ターン制・カード・放置系、ショップ・取引・製作のUI、古いMMOのスキル・アイテム使用すべての行動が0.2秒ほど遅れて始まる。ターン制ならほぼ気づかない連続した行動、1画面に往復が何回もあるUI
状態同期+補間
サーバー権威型
サーバーがゲームの状態をティックごとに送り、クライアントは2つの状態の間をつないで描く。ほとんどのMMOでのほかのプレイヤー・モンスターの表示ほかの人は約0.2秒前の姿。ふだんはほとんど気づかないジッター(到着間隔のばらつき)・パケットロス → ワープ、低いティックレート
クライアントサイド予測+サーバー補正自分の入力はすぐに反映し、サーバーの結果が来たら比べて修正する。FPS、アクションMMO、ほとんどのMMOの移動自分の操作は即座に反映。ときどき短い引き戻しサーバーと計算が食い違うと補正が頻発
ラグコンペンセーション
サーバーが巻き戻して判定
サーバーが、攻撃者が見ていた過去の時点に巻き戻して命中を判定する。FPS、ノンターゲットアクション撃った側は公平に感じるが、撃たれた側は「遮蔽物に隠れたのに当たった」撃たれた側の理不尽感。攻撃者のPingが高いほど大きく巻き戻すため悪化
コマンド・目的地の同期「ここへ行け」「この対象を攻撃」のように意図だけを送り、両側がそれぞれ計算する。クリック移動のMMO、タブターゲットの戦闘、一部のMOBA動き出しが少し遅れるだけで、移動と攻撃はなめらか経路・結果が食い違うと補正が必要
イベント予約
サーバー時刻ベース
「サーバー時刻Tに開始」のように未来の時刻と一緒に知らせ、それぞれがその時刻に再生する。レイドボスの攻撃パターン、カットシーン、定時イベント予兆がPingより長ければ事実上影響なし予約した時刻より遅れて届くと、冒頭部分を飛ばす
決定論的ロックステップ全員の入力を集めて、同じターンにまったく同じ計算をする。入力には固定の遅延を付ける。RTS(StarCraft系)、一部の協力・パズルゲームすべての入力が一定に遅れる(押した瞬間の効果音・表示でごまかす)。ジッターが大きいと全員が止まるジッター・パケットロス、最も遅い1人
ロールバック
予測してから巻き戻し
相手の入力を予測して先に進め、外れたら過去に巻き戻して計算し直す。格闘ゲーム(GGPO系)、一部のアクション・スポーツ操作感はほぼ即座(ふつうは1〜3フレームの入力遅延)。相手の動きがときどき数フレーム飛ぶPingが大きいと巻き戻し幅が大きくなり、ワープのように見える
クライアント権威型それぞれが自分の結果を決め、サーバーは中継・記録だけをする。一部のモバイル・カジュアル、P2P・リレー構成自分の画面は快適。ほかの人の画面と結果が食い違うチート、「自分は当てたのに当たっていない」

実際のゲームは、これらの方式を組み合わせて使います。移動は予測、スキルは先行演出の後に確定、ボスの攻撃パターンはイベント予約、取引はリクエスト・レスポンスのように、行動ごとに使い分けるのがふつうです。

Ping 150msでも快適なゲームの共通点

1. 1つの行動に往復が一度も挟まらない。ボタンを押したらアニメーション・効果音・エフェクトをすぐに始め(先行演出)、サーバーの結果はダメージの数字のように遅れても目立たない部分にだけ使います。

2. ゲームのルールが許す時間がPingより十分に長い。ボスの予兆が1〜2秒あれば、パケットが0.2秒ほど遅れて届き、人の反応に0.25秒使っても十分によけられます。自分のスキルに詠唱時間があれば、詠唱バーがたまる間にサーバーの確認も終わるので、待ち時間が詠唱時間の中に隠れます。タブターゲットのMMOがPingに鈍感な最大の理由です。逆に、0.5秒前後の短い予兆は、Pingが150msあるだけで見てからよけるのが難しくなります(下の判定の受付時間の実験)。

3. 連続した行動を先に受け付けておく。クールタイムが終わる前に次のスキルを押しても受け付けておく先行入力(スキルキュー)があれば、連携の間に往復時間が挟まりません。

4. ジッターを吸収する。補間バッファやサーバー時刻ベースの演出は、「たいてい150ms、ときどき250ms」かかって届くパケットを、常に250msほど遅れた一定の流れに変えます。少し過去を見る代わりに、なめらかになります。人は一定の遅れにはすぐに慣れますが、ばらつきにはなかなか慣れません。よくできたゲームは、ジッターの増減に合わせてバッファの長さを自動で伸び縮みさせます。

5. 判定が「自分が見たもの」と一致する。回避・命中をプレイヤーが見た時点を基準に判定するか(ラグコンペンセーション)、そもそも位置が重要でないルール(ターゲット指定)を使います。

6. 1人の遅延がほかの人を待たせない。サーバー権威型の構成では、自分のPingが悪くてもほかの人は問題ありません。ロックステップやホスト型の構成では、最も遅い1人が全員の体感を決めます。

意図した設計と作りの悪い設計を見分ける

Pingに敏感な理由は、意図した設計の場合もあれば、作りが悪いせいの場合もあります。

意図した選択でありうるもの
  • 短い判定の受付時間:パリィ0.2秒、ジャスト回避のように、短い受付時間そのものが面白さになっているゲーム。Pingの分だけ反応できる時間が減り、ジッターがタイミングを乱すのは避けられないため、ラグコンペンセーションや地域ごとのサーバーで影響を小さくします。
  • チート対策のためのサーバー確定:ゲーム内通貨・アイテム・ランキングのように、絶対にごまかされてはいけない結果は、サーバーの確認を待つのが正解です。
  • ロックステップ:数百のユニットを入力だけで同期するなら、最も現実的な構成です。その代わり、入力遅延をPingに合わせて調整します。
  • 公平性:ラグコンペンセーションをわざと弱くして、Pingの高い人のせいで撃たれた側が理不尽な思いをしないようにする選択もあります。
作りが悪い可能性が高いサイン
  • キーボード・パッドで直接動かすゲームなのに、移動や通常攻撃までサーバーの確認を待つ。予測なしで作ると、Pingがそのまま操作感になります。クリック移動のように命令を出す操作は、サーバーの確認を待ってもあまり目立たないため、MOBAなどではあえて選ぶこともあります。
  • UI操作1回に往復が何回も:ウィンドウを開く → 一覧を受け取る → 確認 → 購入がそれぞれ往復なら、Ping 150msで0.7〜0.8秒かかります。1回にまとめられます。
  • 回線のPingは低いのに、常に同じだけもっさりする:Nagleアルゴリズム(小さなパケットをまとめてから送るTCPのデフォルト動作。TCP_NODELAYで無効化)、要求を次のティックまでためて結果も次のティックで送る二重の待ち、行動ごとにDBへの保存が終わるまで応答しない構造を疑います。自分のPCの垂直同期(V-Sync)や低いFPSも同じ感覚を生みます。
  • スキルキューがなく「確認してから次の入力」:連携のたびに往復時間が挟まり、Pingの分だけDPSが下がります。
  • 届いたらすぐ再生:補間バッファやサーバー時刻を使わずに受け取った順に演出すると、ジッターがそのままアニメーションのカクつきになります。

同期設計でラグを生む原因

サーバー応答後にだけ演出(リクエスト・レスポンス方式) Request-response (no client-side feedback)

ボタンを押しても、サーバーの応答が来るまでアニメーションも音も出ません。Pingがそのまま反応速度になります。

なぜ: スキル・移動・アイテム拾いを、サーバーの確認が来てから再生 → すると: 押した瞬間から、往復時間 + ティック待ちの間まったく反応なし → 画面では: Pingが150msなら、すべての行動が0.2秒ずつ遅れてもっさりする

症状: 入力遅延 · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

逐次往復の多いプロトコル(chatty) Chatty protocol / sequential round trips

1回の操作でサーバーとの往復が順番に何回も必要になると、Pingがその回数分だけ積み重なります。

なぜ: ショップを開く → 一覧を要求 → 価格を確認 → 購入 → インベントリ更新を、それぞれ別々にリクエスト → すると: 前のリクエストの応答を受け取ってから次のリクエストを送る → 画面では: Ping 150msで1回の購入に1秒近くかかる。ロードがやけに長い

症状: 入力遅延, 接続不可・無限ロード · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

スキルの先行入力なし No input/spell queue

前のスキルがサーバーで終わったという確認を受けるまで次のスキルを押せないと、連携のたびに往復時間が挟まります。

なぜ: 次のスキル入力を「前のスキルの確定後」にだけ受け付ける → すると: スキルとスキルの間に、毎回Pingの分だけ空白の時間ができる → 画面では: 連携の間に毎回すき間ができ、Pingが高いほどDPSが下がる

症状: 入力遅延, 不発・ロールバック · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

Pingに削られる短い判定の受付時間 Timing window too short for latency + reaction

回避・パリィ・ガードのように反応すべき時間が短いと、Pingがその時間を削ってしまい、よけられない攻撃が生まれます。

なぜ: ボスの攻撃の予兆0.5秒、パリィの判定0.2秒のような短い判定の受付時間 → すると: 予兆を見るのが遅れ(下りの遅延 + 補間)、自分の入力も遅れて届く(上りの遅延 + ティック待ち) → 画面では: 確かによけたのに当たる、パリィが不発になる

症状: 不発・ロールバック, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発, インフラチーム・サーバーインフラ

ラグコンペンセーションのない判定 Server-now hit validation

サーバーが「今のサーバー上の位置」だけで命中を判定すると、自分が見た画面と判定が食い違います。

なぜ: 自分の画面の相手は約0.2秒前の位置(Ping 150ms、補間100msの場合) → すると: サーバーは現在位置で判定するため、自分が狙った場所にはもういない → 画面では: 確かに当てたのに外れる。動く対象には偏差撃ちが必要

症状: 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

過剰なラグコンペンセーション Excessive lag compensation

攻撃者を基準に巻き戻しすぎると、撃たれる側はもう隠れたのに当たります。

なぜ: Pingが高い攻撃者のために、サーバーが大きく巻き戻して判定 → すると: 撃たれる側の画面では、すでに遮蔽物に隠れた後 → 画面では: 「壁の後ろで撃たれた」、Pingが高い人が有利

症状: 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発

クライアント権威型 Client-authoritative results

それぞれが自分の結果を決めると、自分の画面は快適ですが、ほかの人の画面と結果が食い違い、チートにも弱くなります。

なぜ: 位置・命中をクライアントが決め、サーバーは中継するだけ → すると: 2人が互いに自分が先に当てたと主張し、サーバーは検証できない → 画面では: 相手がワープ・壁抜け、「自分は当てたのに当たっていない」

症状: ワープ, 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

ロックステップでの最も遅いプレイヤー待ち Lockstep waits for the slowest peer

全員が同じターンを一緒に計算する構造では、1人の入力が遅れると全員が待たされます。

なぜ: ターンごとに全プレイヤーの入力がそろわないと計算できない → すると: 1人の入力がジッター・パケットロスで遅れて到着 → 画面では: 全員が同時に一瞬止まり、ひどいと「プレイヤーを待っています」ウィンドウ

症状: フリーズ, カクつき, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

ロールバックネットコードの予測失敗 Rollback misprediction

相手の入力を予測して先に見せ、外れたら巻き戻して計算し直します。Pingが大きいほど巻き戻す幅が大きくなります。

なぜ: 相手が入力を変える(予測と違う) → すると: 実際の入力がPingの半分だけ遅れて届き、その分を巻き戻して再計算 → 画面では: 相手の動きが数フレーム飛んだり、急に変わったりする

症状: ワープ · 主担当 ゲーム開発チーム・クライアント開発

タイムスタンプなしの受信即時再生 Events played on arrival (no timestamps)

サーバーのイベントに発生時刻を付けず、受け取ったらすぐに再生すると、ネットワークのジッターがそのまま演出のタイミングのばらつきになります。

なぜ: 「攻撃開始」「エフェクト再生」のイベントを届いた瞬間に実行 → すると: パケットごとに到着時間が違うため、間隔がばらつく → 画面では: 連続攻撃のモーションが速くなったり遅くなったりし、ボスの攻撃パターンのタイミングが毎回違う

症状: カクつき, 早送り · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

二重のティック待ち Double tick quantization

リクエストを次のティックまでためてから処理し、結果もその次のティックで送ると、ティック間隔が2回分加わります。

なぜ: 受け取ったリクエストは次のティックで処理 → すると: 処理結果も次の送信ティックにまとめて送る → 画面では: 回線のPingは低いのに、反応がティック間隔の1.5倍ほど一定に遅れる。10ティックのサーバーなら平均0.15秒、最悪0.2秒

症状: 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発

厳しすぎるサーバー検証 Over-strict server validation

移動速度・クールタイム・射程をサーバーが厳しくチェックしすぎると、ジッターでまとめて届いた正常な入力まで拒否します。

なぜ: 「1ティックで移動できる距離」「クールタイムの許容誤差0ms」のような厳しい基準 → すると: ジッターで2つのコマンドが1ティックにまとめて届くと、ルール違反と判定 → 画面では: 引き戻し、クールタイムが終わったのにスキルが拒否される

症状: 引き戻し, 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発

ホスト(部屋主)型の構成 Listen server / host advantage

1人のプレイヤーのPCがサーバーの役割をすると、その人の回線とPC性能が全員の体感を決めます。

なぜ: ホストのPCがサーバーの役割を担う(P2P、リッスンサーバー) → すると: ホストの回線やPCが遅いと全員に波及、ホスト自身はPing 0 → 画面では: ホストだけが有利、ホストが抜けると全員がフリーズ・切断

症状: カクつき, フリーズ, 切断 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発, インフラチーム・サーバーインフラ

先行演出後のサーバー拒否 Client-side feedback rejected by server

自分の画面で先に見せたヒット・スキルを後からサーバーが認めないと、確かに見た結果がなかったことになります。

なぜ: ヒットエフェクト・スキルモーションをサーバーの確認前に先に再生(先行演出) → すると: サーバーが射程・対象の位置・クールタイム・リソースを改めてチェックして拒否 → 画面では: 血しぶきが出たのにダメージなし、スキルのモーションだけ出て効果なし、クールタイムだけ回る

症状: 不発・ロールバック, 引き戻し · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

コマンド同期の経路計算の不一致 Command sync with divergent pathing

「ここへ行け」だけをやり取りして経路は両側でそれぞれ計算すると、計算が少し違うだけで、キャラクターやモンスターが別の経路を進んだ後、元の位置に引き戻されます。

なぜ: クリック移動・モンスターの追跡で目的地だけを送り、経路はクライアントが別途計算 → すると: 地形データの違い、ほかのキャラクターとの衝突、計算順序の違いで、サーバーと別の経路を移動 → 画面では: モンスターが壁をすり抜けて進んだ後にパッと位置が移る、クリックしたキャラクターが滑るように向きを変える

症状: ワープ, 引き戻し · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

低いスナップショット送信レート Low snapshot / update rate

サーバーが位置の更新(スナップショット)を1秒に数回しか送らないと、その分だけ補間バッファを長く取る必要があり、ほかのキャラクターをより遠い過去の姿で見ることになります。

なぜ: 送信量を節約するため、位置の更新を1秒に5〜10回しか送らない → すると: なめらかに描くにはバッファをパケット間隔の2倍(200〜400ms)取る必要があり、短くするとパケットを1つ落としただけで止まる → 画面では: 相手の方向転換が遅れて見え、判定と食い違う。バッファが短いとカクつき、パケットロス時にはワープ

症状: カクつき, ワープ, 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

05影響範囲

一人だけ重いとき、片方だけおかしいとき

ラグ報告で最も判断に迷うのは、一部の人だけ、または片方だけに症状が出るケースです。重い1人がほかの人の目にどう見えるか、その人のせいでほかの人まで重くなるかは、サーバーが入力を処理する方式と同期方式によってまったく変わります。同じPCで起動した2つのクライアントのうち、片方だけNPCが表示されない現象もこの章で扱います。

特定のユーザー、特定の回線だけが重い場合

最近のMMOのほとんどはサーバー権威型の構造です。サーバーがすべての結果を決め、クライアントは受け取った結果を描画します。この構造では、ラグはほとんどの場合重い本人にしか現れません。

  • 重い本人には、スキル使用やアイテム拾いのようにサーバーの確認が必要な行動が、Ping分だけ遅れる入力遅延が起きます。移動は予測によってすぐ表示されますが、ジッター(到着間隔のばらつき)が大きいと、引き戻しや、ほかの人のワープも起きます。
  • ほかの人には、重い人のキャラクターが一瞬止まってからまとめて動いたり、ワープしたりする様子が見えるだけです。自分の操作やモンスターの動きは正常です。Pingが高いだけでジッターとパケットロスがなければ、少し遅れた位置になめらかに表示されるだけです。他人の目にラグとして映る原因は、Pingよりもジッターとパケットロスです。
  • 特定の通信事業者・地域の回線だけが悪いと、そのユーザーたちに一斉に上の症状が出ます。サーバーから見るとその人たちの入力だけが不規則に届くので、移動検証やチート検知での誤検知もその人たちに集中します。
  • 特定のキャラクターでだけ重いなら、回線よりもそのキャラクターのデータを疑います。アイテムやメールが数千件たまったキャラクターは、ログインや保存のたびにほかのキャラクターの何倍ものデータを読み書きします。同じキャラクターで別のPC・回線から接続しても同じように重いかを確認すれば、切り分けられます。

しかし、重い1人が全員を重くする構造もあります。共通点は「誰かがその人を待っている」ことです。

  • 全員が同じターンを待つ構造:ロックステップ(RTS)、ターンを揃えて進める協力コンテンツ。1人の入力が遅れると全員が止まります。ジッターがなく遅いだけでも、全員の入力が最も遅い人のPing分だけ遅れて反映されます。
  • サーバーが重い人への送信で待たされる構造:ブロッキング送信(送信バッファに空きができるまでブロックして待つ送信)、同期処理。そのサーバースレッドが担当する全員が重くなります。通常は人ごとに送信キューを個別に持ち、待たないようにします。この場合、ラグは重い人にだけ現れ、キューが長くなりすぎるとその人だけが切断されます。
  • 重い人が中心的な役割を持つ構造:その人のPCがホストになるP2P(サーバーを介さずプレイヤー同士が直接つながる方式)・リッスンサーバー(プレイヤーのPCがサーバーを兼ねる方式)、パーティリーダーの権限でしか進まないイベント。サーバー負荷を減らすためにモンスターの移動計算を近くのプレイヤーのクライアントに任せるゲームなら、その人が担当するモンスターが全員の画面でカクつきます。
  • 判定を重い人の基準で巻き戻す構造:ラグコンペンセーション。重い人も公平に当てられますが、撃たれる側は「もう隠れたのに当たった」という理不尽さを味わいます。そのため、巻き戻す幅には上限を設けます。上限はゲームによって異なり、おおよそ0.2秒〜1秒です(Sourceエンジンのデフォルトは1秒)。

サーバーの入力処理方式による見え方の違い

サーバーの入力処理方式重い本人に起きることほかの人から見た重い人ほかの人自身のゲーム
ティックごとにまとめて処理
固定ティック、受け取った入力を一括で
スキルの結果がPingとティック待ちの分だけ遅れる(入力遅延)。移動検証が厳しいと引き戻し一瞬止まってから一度に何歩も進む(早送り・ワープ)。ジッターがなくPingが高いだけならなめらか影響なし
到着次第処理
イベント方式、受け取り次第適用・送信
Ping分の入力遅延。ティックを待たない分だけ速い移動が速くなったり遅くなったりする(軽い早送り)。まとめて届いた複数のスキルが一瞬で実行される影響なし
プレイヤー別の入力バッファ
人ごとにためておき、1ティックに1つずつ
バッファの分だけ確定が遅れる比較的なめらか。バッファが空になると一瞬その場で止まる影響なし
ラグコンペンセーションによる判定
攻撃者が見た時点に巻き戻す
狙ったとおりに当たる(巻き戻しの上限内で)隠れた後でもその人の攻撃が当たる理不尽な被弾(波及)
ロックステップ・ターン待ち入力遅延。入力が遅れるとフリーズ全員が止まるフリーズ。遅れるだけでも入力遅延(全員に波及)
ブロッキング送信・同期処理
サーバーがその人を待つ
フリーズの後に早送りそのサーバースレッドが担当する全員が重くなるスローモーション・フリーズ(そのスレッドが担当する人たちに波及)
重い人がホスト
P2P、リッスンサーバー
本人はPing 0全員の画面がカクつく全員にラグ
モンスターの制御を重い人が担当
モンスターの移動計算をクライアントに任せる
本人の画面のモンスターは正常その人が担当するモンスターが一瞬止まってからワープそのモンスターと戦う全員(波及)

同じPCの2つのクライアントで、片方だけNPCが表示されないとき

同じ人が同じPCでクライアントを2つ起動し、片方だけNPCが表示されないなら、回線はほぼ原因になりません。2つのクライアントは同じルーター、同じ回線を使っているからです。違いは3か所で生まれます。

  1. サーバーがそのクライアントに送らなかった:チャンネル・インスタンス・クエストのフェーズ(進行度によって見えるNPCを分ける機能)の違い、視界への登録順序の不整合、接続ごとの送信量上限、同じPC・同じIPを1人とみなすセッションのバグ、マルチクライアント制限。
  2. 送ったがクライアントが破棄した:ロード中に届いた出現通知の破棄、入場直後に集中した出現情報が受信バッファのあふれや非信頼(unreliable)チャネル(失っても再送しないチャネル)のせいで消失、基準スナップショット(差分だけを送るときに起点となる全体の情報)の消失、IDが再利用された新しいNPCを古いNPCと誤認、固定UDPポートの衝突で別のクライアントが横取り、バックグラウンドのウィンドウで処理が遅れて受信バッファがあふれる、サーバー時刻の推定がずれて表示を先送り。
  3. 受け取ったが描画できなかった:2つのクライアントが同じキャッシュファイルに同時に書き込んでモデルのロードに失敗、グラフィックメモリ(VRAM)不足、表示人数の上限などのオプションの違い、バージョン・データの不一致。

最も有力な手がかりは3つです。名前表示はあるのにキャラクターモデルだけがないか(サーバーは送ったが描画に失敗)、視界から外れて戻ると表示されるか(出現通知が1つ抜けた)、そして表示されない側のウィンドウを前面に出すと改善するか(バックグラウンドウィンドウの処理制限)。逆に、すでに倒されたモンスターが自分の画面にだけ立っている「ゴースト」は、消滅通知が抜けたものです。

一部のユーザーだけに起きる問題

回線が重い人がほかの人の画面でまとめて動く Laggy player seen by others (bursty inputs)

回線が悪い人の入力は、不規則にまとまってサーバーに届きます。サーバーがティックごとに受け取った分だけ適用すると、ほかの人の目にはそのキャラクターが一瞬止まってから一気に何歩も進んで見えます。

なぜ: 回線が重い人の移動コマンドが、あるティックには0個、あるティックには2〜3個ずつ届く → すると: サーバーが受け取ったティックに一度に適用するため、そのキャラクターの位置が階段状に変わる → 画面では: ほかの人の画面でそのキャラクターだけが一瞬止まっては一気にまとめて移動。ほかは問題なし

症状: 早送り, ワープ · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 外部・外部

受信即時処理のサーバーで起きる早送り Event-driven processing of bursty inputs

パケットが届くたびにすぐ処理して通知するサーバーでは、回線が重い人のまとまって届いた行動が立て続けに即実行されます。

なぜ: 回線が重い人のスキル・移動のリクエストがまとまって届く → すると: サーバーが受け取った瞬間に順番に実行し、すぐに全員へ通知 → 画面では: ほかの人の目には、その人がスキルを一瞬で何個も使ったり、早送りのように動いたりする

症状: 早送り · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

プレイヤーごとの入力バッファのサイズ Per-player server input buffer (jitter buffer)

サーバーが人ごとに入力を少しためておき、1ティックに1つずつ取り出して使うと、ほかの人の目にはなめらかですが、本人の行動がサーバーで確定するタイミングはその分遅れます。

なぜ: サーバーが回線の重い人の入力をバッファにため、1ティックに1つずつ適用 → すると: バッファが小さいと頻繁に空になり、そのキャラクターがその場に止まるか、サーバーが最後の入力から推測して動かす。大きいと本人の入力の確定が遅れる → 画面では: 小さいとほかの人の目には一瞬止まって見え、大きいと本人のスキルの結果が遅れて出る(入力遅延)

症状: カクつき, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

特定の通信事業者のユーザーに集中する検証の誤検知 Anti-cheat / movement validation false positives on bad ISPs

ジッターが大きい回線を使う人は入力がまとまって届くため、サーバーの速度・クールタイムのチェックに頻繁に引っかかります。

なぜ: 特定の通信事業者・地域の回線のジッターが夜に大きくなる → すると: まとまって届いた正常な入力を、サーバーが速度超過・クールタイム違反と判断 → 画面では: その通信事業者のユーザーだけ引き戻し、スキル拒否、ひどいとサーバーから追い出されて切断

症状: 引き戻し, 不発・ロールバック, 切断 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・ネットワークインフラ

回線が重いパーティメンバー1人とボスのギミック One laggy member in a synchronized mechanic

全員が決まった瞬間に一緒に反応しなければならないレイドのギミックでは、回線が重い1人の遅れた反応がパーティ全体の失敗になります。

なぜ: 「全員同時に散開」「1人がボタンを押す」のような全員で対処するギミック → すると: 回線が重い人は予兆を見るのが遅れ、入力も遅れて届く → 画面では: その1人のせいで全滅、ほかのパーティメンバーは「ラグい人のせい」と感じる

症状: 不発・ロールバック, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

モンスターの制御権が遅いクライアントにある Monster movement delegated to a player client

サーバー負荷を減らすため、モンスターの移動計算を近くのプレイヤー1人のクライアントに任せるゲームがあります。その人の回線が悪いと、そのモンスターが全員の画面でおかしな動きをします。

なぜ: サーバーがモンスターの移動計算を、最も近い(または先に来た)プレイヤーのクライアントに任せる → すると: 任された人の結果報告が遅れたり、まとまったりしてサーバーに届く → 画面では: そのモンスターだけが周囲全員の画面で一瞬止まってはワープ。任された本人の画面では問題なし

症状: ワープ, カクつき, 早送り · 主担当 ゲーム開発チーム・サーバー開発

特定キャラクターのデータ肥大化 One character with oversized data (inventory, mail, buffs)

アイテム・郵便が数千個たまっていたり、フレンド・ブロックリストやバフが極端に多かったりするキャラクターは、接続時・保存時・周囲への通知で扱う量がほかの人の数倍になります。回線に関係なく、そのキャラクターでだけ重くなります。

なぜ: 長く育てたキャラクターやイベント報酬で、インベントリ・郵便受けに数千個たまる → すると: 接続・エリア移動・保存のたびにその分DBを読み書きし、周囲に送る装備・バフの情報も大きい → 画面では: そのキャラクターだけ入場時のロードが長く、インベントリ・郵便を開くときに一瞬止まる。保存をゲームスレッドで待つサーバーなら、周囲の人まで一時的に止まる

症状: 接続不可・無限ロード, 入力遅延, フリーズ · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ

チャンネル・インスタンス・フェーズの違い Different channel / instance / phase

2つのキャラクターが別のチャンネルやインスタンスにいたり、クエストの進行度によって見えるNPCが変わる別の「フェーズ」にいたりすると、互いに違う世界を見ることになります。

なぜ: 2つ目のキャラクターが別のチャンネルに割り当てられるか、クエストの段階が違う → すると: サーバーがそのキャラクターにはそのNPCを送らない(正常) → 画面では: 片方にだけNPCがいない。バグのように見えるが設計どおり

症状: 表示されない・ゴースト · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

ロード中に届いた出現通知の破棄 Spawn messages dropped before the client is ready

ゾーンに入るとすぐにサーバーが周囲のNPCの出現通知を送りますが、クライアントがまだマップを読み込んでいる最中なので、その通知を破棄してしまいます。

なぜ: サーバーが入場処理の直後に周囲のオブジェクトの出現通知を送信 → すると: クライアントはロード中でメッセージハンドラーがまだないため、通知を破棄 → 画面では: サーバーは送信済みとして扱い、再送しない。視界から外れて戻ってくるまでNPCが表示されない

症状: 表示されない・ゴースト · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

視界登録の順序の乱れ Interest-management race on enter/leave

キャラクターが視界グリッドに登録される瞬間と、NPCがグリッドのセルを移る瞬間が重なると、そのNPCの出現通知が漏れることがあります。

なぜ: 入場・チャンネル移動・テレポートの処理とNPCの移動が同じ瞬間に重なる → すると: 「新たに見えるようになったオブジェクト」の計算からそのNPCが漏れる → 画面では: 特定のNPC数体だけが表示されないか、すでに去ったNPCが残っている

症状: 表示されない・ゴースト · 主担当 ゲーム開発チーム・サーバー開発

基準スナップショットの欠落 Lost baseline for delta compression

サーバーが「前回から変わったものだけ」を送る方式では、最初に1回送る全体の情報(基準)を失うと、その後の差分を適用できません。

なぜ: オブジェクトの全体情報(基準)のパケットが失われるか、処理前に破棄される → すると: クライアントはその後の差分を適用する対象がないため無視 → 画面では: そのオブジェクトが表示されないか、かなり後で突然現れる

症状: 表示されない・ゴースト, ワープ · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

消滅通知の欠落(ゴースト) Missed despawn (ghost entity)

逆に「消えた」という通知を取りこぼすと、すでに死んだか去ったNPC・プレイヤーが自分の画面にだけ残ります。

なぜ: 死亡・退出・視界外への移動の通知が失われるか、順序が入れ替わる → すると: クライアントはそのオブジェクトがまだいると判断 → 画面では: 叩いても反応しないモンスター、すでに抜けたプレイヤーが立っている

症状: 表示されない・ゴースト · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

入場直後に集中する出現情報の欠落 Initial spawn burst lost (unreliable channel, receive buffer, fragmentation)

ゾーンに入った瞬間、サーバーは周囲の数十〜数百個のオブジェクトの出現情報を一気に送ります。これを非信頼(unreliable)チャネルで送ったり、ロード中でソケットを読めない間に受信バッファがあふれたりすると、一部が消えて二度と届きません。

なぜ: 入場直後に出現情報が短時間に集中して届く → すると: ロード中のクライアントがソケットを読むのが遅れてOSの受信バッファがあふれるか、大きなUDPパケットがフラグメント化され、フラグメントを1つ失っただけで丸ごと消える。非信頼チャネルなら再送もされない → 画面では: ロードが遅い側のクライアントでだけNPCが数体抜ける。視界から外れて戻ると見える

症状: 表示されない・ゴースト · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

オブジェクトIDの再利用による混同 Entity ID reused without a generation counter

倒されたNPCが再び出現するときにサーバーが同じオブジェクトIDを使い回すと、その間に消滅通知を取りこぼしたクライアントは、新しいNPCを古いNPCと誤認します。

なぜ: NPCが倒され、同じオブジェクトIDで再出現 → すると: 消滅通知を取りこぼしたクライアントは「すでに知っているオブジェクト」として出現通知を無視するか、死亡状態のまま残す → 画面では: 片方の画面にだけNPCがいないか倒れたまま見える、別のNPCの姿で見えることもある

症状: 表示されない・ゴースト · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

固定UDPポートの衝突 Two clients bound to the same local UDP port

クライアントが決まったローカルポートを使うように作られていると、同じPCの2つ目のクライアントはそのポートを使えないか、1つ目とパケットを分け合って受け取ることになります。

なぜ: 2つのクライアントが同じローカルUDPポートを開こうとする(再利用オプションで無理に共有) → すると: OSが届いたパケットを片方のソケットにだけ渡すか、どちらが受け取るかを保証しない。ルーターとサーバーも2つのクライアントを同じアドレスとみなす → 画面では: 片方はワールドのパケットを受け取れず、NPC・ほかのプレイヤーが表示されないか切断される

症状: 表示されない・ゴースト, 切断, 接続不可・無限ロード · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

IP・端末基準のセッション識別バグ Session keyed by IP or machine ID

サーバーや中継サーバーが接続をIPや端末IDで区別していると、同じPC(同じグローバルIP)の2つのクライアントを1人として認識します。

なぜ: セッションテーブルをIP、またはIP+端末IDで作っている → すると: 2つ目のクライアントの情報が1つ目のセッションに上書きされるか混ざる → 画面では: 片方はNPCが表示されず、もう片方は切断されるかほかの人の情報を受け取る

症状: 表示されない・ゴースト, 切断 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

多重起動の制限 Multi-client restriction policy

セキュリティモジュールやサーバーのポリシーが1台のPCでの複数クライアントを制限していると、2つ目のクライアントは起動・接続ができないか、先に起動した側が切断されます。一部のゲームは追加のクライアントの機能だけを制限します。

なぜ: セキュリティモジュールが多重起動を検知、またはサーバーが同じ端末からの追加接続を制限 → すると: 2つ目の起動・接続を拒否するか、片方を切断。まれに追加のクライアントの一部の機能だけを遮断 → 画面では: 接続不可か片方の切断。機能だけを制限するゲームでは、片方だけNPC・ショップが表示されない

症状: 接続不可・無限ロード, 表示されない・ゴースト, 切断 · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

バックグラウンドウィンドウの処理制限 Background window throttling

バックグラウンドウィンドウのクライアントでは、ゲーム・エンジン・OSがフレームと処理を減らします。受け取ったパケットを時間内に処理できず、詰まったりあふれたりします。

なぜ: ゲームのオプションやグラフィックスドライバーのバックグラウンドのフレーム制限(例:NVIDIAドライバーでは毎秒20〜200の間で指定)、省電力、エンジンのバックグラウンド停止設定。OSも前面のウィンドウ(フォアグラウンド)にCPU・GPUを優先的に割り当てる → すると: フレームごとに処理するパケット数が減ってキューがたまり、受信バッファがあふれると破棄される → 画面では: ウィンドウを前面に出すとまとめて現れるか、一部のNPCが最後まで表示されない

症状: 表示されない・ゴースト, 早送り, 切断 · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 外部・外部

キャッシュ・アセットファイルへの同時アクセスの競合 Shared cache / asset file lock conflicts

2つのクライアントが同じキャッシュフォルダーに同時に書き込んだりファイルをロックしたりすると、片方がNPCのモデル・テクスチャを読み込めなくなります。

なぜ: 2つのクライアントが同じインストールフォルダーのキャッシュ・アップデートファイルに同時に書き込む → すると: ファイルロックの失敗や、書きかけのファイルを読んでロードに失敗 → 画面では: ネームプレートはあるのにキャラクターモデルがない、または透明なNPC

症状: 表示されない・ゴースト · 主担当 ゲーム開発チーム・クライアント開発

メモリ・VRAM不足によるストリーミングの失敗 Memory / VRAM exhaustion

2つのクライアントがビデオメモリを分け合うと、新たに必要なモデル・テクスチャを載せる場所がなく、一部が描画されません。

なぜ: 2つのクライアントがVRAM・RAMを分け合う。OSはバックグラウンドウィンドウのビデオメモリの割り当てを先に減らすこともある → すると: エンジンが新しいモデル・テクスチャを載せられないか、下ろしては載せ直すことを繰り返す → 画面では: NPCが遅れて現れる、ぼやける、表示されない、カクつき

症状: 表示されない・ゴースト, カクつき · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 外部・外部

表示オプションの違い Different display settings

表示人数の制限、NPCのネームプレート・モデルの非表示、低スペックモードなどのオプションが2つのクライアントで違うと、見えるものが変わります。

なぜ: 片方のクライアントだけ「周囲のキャラクター表示数の制限」や低スペックモード → すると: 遠くにいるか優先度の低いNPCを描画しない(正常) → 画面では: 片方にだけNPCがいない

症状: 表示されない・ゴースト · 主担当 ゲーム開発チーム・クライアント開発

クライアントのバージョン・データの不一致 Client version / data table mismatch

2つ目のクライアントが別のインストール版だったりアップデートが済んでいなかったりすると、サーバーが送った新しいNPCのIDを知らないため、黙って無視します。

なぜ: 別フォルダーのインストール版、またはアップデート中に起動したクライアント → すると: 知らないNPC ID・モデルIDを受け取ると読み飛ばす → 画面では: 新しく追加されたNPCだけが片方で表示されない

症状: 表示されない・ゴースト · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

接続ごとの送信バジェット・優先度 Per-connection bandwidth budget and priority

サーバーが接続ごとに送る量に上限を設けて近いものから送ると、上限が低く設定された側は、遠くにいるNPCを遅れて受け取るか、受け取れません。

なぜ: 人の多い場所で、サーバーが接続ごとの送信量の上限内で重要度順に送信 → すると: 帯域幅の推定が低く出た接続(例:バックグラウンドウィンドウで受信確認が遅れている側)は、後ろのほうのオブジェクトを後回しにし続ける → 画面では: 遠くにいるNPCが片方でだけ遅れて見えるか、表示されない

症状: 表示されない・ゴースト, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

時刻推定の誤差によるオブジェクトの保留 Clock estimate error holds or discards entities

クライアントが推定したサーバー時刻がずれていると、届いたばかりのオブジェクト情報を「まだ未来」として保留したり、「古すぎる」として破棄したりします。

なぜ: 片方のクライアントのサーバー時刻の推定が大きくずれる(ロード中の測定、省電力からの復帰) → すると: 補間の基準時刻とオブジェクト情報の時刻が合わない → 画面では: オブジェクトが遅れて現れるか、止まったまま見える

症状: 表示されない・ゴースト, カクつき · 主担当 ゲーム開発チーム・クライアント開発

06よく見る原因

TCP再送:発生する原因と遅延が大きくなる理由

サーバーのメトリクスで「TCP再送(Retransmission)」が増えると、ラグ報告も一緒に増えることがよくあります。再送は「パケットが消えた」、または「消えたと誤って判断した」というシグナルです。原因はWi-Fiからサーバーのネットワークカードまで、経路のどこにでもあります。ゲームのように小さなパケットをまばらに送る接続では、パケットを1つ失っただけで数百msのフリーズにつながります。この章では、再送の根本原因、原因の探し方、解決の方向性をまとめます。

サーバーが送信ゲームが受信123×消失456124563再送まで待機(復旧方式によって異なる)3ゲームには何も届かない:フリーズ3・4・5・6が一気に:早送り
50msごとに送る接続で、3番が1つだけ消えた場合です。TCPは順番どおりにしか渡さないので、4・5・6番が届いても、3番を再び受け取るまでゲームに渡しません。そのため、1つのパケットロスがフリーズと、その後の早送りになります。再送するタイミングは復旧方式によって、1往復前後から「往復時間+最低200ms」(再送タイマー)まで変わります(下の「再送の種類」を参照)。

再送がゲームを重くする4つの理由

  1. 順序待ち(HOLブロッキング):TCPは、失った1つを再び受け取るまで、後から届いたパケットをゲームに渡しません。1つ失うと、その後ろのすべてが一緒に止まり、一気に解放されます(フリーズの後に早送り)。
  2. 再送の待ち時間:送信側は再送タイマー(RTO)が満了してから再送します。Linuxでは「往復時間+最低200ms」です。再送したものも失うと、待ち時間が倍々に増えます(0.3秒 → 0.6秒 → 1.2秒 …)。
  3. thin stream(小さなパケットをまばらに送る接続):高速再送は、受信側が「後続のパケットが3つ届いた」と知らせるシグナル(重複ACK 3つ。ACKは「受け取った」という確認)で動きます。ゲームのパケットは50〜200msに1つなので、シグナルがそろう前にRTOが先に来ることがよくあります。大容量のダウンロードは問題ないのに、ゲームだけが目立って止まるのはこのためです。最新のLinuxのRACKは、後続のパケットが1つ届くだけで判断できるのでこの差を大きく縮めます。ただし、パケット間隔が200ms前後と長いと、RACKでもRTOより速くはなりません。
  4. 送信量の縮小:TCPはパケットロスを輻輳のシグナルとみなし、一度に送る量(輻輳ウィンドウ)を減らします。RTOまで行くと、一度に1つだけ送る状態から増やし直さなければなりません。その間に新しく生まれたパケットはサーバーにたまって待ち、人が多い場所の大きな更新が次々と後ろ倒しになります。

再送の種類

種類いつ起きるか復旧までの時間ゲームでの見え方
高速再送
Fast retransmit
後続のパケットが先に届き、受信側が「途中が抜けた」(重複ACK・SACK)と知らせたとき往復時間+後続のパケット3つが届くまでの時間一瞬止まる。パケットの間隔が短いほど速い
RACK・TLP
時間ベースのロス判定、末尾パケットの再送
後から送ったパケットが届いたのに、前のものが一定時間届かないとき。しばらくACKがないときは、末尾のパケットをもう一度送る後ろのパケットの確認が来ればすぐ(RACK。順序が入れ替わっただけの可能性があるので、往復時間の1/4ほど余分に待つ)。後ろのパケットがなければ往復時間の約2倍(TLP)、ACK待ちのパケットが1つだけなら遅延ACKを考慮して200ms余分に待つthin streamでも比較的短く一瞬止まる程度。最新のLinuxのデフォルト
RTO再送
Retransmission timeout
何のシグナルもないまま待ち時間が満了したとき往復時間+最低200ms、失敗するたびに2倍数百ms〜数秒のフリーズの後に早送り、長引くと切断
SYN再送接続要求そのものが消えたとき(接続待ちキュー(backlog)のあふれ、ファイアウォールによる遮断)1秒、2秒、4秒、8秒 …(Linux 6.5以降は5回まで1秒間隔で再送した後に倍々、以前のWindowsは3秒から)接続ボタンを押してから1秒、3秒のように秒単位できっちり遅れ、失敗が続くと接続不可・無限ロード
不要な再送
Spurious retransmission
失われていないのに、遅れて届いたり順序が入れ替わったりしたため、失われたと判断して再送する復旧するものはない。その代わり送信量だけが減る(LinuxはDSACK(受信側の「もう受け取った」という通知)やタイムスタンプで検知すると元に戻すこともある)回線の浪費、大容量転送の速度低下。メトリクス上は再送率だけが高い
ゼロウィンドウプローブ
再送と紛らわしいもの
受信側のバッファが満杯で「しばらく送らないで」という状態のときに、確認用に送るパケット受信側が読み出しを始めるまでフリーズ。回線は正常で、受信側のプログラムが時間内に読み出せていない

どこで失われたかの探し方

再送率は「送ったパケットのうち再送した割合」です。起動後にたまった累積値は平常時の値に埋もれるので、1分のような一定の間隔で増えた量から計算します。公認の基準はありませんが、サーバー全体の平均についての大まかな目安は、0.1%未満なら健全、0.1〜1%なら一部のユーザーがときどき一瞬止まる、1%を超えると多くのユーザーが体感、3%を超えると深刻です。モバイルや海外のユーザーが多いゲームは、平常時の値が高めに出ます。そのため、1つの数字で判断するよりも、平常時の何倍に増えたかもあわせて確認します。平均は少数の悪い回線に引っ張られるので、地域・通信事業者・サーバー・時間帯別に分けて見るのが原因を見つける近道です。接続を途中で受けてサーバーへ新たにつなぎ直す機器(プロキシ、一部のロードバランサー・ゲートウェイ)があると、ゲームサーバーのメトリクスにはその機器とサーバーの間の区間しか現れません。ユーザー側の再送はその機器で確認します。

確認場所見る項目わかること
サーバー全体(Linux)nstatを1分間隔で2回実行したときの増分:TcpRetransSegs ÷ TcpOutSegs、およびTcpExt系のTCPTimeouts、TCPLossProbes・TCPLossProbeRecovery、TCPLostRetransmit、TCPSpuriousRTOs、TCPDSACKRecv、TCPSynRetrans再送率、RTOまで行った回数、TLPを送った回数とそのうち実際のロスを埋めた回数、再送したものまで再び失った回数、接続要求の再送。DSACK・Spuriousが多ければ「失われていないのに再送」。LinuxのOutSegsには再送分が含まれないので、厳密な割合はRetransSegs ÷ (OutSegs + RetransSegs)ですが、1%前後では差は小さいです
接続ごと(Linux)ss -tiのretrans(現在復旧中/累積)、rto、backoff、rtt、cwnd、lost、reordering、bytes_retrans特定のユーザー・地域だけ再送が多いか、RTOがどれだけ伸びているか(backoffはRTOが連続して2倍になった回数)。bytes_retrans ÷ bytes_sentがその接続の再送率
再送1件ずつ(Linux)eBPFツールtcpretrans(bcc)。-cは接続ごとの集計、-lはTLPを含む再送が起きるたびに、相手のIP・ポート・接続状態を1行ずつ表示します。パケットキャプチャなしで手軽に、どのユーザーのIP帯・サーバーに集中しているかを確認
サーバーのネットワークカードip -s -s linkのdropped・missed・crc、ethtool -Sのrx_missed_errors・rx_no_buffer_count・rx_crc_errorsなど(名前はドライバーごとに異なり、mlx5はrx_out_of_buffer・rx_discards_phy)、/proc/net/softnet_statの2列目(dropped)・3列目(time_squeeze)サーバーのネットワークカードが受け取った直後に破棄したのか(リングバッファ・CPU)、ケーブルや光モジュールの不良(CRC)なのか。softnet_statはCPUごとに1行で、16進数です。time_squeezeが増え続けるなら、受信処理を担当するコアが時間内に処理を終えられていない
クラウドネットワークAWS ENAはethtool -Sのbw_in_allowance_exceeded、bw_out_allowance_exceeded、pps_allowance_exceeded、conntrack_allowance_exceeded、linklocal_allowance_exceeded。CloudWatchのデフォルトの画面にはないので、CloudWatchエージェントで別途収集しますインスタンスの上限で黙って破棄したか。値が増えていれば上限超過です。ほかのクラウドにも、VMサイズごとの帯域幅・接続数の上限があります
スイッチ・ルーター・ファイアウォールポートのCRC・入力エラー、出力ドロップ、ポリサー超過、セッションテーブル使用量、ドロップログデータセンター機器の区間で破棄したか。5分平均の使用率が低いのに出力ドロップが増えるなら、マイクロバースト(ごく短い瞬間のトラフィック集中)
経路mtr・pathpingで見る、最後まで続くロス。数百回以上送らないと1%前後のロスは見えません。ゲームと同じTCPポートに送る(mtr -T -P PORT)とより正確です何番目の区間からロスが始まるか。途中の1区間だけがロスに見えて後ろが正常なら、その機器が測定用の応答(ICMP)をレート制限しているだけです。行きと帰りの経路が異なることがあるので、サーバー側からユーザー側へも測定します
パケットキャプチャ(両端)Wiresharkのフィルターtcp.analysis.retransmission、同じtcp.analysis.系のfast_retransmission、spurious_retransmission、duplicate_ack、lost_segment、zero_window元のパケットが送信側のキャプチャにはあって受信側になければ、その間で失われたもの。受信側にもあれば、不要な再送か、ACKが戻る途中で遅れたか消えたもの。受信サーバーのリングバッファで破棄されたパケットもキャプチャでは「間で失われた」ように見えるので、ネットワークカードのカウンターとあわせて確認します
WindowsサーバーパフォーマンスモニターのTCPv4\Segments Retransmitted/sec ÷ Segments Sent/sec、Network Interface\Packets Received Discarded、netsh int tcp show global、pktmon(Windows 10 1809・Windows Server 2019以降に内蔵)再送率の推移、ネットワークカードが受け取った直後に破棄したか、TCP設定、Windows内部のどこで破棄したか

確認の順序:インフラチームと一緒に確認するときは、次の順序が早道です。

  1. いつ・誰に:再送率がいつから増えたか、特定の地域・通信事業者・サーバー・時間帯に集中しているかを確認します。
  2. 本当のロスか:TCPSpuriousRTOs・DSACKが一緒に増えているなら、遅れて届いたものを失ったと誤認した不要な再送をまず疑います。
  3. サーバーの受信段階:同じ時刻にネットワークカード・softnet・クラウドの上限のカウンターが増えていれば、サーバー側で破棄しています。
  4. データセンター機器:スイッチ・ファイアウォールのドロップ・CRCカウンターとセッションテーブルを確認します。
  5. 外部の経路:問題のユーザー側とサーバー側から双方向にmtrを実行し、ロスが始まる区間を探します。
  6. それでもわからなければ:両端で同じ時刻にパケットをキャプチャして比較します。

報告に時刻(秒単位)、ユーザーの通信事業者・地域、接続先サーバー、症状名があれば、インフラチームはすぐにこの手順で調べられます。

解決の方向性

1. 失わないようにする(根本的な解決)

  • Wi-Fiの代わりに有線、5GHz・6GHz、ルーターのSQM・ECNでキューのあふれを減らす
  • サーバーが1ティック分の更新を一度に送り出さないよう、ティックの中で分けて送る。1つの接続がまとめて送る分は、ペーシング(fq、BBR、送信レートの上限)で均す
  • リングバッファを増やす、割り込みを複数のコアに分散、クラウドの上限を確認
  • CRCエラーのあるケーブル・光モジュールを交換、デュプレックス設定を揃える
  • ポリサー(超過分を即座に破棄)の代わりにシェーパー(キューに入れてゆっくり送り出す)、許容バーストを増やす
  • ファイアウォール・接続追跡(conntrack)テーブルと中間機器の秒間パケット数に余裕を持たせる、行きと帰りの経路が同じファイアウォールを通るように揃える
  • MSS(1つのパケットに載せるデータの最大サイズ)の調整とサイズ超過通知(ICMP)の許可でMTUブラックホールを防ぐ(MTU探索は最後のセーフティネット)、クライアントが送るハートビートでNAT・LBのマッピングを維持

2. 速く復旧させる

  • SACK・タイムスタンプがサーバーの設定で無効になっていないか、中間機器で削除されていないかを確認(SACKがないとRACK-TLPも動作しない)
  • RACK-TLPを使う(最新のLinux・Androidのデフォルト)。自分の入力のようにクライアントが送る方向はクライアントのOSが復旧するので、サーバーの設定では変わらない(WindowsはWindows 10(1607)・Windows Server 2016からTLPとRACKがデフォルトで有効。失われた再送まで復旧する新しいRACKはWindows Server 2022から)
  • thin stream用のtcp_thin_linear_timeouts、Linux 6.15以降はTCP_RTO_MAX_MSでRTOの上限を下げる
  • ゲームの接続ではTCP_NODELAYを有効にしておく(Nagleアルゴリズムが新しいパケットを送らずにためておくと、RACKが使う後続のパケットがなくなる)
  • 内部ネットワークのサーバー間接続は、経路ごとのRTO最小値を下げる(ip route … rto_min)
  • TCP_USER_TIMEOUTとゲームのハートビートで、死んだ接続を早く切って再接続

3. 再送の影響を受けにくくする(構造)

  • リアルタイムの位置・戦闘は、UDPの上で必要なものだけ再送する(古い位置は再送する価値がない)。入力は直近の数個を重ねて送れば、1つ失っても次のパケットが埋める
  • チャット・取引のように順序が必要なものとリアルタイムのパケットを、別々のフローに分離(QUICのストリーム、TCP接続を分けるなど)。片方のロスがもう片方をブロックしない
  • TCPを使い続けるなら、送信バッファに古い位置をためずに最新の状態で上書き(TCP_NOTSENT_LOWATなど)。長いフリーズの後の早送りが短くなる
  • 補間バッファと予測で、一瞬の停止を画面上で隠す。数百msのRTOによるフリーズまで隠すのは難しい

設定名の整理:有効にする設定と紛らわしい設定

再送の復旧に関わる設定のほとんどはOS(カーネル)の設定で、ゲームの接続にだけ個別に有効にできるソケットオプションはわずかです。名前のせいでよく誤解されるTCP_NODELAYは、復旧を速くする設定ではありません。ただし、有効にしないと(Nagleアルゴリズムを使うと)、復旧中に新しいパケットがさらに遅れます。以下はLinuxの場合で、Windowsは名前と対応範囲が異なります。

設定設定場所何を変えるか注意
TCP_NODELAYソケットオプションNagleアルゴリズムを無効化。小さなメッセージをためずにすぐ送るパケットロスがなくても生じる40〜200msの待ちをなくす。再送タイマー(RTO)自体は変わらない。ただし、Nagleアルゴリズムが有効だと、復旧を待つ間に新しいパケットまで足止めされて復旧後にさらに1往復待つ。高速再送・RACKが頼る後続のパケットもなくなるので、RTOまで行きやすい。ゲームでは有効にするのが普通
net.ipv4.tcp_recovery (RACK)カーネル設定時間ベースのロス判定。順序の入れ替わりに強く、thin streamも速く復旧デフォルト値1(有効)。Linux 4.4で導入され、4.18ごろに現在の形になった。6.17からはRACKが唯一のロス判定方式なので、0にしても効果がない。SACKのない接続では動作しない
net.ipv4.tcp_early_retrans (TLP)カーネル設定しばらく(往復時間の約2倍)ACKがなければ末尾のパケットをもう一度送り、末尾パケットのロス(tail loss)を早く発見デフォルト値3(有効)、0なら無効。SACKがないと動作しない。ACK待ちのパケット(in-flight)が1つだけなら200ms余分に待つので、RTOと大差なくなる
net.ipv4.tcp_sack, tcp_dsack, tcp_timestampsカーネル設定選択的ACK(SACK、途中の抜けの通知)、重複受信の通知(DSACK)、往復時間の測定(タイムスタンプ)デフォルトはすべて有効。2019年のSACKのセキュリティ問題のときに無効にしたまま残っているサーバーがある。SACKが無効だとRACK・TLPも動作しない
net.ipv4.tcp_thin_linear_timeouts / TCP_THIN_LINEAR_TIMEOUTSカーネル設定 / ソケットオプションACK待ちのパケット(in-flight)が4つ未満の接続では、最初の6回までRTOを倍々に増やさないデフォルトは無効。ソケットオプションでゲームの接続にだけ有効にできる。最初のRTOは短くならない
TCP_RTO_MAX_MS / net.ipv4.tcp_rto_max_msソケットオプション / カーネル設定(Linux 6.15以降)倍々に増えるRTOの上限(デフォルト120秒)を下げる。最小1秒連続したパケットロスの後に、RTOが数十秒まで大きくならないようにする。死んだ接続の判定も一緒に早くなる
net.ipv4.tcp_mtu_probingカーネル設定大きなパケットが消え続けるとサイズを小さくし、MTUブラックホールを通過デフォルト0(無効)。1 = 再送が3秒ほど続いてブラックホールが疑われるときだけ小さくする(その間はフリーズ)。2 = 最初から1,024バイトで始めて少しずつ大きくしてみる
ip route … rto_min経路設定その経路のRTO最小値(デフォルト200ms)を下げるサーバー同士の内部ネットワークに限る。インターネット区間で下げると不要な再送が増える。Linux 6.11以降のnet.ipv4.tcp_rto_min_usはサーバー全体の値なので、インターネット側の接続まで一緒に変わる。6.15以降はソケットオプションTCP_RTO_MIN_USで内部の接続だけ下げられる
TCP_USER_TIMEOUTソケットオプション再送が続くときに接続を諦めるまでの時間復旧を速くはしない。死んだ接続を早く切って再接続させる。設定しないと、Linuxは再送を15回前後、約15分続けてからようやく切断する(tcp_retries2)
SO_KEEPALIVE + TCP_KEEPIDLEなどソケットオプションアイドル接続が生きているかを確認再送とは別物。NAT・LBのマッピング維持と、死んだ接続の検知用
fqキュー + SO_MAX_PACING_RATE、BBRキュー設定 / ソケットオプション / カーネル設定パケットを均等に分けて送り、バースト(一度にまとめて送ること)によるパケットロスを減らすパケットロスを「予防」するためのもの。復旧速度とは別物

TCP再送の根本原因

無線区間のパケットロス Wi-Fi / cellular link loss

Wi-Fiとモバイル回線は、無線区間で何度か再送し、それでも届かなければパケットを破棄します。破棄されたパケットは、TCPがかなり後になってから送り直します。

なぜ: 電波が弱いか干渉が強く、無線区間での送信が連続して失敗 → すると: 無線機器の再試行上限(通常は数回〜十数回)を超えるとパケットを破棄 → 画面では: TCPの再送を待つ間止まり、後続のパケットは受信バッファで待たされた後に早送り

症状: フリーズ, 早送り, ワープ · 主担当 外部・外部 · 副担当 インフラチーム・サーバーインフラ, ゲーム開発チーム・サーバー開発, ゲーム開発チーム・クライアント開発

ボトルネックでのキューあふれ(輻輳によるロス) Tail drop at a congested bottleneck

ルーター、通信事業者どうしの接続区間、データセンターの回線のように、最も細い箇所のキューが満杯になると、新しく届くパケットを破棄します。

なぜ: 動画・ダウンロード・他のユーザーのトラフィックでボトルネック区間が満杯 → すると: キューが満杯の間、新しく到着するパケットが続けて破棄される(tail drop)。破棄されなかったパケットも満杯のキューの末尾で待たされる → 画面では: 複数のパケットが一度に消え、長く止まった後に早送り、夜の時間帯に多い

症状: フリーズ, 早送り, 引き戻し · 主担当 インフラチーム・ネットワークインフラ · 副担当 外部・外部, ゲーム開発チーム・クライアント開発

送信バーストによる浅いバッファのあふれ Sender bursts overflow shallow buffers

サーバーがティックごとに数千人分の更新を一瞬でまとめて送ると、スイッチの小さなバッファやクラウドの瞬間的な上限が1ms足らずであふれ、一部が破棄されます。

なぜ: ティックの開始時に、全員に送るパケットを一度に送信 → すると: 複数のサーバーのトラフィックが集まるスイッチポートのバッファ(ポートあたり数百KB〜数MB)やクラウドインスタンスの上限が瞬間的にあふれる(平均利用率は低い) → 画面では: 複数の人が同時にワープしたり一瞬止まったりする、平均値のメトリクスでは原因が見えない

症状: ワープ, フリーズ, 早送り · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ, インフラチーム・ネットワークインフラ

ポリサーによる超過分の破棄 Traffic policing

通信事業者の料金プラン、クラウドインスタンスの上限、DDoS対策機器は、決められた速度を超えるパケットをキューに入れずにすぐ破棄することもあります。

なぜ: 瞬間的な送信量が許容速度・許容バーストを超える → すると: 超えたパケットをキューに入れずにすぐ破棄(ポリシング) → 画面では: バーストが大きい瞬間ごとに複数のパケットが消え、止まった後に早送り、平均速度は上限を下回って見える

症状: フリーズ, 早送り, ワープ · 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ, ゲーム開発チーム・サーバー開発

物理エラー(不良ケーブル・光モジュール・コネクター) Bit errors: bad cable, optics, dirty fiber

ケーブルの損傷、ほこりの付いた光コネクター、寿命を迎えた光モジュールはビットエラーを起こし、壊れたパケットは機器が黙って破棄します。

なぜ: ケーブル・光モジュール・コネクターの不良でビットが反転 → すると: チェックサム(CRC)が合わないパケットを機器が破棄 → 画面では: その経路を通る人だけが継続的に一瞬止まっては早送り、時間帯とは無関係

症状: フリーズ, 早送り, ワープ · 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ, 外部・外部

デュプレックスの不一致 Duplex mismatch

片側はオートネゴシエーション、もう片側は速度・デュプレックスを固定にしておくと、片側が半二重で動作し、負荷がかかるたびに衝突(コリジョン)でパケットを失います。

なぜ: 機器の片側だけ速度・デュプレックスを固定設定 → すると: 片側は全二重、もう片側は半二重で動作し、コリジョン・レイトコリジョンが発生 → 画面では: 普段は問題ないが、トラフィックが増えるとその機器を通る人全員が止まっては早送り

症状: フリーズ, 早送り · 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ

受信サーバーのホストでのパケット破棄 Receiver host drops (ring, softirq, CPU)

パケットはサーバーまで届いたのに、NICのリングバッファ(到着したパケットを一時的に入れておくバッファ)があふれたり、カーネルで受信処理を担うコアが飽和したりして破棄されます。

なぜ: 接続数の急増・1つのコアに集中した割り込み・仮想マシンのCPUスチール・仮想スイッチの過負荷 → すると: リングバッファ(rx_missed_errorsなど、名前はドライバーによって異なる)やカーネルの受信キュー(softnet dropped)で破棄 → 画面では: 人が集中すると、サーバー全体で同時に入力の反映が遅れ、一瞬止まる

症状: 入力遅延, フリーズ, 早送り, ワープ · 主担当 インフラチーム・サーバーインフラ

ファイアウォール・接続追跡による破棄 Stateful firewall / conntrack drops

ファイアウォールやLinuxの接続追跡(conntrack、通過する接続をテーブルに記録する機能)は、テーブルが満杯になったり、接続の状態が合わないと判断したりすると、パケットを破棄します。

なぜ: 接続追跡テーブルが満杯(table full)、または行きと帰りの経路が異なり、片方向だけがファイアウォールを通る(非対称経路) → すると: ファイアウォールが「知らない接続」や「ウィンドウの範囲から外れたシーケンス番号」のパケットとみなして破棄 → 画面では: テーブルが満杯になると新規接続ができなくなり、経路がずれるとその経路の人だけが再送を繰り返した末に切断

症状: フリーズ, 切断, 接続不可・無限ロード · 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ, ゲーム開発チーム・サーバー開発, ゲーム開発チーム・クライアント開発

中間機器の処理上限超過(ファイアウォール・IPS・DDoS対策) Inline appliance PPS / CPU overload

ファイアウォール、侵入防止システム(IPS)、DDoS対策機器は、通過するパケットを1つずつ検査します。検査能力を超えた瞬間から、処理しきれなかったパケットを破棄します。

なぜ: ピーク時間帯・イベントで小さなゲームパケットが毎秒数十万個以上集中、または検査ルールが重い → すると: 機器のCPU・秒間パケット数が上限に達し、機器で破棄。誤検知なら正常なパケットも遮断 → 画面では: その機器の後ろにあるサーバー全体で同時にフリーズ・ワープ、人が集中したときだけひどくなる

症状: フリーズ, 早送り, ワープ, 切断 · 主担当 インフラチーム・ネットワークインフラ · 副担当 ゲーム開発チーム・サーバー開発

MTUブラックホール(大きいパケットだけ繰り返し失われる) PMTU black hole

途中の区間が受け取れるサイズが小さくなったのに「大きすぎる」という通知(ICMP)が遮断されると、大きなパケットは何度送り直しても消え続けます。

なぜ: VPN・トンネル区間で最大サイズが小さくなり、サイズ超過の通知はファイアウォールで遮断 → すると: 送信側は理由がわからないまま同じ大きなパケットを再送し続け、RTOは2倍ずつ増加 → 画面では: 普段は問題ないが、インベントリ・人の多い場所・入場時のロードのように大きなデータがやり取りされる瞬間に、後続の小さなパケットまですべて止まり、最終的に切断や無限ロード

症状: フリーズ, 切断, 接続不可・無限ロード · 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ, ゲーム開発チーム・サーバー開発

接続中のNAT・ロードバランサーのマッピング期限切れ NAT / load balancer mapping expired mid-connection

アイドル接続のマッピング(この接続をどこに転送するかを記録したエントリ)を中間機器が消すと、次に送るパケットは転送されません。再送だけを繰り返した末に切断されるか、機器が接続拒否(RST)を返してすぐに切断されます。

なぜ: しばらくパケットのやり取りがない接続(離席、ロビー) → すると: ルーターのNAT・通信事業者のCGNAT・ファイアウォール・ロードバランサー・クラウドのセキュリティグループがアイドル状態のマッピングを削除 → 画面では: 再び動いた瞬間に再送が続いた末に切断、またはすぐに切断

症状: 切断, フリーズ · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発, インフラチーム・ネットワークインフラ, インフラチーム・サーバーインフラ

経路変更・ECMPの不良経路 Route change / bad ECMP member

インターネットの経路が切り替わる数秒の間、または複数のECMP経路のうち不良な経路に割り当てられた接続で、パケットが消えます。

なぜ: BGPの経路再計算、または複数の経路(ECMP・LAG)のうち1つの経路で機器・回線が不良 → すると: 経路の切り替え中に一時的なパケットロス、またはその経路を通る接続だけに継続的なパケットロス → 画面では: 突然数秒止まった後に早送り、または「再接続すると直る」(別の経路に割り当てられる)

症状: フリーズ, 早送り, ワープ · 主担当 インフラチーム・ネットワークインフラ · 副担当 ゲーム開発チーム・サーバー開発, 外部・外部

遅延の急上昇による不要な再送 Spurious RTO from delay spikes

パケットは消えておらず、一時的にとても遅れて届いただけなのに、その遅延がRTOより長いと、送信側はパケットロスと判断して再送します。

なぜ: バッファブロート、Wi-Fiの省電力、モバイルの無線状態の切り替え、仮想マシンの一時停止で、瞬間的な遅延が数百ms → すると: RTOが先に満了して再送、元のパケットもすぐに到着(受信側は重複して受け取る) → 画面では: フリーズ・早送りは遅延の急上昇そのものが原因。不要な再送は止まる時間をほとんど延ばさず、再送のメトリクスだけを押し上げるため、パケットロスと誤解される

症状: フリーズ, 早送り, 入力遅延 · 主担当 外部・外部 · 副担当 インフラチーム・サーバーインフラ, ゲーム開発チーム・クライアント開発

順序の入れ替わりによる不要な高速再送 Reordering triggers spurious fast retransmit

複数の経路や束ねたリンクを通る間にパケットの順序が入れ替わると、受信側が重複ACKで「抜けたパケットがある」と知らせ、送信側は問題のないパケットを送り直します。

なぜ: パケット単位で経路を振り分ける機器、パケット単位で振り分けて送るLAG(リンクアグリゲーション)、経路が切り替わる瞬間が順序を乱す → すると: 後のパケットが先に到着して重複ACKが3つたまる → 高速再送 → 画面では: まばらにやり取りされるゲームパケットにはほとんど影響なし。人の多い場所での大きな更新やアップデートデータのダウンロードが遅くなり、ときどきカクつく

症状: カクつき, 入力遅延 · 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ

ACKの遅れ・消失(上り回線の飽和) ACK path congestion on asymmetric links

データは問題なく届いているのに、「受け取った」というACKが満杯の上りキューで遅れたり消えたりすると、送信側はパケットロスと判断して再送します。

なぜ: 家で動画のアップロード・クラウドバックアップにより上り回線が満杯 → すると: ACKがルーターのキューで数百ms遅れるか、あふれて破棄される → 画面では: サーバーが送るゲームパケットはおおむね時間どおりに届く。同じ上りキューにたまった自分の入力が遅れて入力遅延・引き戻し、ときどき不要な再送

症状: 入力遅延, 引き戻し · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

RTOの設定が環境に合っていない RTO min too low or too high

RTOの最小値を下げすぎると少し遅れただけで不要な再送が起き、デフォルト値(200ms)はゲームにとっては長すぎて、1回失うたびに長く止まります。

なぜ: データセンター向けにRTOの最小値を大きく下げた、またはインターネット区間でデフォルト値のまま使用 → すると: 低いと瞬間的な遅延でも再送が殺到、高いとパケットロスのたびに長く待つ → 画面では: デフォルト値ならパケットロス1回で数百ms止まった後に早送り、下げすぎると止まる時間は減るが不要な再送が急増して回線を浪費

症状: フリーズ, 早送り, 入力遅延 · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発

thin streamの遅い回復 Thin streams fall back to RTO

ゲームのように小さなパケットをまばらに送ると、「後続のパケット3つ」がそろう前にRTOが先に来ます。大容量の転送と比べて、同じパケットロスでもはるかに長く止まります。

なぜ: パケットの間隔が100ms前後なので、ACK待ちのパケット(in-flight)が数個しかない → すると: 重複ACKが3つそろうには300ms以上かかるため、RTO(Ping + 200ms)が先に発動、連続したパケットロスなら2倍ずつ → 画面では: パケットロス1回で0.3秒前後止まり、送り直したものまで失うと1秒近く止まった後に早送り

症状: フリーズ, 早送り · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ, ゲーム開発チーム・クライアント開発

中間機器によるTCPオプションの除去 Middlebox strips TCP options

一部のファイアウォール・高速化装置がTCPオプションを消したり書き換えたりすると、複数のパケットを失ったときに1往復に1つずつしか回復できなくなったり、ウィンドウ(一度に送れる量)が小さくなったりして遅くなります。

なぜ: ファイアウォールの「TCP正規化」、古い高速化装置がSACK・タイムスタンプ・ウィンドウスケールのオプションを除去 → すると: 失ったパケットが複数あると1往復ごとに1つずつ回復、ウィンドウは64KBに制限される → 画面では: パケットロスのたびに止まる時間がずっと長くなり(SACKがないとRACK-TLPも使えない)、解消すると早送り。アップデートデータのダウンロードのような大容量の転送も遅い

症状: フリーズ, 早送り · 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ

ゼロウィンドウ(再送のように見える停止) Zero window, often mistaken for retransmission

受信側のプログラムがソケットを読むのが間に合わず、バッファが満杯になると、送信側は送信を止めてゼロウィンドウプローブだけを送ります。回線の問題ではありません。

なぜ: クライアントのフレームが止まる、サーバーのスレッドがブロックされるなどでソケットを読めない → すると: 受信ウィンドウが0になり、送信側は送信を止めてプローブだけを送る(間隔がだんだん延びる) → 画面では: 止まった後に早送り。パケットキャプチャに「ZeroWindow」が見え、パケットロスはない

症状: フリーズ, 早送り · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発, インフラチーム・サーバーインフラ

接続要求(SYN)の再送 SYN retransmission on connect

接続要求が接続待ちキュー(backlog)のあふれやファイアウォールの遮断で消えると、クライアントOSは1秒後から間隔を延ばしながら送り直します。

なぜ: メンテ明けの接続の殺到でサーバーの接続待ちキューがあふれる、またはファイアウォール・DDoS対策がSYNを破棄 → すると: クライアントOSが1秒後から決まった間隔でSYNを再送(以前のLinuxは1秒 → 2秒 → 4秒) → 画面では: 接続ボタンを押してから1秒、3秒のようにきりのいい秒数だけ遅れ、失敗が続くと接続不可・無限ロード

症状: 接続不可・無限ロード · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ, インフラチーム・ネットワークインフラ, ゲーム開発チーム・クライアント開発

07担当分け

ゲーム開発チームとインフラチームの担当範囲

同じラグでも、直す担当は違います。クライアント・サーバーのコードと同期設計はゲーム開発チームが、回線・ネットワーク機器・サーバー機器・DBサーバーはインフラチームが担当します。ユーザーのPCや家庭内ネットワーク、通信事業者の区間、クラウド事業者側の問題は、どちらのチームも直接は直せないため、案内や依頼で対応するか、迂回します。すべての原因カードに主担当と副担当を表示しています。カードの「数値の目安・確認方法・チーム別の対応」を開くと、チームごとの対応が分けて書かれています。

  1. 報告・アラート症状、秒単位の時刻、サーバー・チャンネル
  2. 誰に起きるか1人・同じ家 / 特定の通信事業者・地域 / 特定のサーバー・チャンネル / 全体
  3. 最初に呼ぶ担当候補となる原因カードの主担当。診断ツールの「最初の確認先」
  4. 渡す情報IP・通信事業者、切断理由、関連するグラフ、直前の変更
  5. 共同で対応カードのチーム別の対応に沿って分担
チケットが届いてから、チーム別の対応に分かれるまでの流れです。担当を最も大きく分けるのは「誰に起きるか」です。詳しい基準は下の表と観測データで切り分けるにあります。
担当担当範囲主な解決手段
ゲーム開発チームクライアントゲームクライアントのコード:フレーム・GC・ロード、補間・外挿・予測、クライアントのネットワーク処理(ハートビート送信・自動再接続を含む)コード修正、補間バッファ・予測の調整、ロード方式の変更、ハートビート間隔・再接続フロー、クライアントのアップデート
ゲーム開発チームサーバーゲームサーバーのコード:ティック・スレッド・ロック、同期設計、接続処理(acceptループ・listenの引数)、ハートビートへの応答・切れた接続の後始末、ソケットオプション、クエリ・トランザクション設計ロジックの最適化、非同期呼び出し、ティック・エリアの分散、ログイン待機列、セッショントークンによる引き継ぎ、ソケットオプション(TCP_NODELAYなど)、クエリ・インデックス設計、サーバーのアップデート
インフラチームネットワーク回線とデータセンターのネットワーク機器(スイッチ・ルーター・ファイアウォール・ロードバランサー・DDoS対策)、クラウドのネットワークACL・VPCルーティング・ロードバランサー、通信事業者・ピアリング機器の設定・交換、回線・ピアリングの増強、経路変更、通信事業者へのエスカレーション、ロードバランサー・ファイアウォールのアイドルタイムアウト・セッション上限の調整
インフラチームサーバー機器・OSサーバー機器・クラウドインスタンス(セキュリティグループ・接続追跡を含む)、OS・カーネル設定、NIC、デプロイ・監視環境増設・インスタンス変更、カーネル設定(sysctl:somaxconn・conntrackなど)、セキュリティグループの構成・接続追跡の時間、NICのリングバッファ・割り込みの分散、cron・バックアップの時刻調整
インフラチームDBサーバーDBサーバー・ストレージ、DBの設定・レプリケーション・バックアップ、キャッシュサーバーDBの増強、ストレージのIOPS確保、DBパラメータ・レプリケーション設定、バックアップ・チェックポイントの調整
外部ユーザー・ISP・クラウドユーザーのPC・家庭内ネットワーク、通信事業者の区間(自社の契約外)、クラウド事業者ユーザーへの案内(有線接続など)、通信事業者・クラウド事業者への依頼、ゲーム側での迂回・緩和

層・テーマ別の担当一覧

太字の数字はその担当が主担当の原因の数、+数字は副担当の原因の数です。マスを押すと、その原因とチームの対応が下に表示されます。

境界があいまいなとき:原因のあるチームが主担当、ほかのチームは緩和と確認

主担当は、根本原因がある場所、またはそれを取り除ける場所です。回線や機器が原因でも、ゲーム開発チームはその間、影響を減らす設計(補間バッファ、入力の重複送信、再接続)でしのぎます。サーバーのコードが原因なら、インフラチームが機器を増やしても一時的に先送りするだけです。よく迷う境界は次のように決めました。

  • 放置していると切断:ユーザーのルーターや通信事業者の機器のアイドルタイムアウトは自社では変えられず、そのマッピングは内側から出ていくパケットでしか確実に維持できません。そのため、クライアントがハートビートを送り、切断されたら自動で再接続します。サーバーはハートビートに応答し、届かなければ先に接続を片付けてから、セッショントークンで引き継ぎます。インフラチームは自社の機器のタイムアウト値を伝え、必要なら延ばします。
  • 接続待ちキュー(backlog)のあふれ:実際の上限はサーバーのコードのlistenの引数とacceptループで決まるため、サーバー開発が主担当です。サーバー機器・OSは、カーネルの上限(somaxconn)とSYN Cookieを担当します。
  • クラウド:セキュリティグループとインスタンスの接続追跡はサーバー機器・OSが、ネットワークACL・VPCルーティング・クラウドのロードバランサーはネットワークが担当します。

表の「まず」は、その現象に当てはまる原因カードの主担当を数えて決めた、最初に呼ぶ担当です。2つある場合、前にあるのは主担当になっているカードが最も多い担当で、後ろは最初から一緒に呼ぶ担当です。

現象ゲーム開発チームの対応インフラチームの対応まず確認するメトリクス
特定の通信事業者・地域でパケットロス・ジッターが大きい
まずインフラチームネットワーク
適応型の補間バッファ、入力の重ね送り、パケットロスに強いUDP送信、接続ごとのロス・再送の統計から影響を受けている人のIP・ポート・時刻を抽出、移動検証の基準を回線状態に応じて緩和ゲームと同じプロトコル・ポートで双方向の経路測定(mtr)、不良経路の除外、通信事業者へのエスカレーション、ピアリング・回線の追加通信事業者別のロス率・ジッター分布、再送率
TCP再送の増加
まずインフラチームネットワークゲーム開発チームサーバー
TCP_NODELAY、1ティック分の送信をティック内で分けて送る、ソケットを遅れずに読み出す(ゼロウィンドウを防ぐ)、ハートビートでマッピングを維持、リアルタイムのパケットはUDPか別の接続で送る、送信バッファに古い位置をためない(TCP_NOTSENT_LOWAT)ロス箇所の除去(ケーブル・光モジュール・デュプレックス・ポリサー・ファイアウォールの接続追跡・MTU)、MSS調整、サーバーのリングバッファ・割り込みの分散、カーネルの復旧設定(RACK・tcp_mtu_probing)再送の増分(nstat)、ゼロウィンドウの回数、NIC・スイッチポートのドロップ・CRCカウンター
サーバーのCPU飽和でティック超過
まずゲーム開発チームサーバー
視界計算・ブロードキャストの最適化、ティックを複数のスレッドに分割、混雑するエリア・チャンネルの分割、ワーカースレッド数をCPUの上限に合わせる、ティック処理時間をメトリクスとして記録シングルコア性能(クロック)が高いCPU・インスタンス、コアごとのCPU使用率のアラート、CPUスチール・コンテナのCPUスロットリングの確認、割り込み処理のコアとティックスレッドのコアを分離ティック処理時間、コアごとのCPU使用率・steal・スロットリング回数(nr_throttled)
DBの応答遅延
まずゲーム開発チームサーバーインフラチームDBサーバー
クエリ・インデックス・トランザクション設計(短く、ロック順序を統一)、ゲームスレッドの外で非同期呼び出し、まとめて取得・キャッシュ、コネクションプールのサイズ・待機タイムアウトの調整遅いクエリ・実行計画・ロック待ちを見つけてゲーム開発チームに共有、チェックポイント・レプリケーション・統計情報更新の設定、ストレージのIOPS、サーバー数 × プールサイズが最大接続数以内かを確認、DBサーバーの増強スロークエリログ、ロック待ち、コネクション待ち、レプリケーション遅延、IOPS
メンテ明けに接続不可
まずゲーム開発チームサーバー
接続を受け付けるスレッド(acceptループ)がほかの処理で止まらないようにする、listenのbacklog引数を増やす、ログイン待機列システム、ログインのクエリをまとめる(N+1の解消)、クライアントの再試行間隔を延ばしつつランダムに分散カーネルのsomaxconn・SYN Cookie、ファイアウォール・ロードバランサーのセッション上限、サーバーのconntrack・ファイルディスクリプタの上限、DBキャッシュのウォームアップ、イベント前にサーバーを事前に拡張ListenOverflows、セッションテーブル・conntrackの使用率、ログインのクエリ数・コネクション待ち
放置していると切断
まずゲーム開発チームクライアント
クライアント:最も短いアイドルタイムアウトの半分以下の間隔でハートビートを送る(1つが遅れたり抜けたりしても、タイムアウト前に次が届くように)、切断されたら自動で再接続。サーバー:ハートビートに応答し、一定時間届かなければ先に接続を片付け、セッショントークンで引き継ぐ。経路上のロードバランサー・ファイアウォールのアイドルタイムアウト(ネットワーク)とクラウドのセキュリティグループの接続追跡時間(サーバー機器・OS)をまとめてゲーム開発チームに共有、自社の機器は必要なら延ばす。ユーザーのルーター・通信事業者のCGNATのタイムアウトは変えられない切断された接続のアイドル時間の分布(ある値の付近に集中していれば、そのタイムアウトを持つ機器)、回線の種類(モバイル・有線)
決まった時刻にサーバーが止まる
まずゲーム開発チームサーバーインフラチームサーバー機器・OS
正時のイベント・保存・タイマー・キャッシュ期限切れの時刻をランダムに分散、バッチクエリは細かく分けて少しずつ、停止時間の短いGCを明示的に指定cron・バックアップ・ログ圧縮の時刻分散とI/O優先度の引き下げ、DBバックアップはレプリカで取りチェックポイントは均等に、ディスクのバーストクレジットの確認、バックアップ転送速度の制限止まった時刻とジョブのスケジュール(cron・バックアップ・バッチ・チェックポイント)、GCログ
DDoS・トラフィックの急増
まずインフラチームネットワーク
ゲームのトラフィックパターン(ポート、パケットサイズ、秒間パケット数)をインフラチームに共有、アカウント・キャラクターごとのリクエスト頻度の制限、異常なパケットの早期遮断DDoS対策(スクラビング)とゲームのトラフィックに合わせた防御ルール、サーバーアドレスの秘匿、機器の秒間パケット数の上限、IP単位の制限は通信事業者の共有IP・ネットカフェを考慮秒間パケット数、機器のCPU・ドロップ、地域・通信事業者別の接続失敗率(誤検知の確認)
ユーザーのWi-Fi・PCの問題
まず外部ユーザー・ISP・クラウドゲーム開発チームクライアント
ゲーム内のネットワーク状態表示(Ping・ロス)、ジッターに応じて補間バッファの長さを自動調整、ラグが起きたときのログに回線の種類・PCのCPU使用率を記録、有線接続などの案内文直接は直せない。同じ通信事業者・地域に報告が集中したら、回線の問題として分類し直す報告にある回線・端末の情報、同じ通信事業者・地域の割合

引き継ぐときにそろえる情報

ゲーム開発チーム → インフラチーム

  • 正確な時刻(秒単位、タイムゾーンを明記)と継続時間、今も続いているか
  • サーバー・チャンネルID、影響範囲(自分だけ・特定の通信事業者・サーバー全体)と影響を受けた人数(同時接続数との比)
  • 症状名と様子:切断ならその前のアイドル時間、フリーズなら長さと繰り返しの周期
  • 影響を受けている人のIP・ポート・通信事業者・地域(複数の経路のうち1つだけが不良なら、ポートまでないと切り分けられない)、ゲームが使うプロトコル(TCP・UDP)とサーバーのポート
  • ゲーム側のメトリクス:ティック処理時間、Ping・ロスの分布、再送が増えた接続の数、切断理由(ハートビートのタイムアウト、接続拒否(RST)など)
  • 現在のハートビート間隔、サーバーの無応答判定時間、再試行の方式
  • 最近のデプロイ・設定変更の有無、すでに確認して除外した原因

インフラチーム → ゲーム開発チーム

  • 同じ時刻の機器・回線のメトリクス(使用率、ドロップ・エラーカウンター、セッション数)とサーバーOSのメトリクス(ListenOverflows、conntrack使用率、CPU steal)
  • 経路上の機器のタイムアウト・上限値:ロードバランサー・ファイアウォールのアイドルタイムアウト、セキュリティグループの接続追跡時間、セッション数・秒間パケット数の上限
  • 機器・回線の変更履歴と予定されている作業(交換、設定変更、バックアップ・cron、通信事業者の作業告知)
  • 通信事業者・クラウド事業者への問い合わせ番号と、回答の見込み時刻
  • 暫定対応(迂回、上限の緩和)と元に戻す時期
  • 原因区間と結論、再発防止策
  • ゲーム側に必要な対応(ハートビート間隔、再試行の方式、接続数の制限など)

両チーム共通:障害対応の責任者を1人決め、1つのチャンネルに時系列の記録を残し、次の共有時刻を事前に知らせます。主担当がほかのチームに移るときはこの記録も一緒に渡し、同じ確認を繰り返さないようにします。終わったら、同じ記録をもとに該当する原因カードの担当と対応を修正します。

クライアントのゲームプロセス

プレイヤーのPCやスマホで動いているゲームプログラムそのものです。ネットワークが完璧でも、ここでフレームが遅れると画面がカクつきます。また、ネットワークが悪いときにそれをどれだけうまく隠せるかも、ここで決まります。

ゲームは1秒に60回ほど同じ処理を繰り返します。入力を読み、受け取ったパケットを処理し、ゲームの状態を1ステップ進め、画面を描きます。このループ1回がフレームで、60FPSなら1フレームに使える時間は16.7msです(30FPSで動くスマホゲームなら33.3ms)。1フレームが遅れるとその分だけ画面が止まり、次のフレームで遅れた分だけ一気に動きます。

ネットワーク面でクライアントがする仕事は「足りない情報を埋めること」です。ほかのプレイヤーの位置はサーバーから飛び飛びに届くため、その間をつないで描く必要があり(補間)、パケットが途切れたら推測して動かす必要があり(外挿)、自分のキャラクターはサーバーの確認を待たずに先に動かして見せます(予測)。これらの技術が失敗したときの見え方が、そのままワープ、引き戻し、カクつきです。

たとえ

ゲームクライアントは生中継の映像を作る放送局の副調整室です。現場(サーバー)から写真が飛び飛びに届くと、その間を自然につなぎ合わせて映像のように見せます。写真が遅れて届くと、つなぐ写真がなくて画面が止まります。編集室そのものが忙しくても放送は途切れます。

この層でラグを生む原因

フレームタイムのスパイク Frame hitch

1フレームの計算に普段の数倍の時間がかかり、画面が一瞬止まります。

なぜ: スキルエフェクトの急増、大量スポーン、UI全体の更新が1フレームに集中 → すると: 16.7ms以内に終わらず、50〜300msかかる → 画面では: 画面が一瞬止まり、次のフレームで全員が一気に動く

症状: カクつき, フリーズ · 主担当 ゲーム開発チーム・クライアント開発

クライアントのガベージコレクション Client GC (Unity C#, Unreal, Lua)

使い終わったメモリ(ガベージ)を回収する間、ゲーム全体が止まります。一定の間隔でカクつくのが特徴です。

なぜ: 毎フレーム、一時的な文字列・配列・リストを作っては捨てる → すると: ガベージがたまると、GCがメインスレッドを止めて回収 → 画面では: 数秒〜数十秒ごとに規則的にカクつく

症状: カクつき, フリーズ · 主担当 ゲーム開発チーム・クライアント開発

メインスレッドでの同期ロード・シェーダーコンパイル Synchronous asset load, shader compile

初めて見るエリア・モンスター・エフェクトを描画する直前に、ファイルの読み込みやシェーダーの生成を待って止まります。

なぜ: 新しいエリアへの進入、初めて見るスキル・装備・モンスターの登場 → すると: メインスレッドがファイルの読み込みとシェーダーコンパイルを待つ → 画面では: 初回だけ0.1〜1秒止まり、2回目以降は問題ない

症状: フリーズ, カクつき · 主担当 ゲーム開発チーム・クライアント開発

ストレージが遅くアセットストリーミングが間に合わない Slow storage stalls asset streaming

HDDのような遅いストレージでは、オープンワールドのテクスチャ・モデルを読み込む速度が移動に追いつかず、オブジェクトの表示が遅れたり、ゲームが読み込みを待ってカクついたりします。

なぜ: 乗り物・テレポートで高速に移動したり、人が多い場所に入ったりして、新しいテクスチャ・モデルが一気に必要になる → すると: HDDのような遅いストレージが必要な速度で読み込めず読み込み要求がたまり、一部のロードはメインスレッドが完了まで待つ → 画面では: テクスチャがしばらくぼやけ、建物・キャラクターの表示が遅れ、読み込みを待つ瞬間にカクつき・フリーズ

症状: 表示されない・ゴースト, カクつき, フリーズ · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 外部・外部

大人数の描画負荷 Render/animation cost of crowds

攻城戦やワールドボスのように数百人が1つの画面に入ると、描画のコストそのものが処理しきれなくなります。

なぜ: 1つの画面に数百人とエフェクトが重なる → すると: アニメーション・影・名前表示・エフェクトのコストが人数に比例して増加 → 画面では: FPSが60 → 15に落ち、すべての動きがカクつき、入力も遅れる

症状: カクつき, 入力遅延 · 主担当 ゲーム開発チーム・クライアント開発

メインスレッドのパケット処理ボトルネック Network processing on the main thread

受信したパケットをフレームごとに決まった量しか処理しないと、押し寄せたパケットがどんどん次のフレームへ持ち越されます。

なぜ: 人が多い場所で、毎秒数千件の更新が届く → すると: メインスレッドがフレームあたりの処理量の上限に達し、読み切れない → 画面では: 他の人の動きがだんだん遅れ、まとめて反映される

症状: 早送り, 入力遅延 · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

補間バッファがないか短い Missing/short interpolation buffer

サーバーのパケットを受け取ってすぐ描画すると、ジッター(到着間隔のばらつき)がそのまま画面に表れます。

なぜ: 受信した位置をすぐに描画するか、バッファがジッターより短い → すると: 遅れて届いたパケットの分だけ止まり、まとめて届いたパケットの分だけ跳ぶ → 画面では: 他のキャラクターの動きがカクつく

症状: カクつき · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

過度な外挿(デッドレコニング) Over-extrapolation / dead reckoning

パケットが届かない間は最後の速度のまま動かし続けて見せ、外れていたと分かると元に戻します。

なぜ: パケットの受信が途切れ、最後の方向・速度のまま移動させ続ける → すると: 実際には相手は止まっていたか、方向を変えていた → 画面では: 相手キャラクターがしばらく進んでから本当の位置へ一気に移されたり、壁をすり抜けたりする。パケットの到着間隔がばらつくと、先に進んでは戻されるのを繰り返し、震えるように動く

症状: ワープ, カクつき · 主担当 ゲーム開発チーム・クライアント開発

クライアントサイド予測の不一致 Prediction mismatch / reconciliation

自分のクライアントが先に動かして見せたのに、サーバーの計算結果が違うと、自分のキャラクターが引き戻されます。

なぜ: クライアントがサーバーの確認前に先に動く(予測) → すると: サーバーが衝突・移動速度・バフを違う形で計算するか、コマンドを受け取れない → 画面では: 確認が届いたとき、自分のキャラクターが後ろへ引き戻される

症状: 引き戻し · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

固定タイムステップの追いつき処理の暴走 Fixed-timestep catch-up / spiral of death

一度止まった後、遅れた計算をまとめて処理しようとして、その計算のせいでさらに遅れます。

なぜ: ゲームのシミュレーションを固定間隔で回している最中に、一度止まる → すると: 遅れたステップを1フレームでまとめて計算 → 画面では: 長いフレームが次々と続いて跳ねるか、上限に達して世界全体がスローモーションになる

症状: カクつき, 早送り, スローモーション · 主担当 ゲーム開発チーム・クライアント開発

時刻同期の誤差 Clock sync error

クライアントが推定したサーバー時刻がずれていると、補間のタイミングやクールタイムの判定がずれます。

なぜ: 接続時に一度だけサーバー時刻を合わせ、Pingが変わってもそのまま → すると: 補間するタイミング・クールタイムが終わる時刻がサーバーとずれる → 画面では: 相手がときどき一瞬止まる。クールタイムが終わったのにスキルが拒否される

症状: カクつき, 不発・ロールバック · 主担当 ゲーム開発チーム・クライアント開発

float型で持つ時刻の精度低下 Float time precision loss on long sessions

ゲーム内の時刻を精度の低い小数形式(float)で持っていると、起動したままの時間が長いほど時間分解能(区別できる最小の時間差)が下がり、動きやエフェクトが震えます。

なぜ: ゲーム起動後の経過時間をfloatに積算するか、そのままシェーダーに渡す → すると: 起動したままの時間が長いほど、floatで表せる最小の差が大きくなる → 画面では: 何日も起動したままのクライアントでだけ、キャラクター・アニメーション・流れるエフェクトが小刻みに震え、再起動すると直る

症状: カクつき · 主担当 ゲーム開発チーム・クライアント開発

V-Syncとレンダーキュー V-Sync, render queue

GPUが描画したフレームを何枚かキューにためておき、モニターの周期に合わせて出力する間、入力が遅れます。

なぜ: グラフィックドライバーがフレームを1〜3枚先にキューにためる → すると: 入力が画面に反映されるまで、その分余計に時間がかかる → 画面では: Pingは低いのに、操作が重くもたつく

症状: 入力遅延, カクつき · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 外部・外部

クライアントのメモリリーク Client memory leak

長く起動しておくほどメモリが増えてだんだん重くなり、最後にはゲームが強制終了します。

なぜ: エリアを行き来するたびに、テクスチャ・UI・エフェクトが解放されずに残る → すると: GCが頻繁になり、OSのメモリが足りなくなってスワップが発生 → 画面では: 数時間プレイした後、だんだんカクつくようになり、強制終了(プレイヤーには切断のように見える)

症状: カクつき, 切断 · 主担当 ゲーム開発チーム・クライアント開発

クライアントのクラッシュ Client crash

処理されないエラーでゲームが終了します。プレイヤーには切断のように見えますが、サーバーは正常です。

なぜ: null参照、メモリ不足、グラフィックドライバーのエラー → すると: ゲームプロセスが強制終了 → 画面では: 「落ちた」という報告。同じ時刻、ほかの人は問題ない

症状: 切断 · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 外部・外部

ゲームのセキュリティモジュール(アンチチート)の検査 Anti-cheat scan and heartbeat

チートを防ぐためにゲームと一緒に動くセキュリティモジュールが、定期的に検査を行います。検査が重かったり、セキュリティサーバーとやり取りするハートビート(定期的な生存確認の信号)が遅れたりすると、カクついたり切断されたりします。

なぜ: セキュリティモジュールが定期的に、ゲームのメモリ・実行中のプログラム・ドライバーを検査 → すると: 検査の間ゲームスレッドが止まるか、ハートビートが時間どおりに届かない → 画面では: 一定の間隔で一瞬止まり、ひどいとセキュリティエラーの案内とともに切断

症状: カクつき, フリーズ, 切断 · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

クライアントのOSと端末

ゲームはWindows、Android、iOSの上で、ほかのプログラムとCPU・メモリ・ネットワークを分け合って動いています。OSがゲームへのCPUの割り当てを遅らせたり、バッテリー節約のために速度を落としたり、バックグラウンドのアプリを一時停止させたりすると、ラグになります。

オペレーティングシステム(OS)のスケジューラー(CPUを使う順番を決める機能)が、複数のプログラムにCPU時間を分配します。ゲーム、ウイルス対策ソフト、ブラウザ、アップデートプログラムがみな「自分の番」を待っていて、OSは数msから数十msずつ(タイムスライス)交代でコアを割り当てます。OSは前面に出ているゲーム(フォアグラウンド)の優先度を少し上げてはくれますが、コアの数より処理が多ければゲームも待たされ、その待ち時間がフレームを遅らせます。

ネットワークもOSを通ります。LANカードやWi-Fiチップが受け取ったパケットは、ドライバーとOSの受信バッファに入り、ゲームが取り出すまで待ちます。ゲームが忙しくて取り出すのが遅れるとバッファがあふれ、一気に取り出すと早送りになります。モバイルでは、OSがバッテリーのために無線接続を省電力状態に切り替え、アプリそのものもたびたび一時停止させる点が特に重要です。

たとえ

OSは1つしかない厨房を複数の料理人に交代で使わせる料理長です。ゲームが急ぎの料理を作っていても、ウイルススキャンという料理人がコンロを占領すれば待つしかありません。厨房が熱くなりすぎると(発熱)、火力まで落としてしまいます。

この層でラグを生む原因

バックグラウンドプロセスによるCPU占有 Background CPU contention

ウイルス対策ソフトのスキャン、Windows Update、配信ソフト、ブラウザの動画がコアを占有すると、ゲームスレッドがCPUを割り当ててもらえずに待たされます。

なぜ: 他のプログラムがCPUコアを長時間占有 → すると: ゲームスレッドがスケジューリング待ちになる → 画面では: フレームが遅れ、受信したパケットの処理も遅れる

症状: カクつき, 早送り · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

省電力モード・サーマルスロットリング Power saving, thermal throttling

ノートPCのバッテリーモード、スマホの省電力モード、端末の発熱によって、CPU・GPUの速度が落ちます。発熱の場合は、最初は問題なく、しばらくしてから重くなるのが特徴です。

なぜ: バッテリー・省電力モードか、端末が熱くなっている → すると: CPU・GPUのクロックを、端末によって30〜50%下げる → 画面では: 省電力モードは起動直後から、発熱は数分〜20分ほどプレイした後から、FPSが下がってカクつく

症状: カクつき, 入力遅延 · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

タイマー分解能 Timer resolution (Windows 15.6ms)

Windowsのデフォルトのタイマーは15.6ms単位なので、「1msだけ待つ」が実際には次のタイマー周期まで、長いと15.6msまで延びます。

なぜ: フレームレート制限・パケット送信をSleep(短い待機)で実装 → すると: OSが15.6ms単位でしか起こしてくれない → 画面では: フレーム間隔と入力の送信間隔がばらつく

症状: カクつき · 主担当 ゲーム開発チーム・クライアント開発

モバイルアプリのバックグラウンド移行 App suspended in background

通知を見ようとアプリをいったんバックグラウンドに移すと、OSが数秒後にアプリを一時停止(suspend)し、その間にサーバーは自分を切断します。

なぜ: メッセージの確認・電話でゲームをバックグラウンドに移す → すると: ゲームエンジンがゲームの進行を止め、OSもすぐにアプリとネットワークを停止させる → 画面では: 戻るとすでに切断されていて、再接続

症状: 切断 · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

Wi-Fi ↔ LTE・5Gの切り替え Network switch changes IP

家の外に出てWi-Fiが切れ、LTE・5Gに切り替わると、自分のIPアドレスが変わり、それまでの接続が無効になります。

なぜ: Wi-Fiの電波が弱くなり、モバイル回線に切り替わる → すると: 自分のIPアドレスが変わり、古いアドレスで確立した接続ではもうやり取りできない → 画面では: 少し止まった後に切断、または再接続

症状: フリーズ, 切断 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発, インフラチーム・ネットワークインフラ

セキュリティソフトによるパケット検査 Antivirus / firewall inspection

ウイルス対策ソフト・ファイアウォールがすべてのパケットを検査すると遅延が増え、行き過ぎるとゲームを攻撃と誤認してブロックします。

なぜ: セキュリティソフトが送受信パケットを1つずつ検査 → すると: パケットごとに遅延が加わり、検査が追いつかないと破棄される → 画面では: Pingが不規則に跳ねるか、接続がブロックされる

症状: カクつき, 接続不可・無限ロード · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

受信バッファのあふれ Socket receive buffer overflow

ゲームの処理が忙しく、ソケット(OSが提供するネットワーク送受信のインターフェース)からパケットを取り出すのが遅れると、OSのバッファがあふれます。

なぜ: フレームが遅れ、ゲームがソケットを読むのが遅くなる → すると: OSの受信バッファがいっぱいになり、UDPは破棄され、TCPは受信ウィンドウを縮めて送信側を止めさせる → 画面では: ワープ(UDP)または早送り(TCP)

症状: ワープ, 早送り · 主担当 ゲーム開発チーム・クライアント開発

クライアントのメモリ不足・スワップ Paging / swap on client

ブラウザのタブを数十個開いたままゲームを動かすと、OSがゲームのメモリの一部をディスクに追い出します。

なぜ: 全体のRAMが足りなくなる → すると: OSが今すぐには使わないゲームのメモリをディスクに移す → 画面では: その部分を再び使う瞬間に、ストレージによって数十〜数百ms止まる

症状: フリーズ, カクつき · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

ビデオメモリ(VRAM)不足 VRAM over-commit

グラフィックオプションが必要とするメモリがグラフィックボードのメモリより大きいと、OSがテクスチャをPCのメモリへ追い出してはまた戻すため、カクつきます。

なぜ: 高いテクスチャ設定や、人が多い場所のさまざまな装備・エフェクトで、グラフィックボードのメモリがいっぱいになる → すると: OSが今すぐには使わないテクスチャをPCのメモリに移し、必要になると遅いPCIeバスで再び戻す → 画面では: 新しい場面や新しいキャラクターが見えるたびに一瞬止まり、テクスチャがしばらくぼやける

症状: カクつき, フリーズ · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 外部・外部

Wi-Fiのバックグラウンドスキャン Periodic Wi-Fi background scan

OSが周囲のWi-Fiを探すために定期的にチャンネルを切り替えている間、通信が一瞬止まります。

なぜ: OS・ドライバーが一定周期で周囲のWi-Fiを検索 → すると: 検索している間、送受信が一瞬止まる → 画面では: 正確に一定の間隔(例:60秒ごと)でPingが跳ねる

症状: カクつき, ワープ · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

NICの省電力・ドライバーの問題 NIC power saving, driver bugs

有線LANアダプター・Wi-Fiチップがパケットの合間に省電力状態に入ると、再び動き出すまでに時間がかかります。

なぜ: ネットワークデバイスの省電力機能が有効か、ドライバーが古い → すると: 省電力状態からの復帰(wake-up)の遅延、ときどきデバイスの再起動 → 画面では: 不規則な遅延、まれに数秒止まる

症状: カクつき, フリーズ · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

同じ端末の他のアプリによる帯域幅の占有 Other apps saturating the link

クラウド同期、大容量のダウンロード、ゲームのアップデートが同じPCで動いていると、ゲームのパケットがキューで待たされます。

なぜ: 他のアプリが上り・下りを目いっぱい使う → すると: PCとルーターのキューにゲームのパケットがたまる → 画面では: Pingの急上昇、入力遅延、早送り

症状: 入力遅延, 早送り · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

ウィンドウの最小化・非アクティブ時の処理制限 Minimized / unfocused window throttling

ほかのウィンドウを見たりゲームを最小化したりすると、ゲームとWindowsが電力を節約するためにゲームの処理を遅くします。戻ると遅れていたパケットが押し寄せるか、すでに切断されています。

なぜ: Alt+Tabでほかのウィンドウを見るか、ゲームを最小化 → すると: ゲームが見えない間はFPSを大きく下げるか止め、Windowsも見えないプログラムの優先度を下げる → 画面では: 戻った瞬間に早送り、長くバックグラウンドにしていたら切断

症状: 早送り, カクつき, 切断 · 主担当 ゲーム開発チーム・クライアント開発

オーバーレイソフトの干渉 Overlays and screen hooks

メッセンジャー・ランチャー・録画・FPS表示のソフトが、ゲーム画面の上に自分のUIを重ねて描くため、ゲームのレンダリング処理に割り込みます(フック)。フレームごとの処理が増え、ときどきゲームとぶつかって一瞬止まったり、ゲームが強制終了したりします。

なぜ: メッセンジャー・ゲームランチャー・グラフィックボードのツール・録画ソフトのオーバーレイが有効 → すると: フレームを画面に出力するたびにオーバーレイが割り込み、自分のUIを重ねて描く → 画面では: フレームが少しずつ遅れ、通知が出た瞬間に一瞬止まったり、グラフィックの不具合・強制終了が起きたりする(プレイヤーには切断のように見える)

症状: カクつき, フリーズ, 切断 · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

ディスプレイ・入力デバイス・フレーム生成による遅延 Display, input device and frame generation latency

Pingは正常なのに操作が重いなら、テレビの映像処理やワイヤレスコントローラー、フレーム生成機能が、入力と画面の間に遅延を上乗せしているのかもしれません。

なぜ: テレビのゲームモードがオフ、Bluetooth・ワイヤレスコントローラーを使用、フレーム生成(DLSS・FSRのフレーム生成)が有効、のいずれか → すると: テレビは画質処理をしている間フレームを遅れて出力し、ワイヤレス入力は送信周期と干渉の分だけ遅れて届き、フレーム生成は次のフレームを待ってから中間フレームを作る → 画面では: PingとFPSの数字はよいのに、押してから画面に反映されるまでが遅く、入力遅延になる

症状: 入力遅延 · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

家庭内ネットワーク:Wi-Fi・ルーター・モバイル回線

パケットが家を出る前の最後の数メートルです。距離は短いのに、ラグ報告のかなりの部分がここで生まれます。Wi-Fiは同じ無線チャネルを複数の機器で分け合い、ルーターは家族全員のトラフィックを1つのキューで送り出すからです。

Wi-Fiは同じ無線チャネル(周波数帯)を近所のルーターと分け合い、2.4GHz帯はBluetoothや電子レンジとも重なります。送信中に衝突すると少し待ってから送り直しますが、この再送が重なるとパケットの届く間隔がばらつきます。Pingの平均は問題なさそうに見えても、ときどき瞬間的に跳ねるのがWi-Fiの典型的な姿です。

ルーターは、家の中のすべての機器がインターネットに出るときに必ず通る機器です。インターネット回線が受け付けられる速度より多く送ると、ルーターやモデムの中にキューができます。キュー管理機能(SQM)のない機器は、このキューを数百ms分まで長くためてしまいます。高価なルーターでもこの機能がオフなら同じです。弟が動画をアップロードした瞬間、ゲームのパケットもそのキューの最後尾で待つことになります。この現象をバッファブロートと呼びます。

ルーターはまた、「家の中の機器 ↔ 外のサーバー」の接続をNATテーブルに記録しますが、しばらくパケットのやり取りがないとテーブルから消してしまいます。しばらく放置した後に切断される現象のよくある原因です。モバイル回線ではこれに、基地局の切り替え、無線の省電力状態、弱い電波が加わります。

たとえ

ルーターはマンション団地に1つしかない出入口です。引っ越しトラック(動画のアップロード)が列を作っていると、急ぎのバイク便(ゲームのパケット)もトラックの後ろで待たなければなりません。賢いルーター(SQM)は、バイク便専用の車線を別に開けてくれます。

この層でラグを生む原因

Wi-Fiの干渉・電波の弱さ Wi-Fi interference, weak signal

電波が弱かったり干渉があったりすると、無線区間で何度も送り直すことになり、パケットの到着がばらつきます。

なぜ: 壁・距離・電子レンジ・Bluetooth・近所のルーターによる電波品質の低下 → すると: 無線区間で送信に失敗 → 何度も再送 → 画面では: パケットの到着がばらつき(ジッター)、キャラクターが何度も一瞬止まる。ひどいとパケットロスでワープ

症状: カクつき, ワープ, 引き戻し · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

Wi-Fiチャンネルの混雑 Crowded Wi-Fi channel

マンションのようにルーターが数十台ある場所では、同じチャンネルを分け合って使うため、送信の機会を待つことになります。

なぜ: 数十台のルーターが同じ2.4GHzのチャンネルを使用 → すると: 送信するには、他の機器の送信が終わってチャンネルが空くまで待機 → 画面では: 人が帰宅する夜の時間帯にジッター(到着間隔のばらつき)が増え、カクつき

症状: カクつき, 入力遅延 · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

バッファブロート(ルーターのキュー) Bufferbloat

家族の誰かが動画をアップロードしたり大きなファイルをダウンロードしたりすると、ルーターのキューに数百ms分のパケットがたまり、ゲームのパケットもその後ろで待たされます。

なぜ: 家族の動画アップロード・クラウドバックアップ、自分の配信、大容量ダウンロードで回線がいっぱいになる → すると: ルーターやモデムが、あふれたパケットを大きなキューにためておく → 画面では: ゲームのパケットもキューの後ろで待たされ、Pingが数百msまで急上昇

症状: 入力遅延, 早送り, ワープ · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

NATマッピングの期限切れ NAT mapping timeout

ルーターは、しばらくパケットがやり取りされていないアイドル接続をNATテーブルから削除します。しばらく放置した後、動いた瞬間に切断されるときによくある原因です。

なぜ: ルーターが「内側の機器 ↔ 外側のサーバー」の接続をNATテーブル(アドレス変換表)に記録 → すると: パケットがしばらくないとテーブルから削除(UDPは30〜120秒が多い) → 画面では: サーバーのパケットが家の中に入れず、切断

症状: 切断 · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発

ルーターの性能不足・過熱 Router CPU / session table exhaustion

安価なルーターに数十台の機器、数千の接続が集中すると、ルーター自体が処理しきれなくなります。

なぜ: 数十台の機器、P2P・トレントが数千の接続を開く → すると: ルーターのCPUとセッションテーブルが飽和 → 画面では: パケット処理の遅延・パケットロス、新しい接続の失敗

症状: カクつき, 接続不可・無限ロード, 切断 · 主担当 外部・外部

基地局のハンドオーバー(移動中) Cellular handover

バスや地下鉄で移動すると、基地局が切り替わる間、通信が途切れます。

なぜ: 移動に伴い、接続する基地局が切り替わる → すると: 通常は数十msの空白だが、電波が悪く切り替えに失敗すると数百ms〜数秒途切れることもある → 画面では: 止まった後にワープ、長いと切断

症状: フリーズ, ワープ, 切断 · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発, ゲーム開発チーム・サーバー開発

RRC状態遷移の遅延(モバイル無線の省電力) Radio state promotion (RRC)

スマホはしばらく通信がないと無線接続を低電力状態に落とし、次のパケットのときに再び立ち上げるため遅れます。

なぜ: しばらく通信がないと、スマホが無線接続を省電力状態に切り替える → すると: 次のパケットを送るには、接続を再び立ち上げる必要がある → 画面では: しばらく放置した後の最初の操作だけが特に遅い

症状: 入力遅延 · 主担当 ゲーム開発チーム・クライアント開発

モバイル電波の弱さ・不感地帯 Weak cellular signal

エレベーター・地下・建物の奥では、再送が増えて速度が落ち、最終的に切断されます。

なぜ: 電波の弱い場所へ移動 → すると: 無線区間の再送の増加、速度の低下、瞬断 → 画面では: ジッター・パケットロスでカクつき・ワープ、最終的に切断

症状: カクつき, ワープ, 切断 · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

5G↔LTEの頻繁な切り替え(5Gエリアの境界) 5G NSA / LTE switching

5Gの電波が弱い建物の中や5Gエリアの境界では、スマホが5GとLTEを頻繁に行き来し、切り替わるたびにPingが跳ねたり通信が一瞬途切れたりします。

なぜ: 5Gの電波が不安定な場所(建物の中、5Gエリアの境界)にいる → すると: スマホが5GとLTEの間を頻繁に切り替え、そのたびに短い空白が生じる → 画面では: 動かずにいても不規則にPingが跳ね、ときどきフリーズ・ワープ

症状: カクつき, ワープ, フリーズ · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

公衆Wi-Fi・社内ネットワークの制限 Captive portal, restrictive network

カフェのWi-Fiのログインページや会社のファイアウォールが、ゲームの接続をブロックします。

なぜ: ログインページでの認証前か、ファイアウォールがゲームのポート・UDPを遮断 → すると: 接続の試み自体がブロックされるか、一部だけが通る → 画面では: 接続不可、ログインはできるのにゲームに入れない

症状: 接続不可・無限ロード · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発, ゲーム開発チーム・サーバー開発

インターネット回線:通信事業者網と長距離区間

家を出たパケットは、通信事業者網や複数の通信事業者をつなぐ区間、ときには海底ケーブルを通って、サーバーのあるデータセンターに届きます。この区間の遅延はほとんどが距離と経路の選択(ルーティング)で決まり、ゲーム会社が自分で直せないことが多いです。

光は光ファイバーの中を1秒に約20万km進みます。1,000km離れたサーバーなら往復に最低10msかかり、光ファイバーを使う限り、この数字はサーバーや機器をどれだけ良くしても縮められません。実際のパケットは直線では進まず、通信事業者同士がつながる地点(ピアリング)をたどって回り道をするため、ふつうは理論値の1.5〜2倍かかります。韓国–欧州のように直線上に大きなケーブルがほとんどない区間では、東南アジア・スエズや米国を回るため2.5〜3倍(往復約230〜270ms)になります。

問題は、この経路が時間や状況によって変わることです。夜9〜11時ごろはみんなが動画を見るため通信事業者間の接続区間が混みやすく、経路情報(BGP)が変わると数秒〜数十秒(まれに数分)の間パケットが宛先に届かず、海底ケーブルが切れると数週間にわたって遠い経路に迂回します。「特定の通信事業者のユーザーだけ」「夜だけ」「海外からだけ」ラグが出るなら、まずこの層を疑います。

たとえ

通信事業者網は高速道路網です。ソウルから釜山への道が空いていても距離の分だけ時間はかかり、帰宅ラッシュの料金所(ピアリング区間)は渋滞し、事故が起きればカーナビが遠回りのルートを案内します。

この層でラグを生む原因

伝搬遅延(物理的な距離) Propagation delay

光ファイバーの中では、光でさえ1秒に約20万kmしか進みません。遠いサーバーは、どれほど性能が良くても遅れます。

なぜ: サーバーが遠くにある(海外サーバー、別の大陸) → すると: 距離の分だけ往復時間が延びる(1,000kmあたり最低10ms) → 画面では: すべての操作に一定の入力遅延、判定で不利

症状: 入力遅延 · 主担当 インフラチーム・サーバーインフラ · 副担当 インフラチーム・ネットワークインフラ, ゲーム開発チーム・サーバー開発

衛星インターネット(低軌道・静止軌道) Satellite internet (LEO, GEO)

衛星インターネットは電波が宇宙を往復するため、静止軌道衛星では往復だけで0.5秒を超えます。Starlinkのような低軌道衛星は普段は速いものの、経路を割り当て直す瞬間に遅延が揺れ、一瞬途切れることもあります。

なぜ: 自宅・船・飛行機から、静止軌道衛星や低軌道衛星のインターネット、衛星を使う機内Wi-Fiで接続 → すると: 静止軌道は高度が約36,000kmあり、往復する距離そのものが長い。低軌道は端末・衛星・地上局の経路を短い周期で割り当て直し、その瞬間に遅延・パケットロスが一時的に発生 → 画面では: 静止軌道はすべての操作に大きな入力遅延。低軌道は普段は問題ないが、一定の間隔でカクつき・ワープ

症状: 入力遅延, カクつき, ワープ · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発, ゲーム開発チーム・サーバー開発

迂回ルーティング Suboptimal routing

通信事業者どうしの接続契約の都合で、近いサーバーでも遠くを回って届きます。

なぜ: 自分の通信事業者とサーバー側の通信事業者が直接つながっていない → すると: 別の国や別の都市を経由し、距離と経由する機器が増える → 画面では: 特定の通信事業者のユーザーだけPingが際立って高い

症状: 入力遅延 · 主担当 インフラチーム・ネットワークインフラ · 副担当 外部・外部

ピーク時間帯のピアリング混雑 Peak-hour congestion at peering

夜9〜11時ごろは動画のトラフィックが急増し、通信事業者間の接続区間(ピアリング)が混雑しやすくなります。

なぜ: 夜の時間帯にストリーミング・ダウンロードが集中 → すると: ピアリング区間でキューの滞留とパケットロスが発生 → 画面では: 夜だけ、特定の通信事業者のユーザーにカクつき・ワープ

症状: カクつき, ワープ, 引き戻し · 主担当 インフラチーム・ネットワークインフラ · 副担当 外部・外部

海底ケーブル・国際回線の障害 Submarine cable fault

海底ケーブルが切れると、修理されるまでの数週間(長ければ数か月)は遠い迂回経路を回ることになり、残った回線は混雑します。

なぜ: ケーブルの切断・機器の故障 → すると: トラフィックが遠い迂回経路と残った回線に集中 → 画面では: 海外からの接続者でPingの急上昇とパケットロスが数日〜数週間続く

症状: 入力遅延, ワープ · 主担当 外部・外部 · 副担当 インフラチーム・ネットワークインフラ

BGPの経路変更・収束 Route change / BGP convergence

インターネットの経路情報が変わり、再び収束するまでの数秒〜数十秒(まれに数分)の間、パケットが失われます。

なぜ: どこかの通信事業者の区間で経路情報が変わる → すると: 数秒〜数十秒の間パケットが消えるか、新しい経路に切り替わる → 画面では: 突然数秒止まった後、Pingの値が変わる(例:40→70ms)

症状: フリーズ, ワープ · 主担当 インフラチーム・ネットワークインフラ · 副担当 ゲーム開発チーム・サーバー開発, 外部・外部

ECMP経路のうち1本の不良 ECMP / link bundle member fault

通信事業者やデータセンターは同じ宛先への経路を複数持ち、接続ごとに1本の経路を決めて送ります。1本の経路だけが故障すると、その経路に割り当てられた人だけにラグが出続けます。

なぜ: 複数の回線を束ねた区間で、1本の回線や1台の機器が不良、または混雑 → すると: アドレス・ポートの組み合わせ(ハッシュ)で経路が決まり、その経路に割り当てられた接続だけにパケットロス・遅延 → 画面では: 同じ地域・同じ通信事業者なのに一部の人だけが継続的にワープ。再接続すると直ることもある

症状: ワープ, 引き戻し, カクつき · 主担当 インフラチーム・ネットワークインフラ · 副担当 ゲーム開発チーム・サーバー開発, 外部・外部

通信事業者の速度制限・トラフィック管理 Traffic shaping, data caps

データ使用量の上限を超えた場合や、特定のトラフィックを管理する料金プランでは、パケットが遅らされたり破棄されたりします。

なぜ: 料金プランのデータ容量を使い切った後の速度制限、または特定トラフィックの制限 → すると: パケットが待たされるか破棄される → 画面では: 一定の使用量を超えた後にラグ、特にモバイル

症状: 入力遅延, ワープ · 主担当 外部・外部 · 副担当 ゲーム開発チーム・サーバー開発, インフラチーム・ネットワークインフラ

国・通信事業者単位のUDP制限・パケット検査 UDP blocking, throttling and inspection by networks

一部のネットワークでは、特定のUDPアドレス・ポートをブロックしたりUDPの速度を制限したりし、パケット検査装置が識別できないプロトコルを遮断します。UDPで通信するゲームは、そのネットワークでは接続できなかったり、頻繁に切断されたりします。

なぜ: UDPの速度を制限する一部の通信事業者網や、国・通信事業者単位のトラフィック検査(検閲)装置があるネットワークから接続 → すると: 特定のUDPアドレス・ポートをブロック、混雑する時間帯にUDPの速度を制限、許可リストにないポート・プロトコルを遮断、または最初の数パケットだけ通してからブロック → 画面では: 特定の国・通信事業者のユーザーだけ接続不可・無限ロード、接続してもすぐに切断、混雑する時間帯にパケットロスでワープ

症状: 接続不可・無限ロード, 切断, ワープ · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発, ゲーム開発チーム・サーバー開発, インフラチーム・ネットワークインフラ

回線品質の不良 Faulty last-mile line / modem

端子の接触不良や古いケーブル、モデムの異常は、継続的なパケットロスと周期的な回線断を引き起こします。

なぜ: ケーブルの損傷、接触不良、モデム・ONU(光回線終端装置)の異常 → すると: ビットエラーでパケットが破棄され、ときどき回線の再接続で数秒〜1分ほど途切れることもある → 画面では: 継続的な少量のパケットロス、ときどき数秒のフリーズや切断

症状: ワープ, フリーズ, 切断 · 主担当 外部・外部

DNSの障害・遅延 DNS failure / slowness

サーバー名をアドレスに変換するDNSが遅かったり失敗したりすると、ログインサーバーやアップデートサーバーを見つけられません。

なぜ: 通信事業者のDNSの障害または設定ミス → すると: ログイン・アップデートサーバーのアドレスが見つからない → 画面では: 接続ボタンを押した後に長く待たされるか接続不可。すでに接続している人は問題ない

症状: 接続不可・無限ロード · 主担当 外部・外部 · 副担当 ゲーム開発チーム・クライアント開発

DDoSによる共有回線の飽和 DDoS saturating shared links

ゲーム会社や同じネットワーク内の別の宛先を狙った大量の攻撃が、共有回線を埋め尽くします。

なぜ: 大量の攻撃トラフィックが発生 → すると: 同じ回線を使う正常なトラフィックまで押し出されて破棄される → 画面では: 多くの人が同時にワープ・切断・接続不可

症状: ワープ, 切断, 接続不可・無限ロード · 主担当 インフラチーム・ネットワークインフラ · 副担当 外部・外部

通信事業者の共有IP(CGNAT) Carrier-grade NAT

モバイル回線や一部の通信事業者では、複数の契約者が1つのIPを共有し、アイドル接続のマッピングを短時間で削除します。

なぜ: 通信事業者の機器が膨大な数の契約者のセッションテーブルを管理 → すると: セッションテーブルの上限、短いアイドルタイムアウト → 画面では: しばらく放置した後に切断、同じIPを使う人たちがまとめてブロックされる誤検知

症状: 切断, 接続不可・無限ロード · 主担当 ゲーム開発チーム・クライアント開発 · 副担当 ゲーム開発チーム・サーバー開発, インフラチーム・ネットワークインフラ

VPN・ラグ軽減ツール経由 VPN / game accelerator detour

VPNやラグ軽減ツールを使うと、パケットはその会社の中継サーバーを経由します。中継サーバーが遠かったり混雑していたりすると、かえって遅くなります。

なぜ: VPN・ラグ軽減ツールが、ゲームのパケットをすべて中継サーバーに回す → すると: 中継サーバーまでの距離と混雑が加わり、トンネルのヘッダーのせいでMTU(一度に送れるパケットサイズ)も小さくなる → 画面では: Pingの上昇とパケットロス、同じ中継アドレスを使う人と一緒にブロックされて接続不可

症状: 入力遅延, ワープ, 接続不可・無限ロード · 主担当 外部・外部 · 副担当 インフラチーム・ネットワークインフラ, ゲーム開発チーム・サーバー開発

データセンターのネットワーク機器

サーバーに届く直前、パケットはルーター・DDoS対策装置・ファイアウォール・ロードバランサー・スイッチを順に通過します。ふだんは1msもかからない区間ですが、機器が1台でも容量いっぱいになったり障害が発生したりすると、サーバー全体の数千人が同時に影響を受けます。

それぞれの機器は役割が異なります。ルーターは経路を決め、DDoS対策装置は攻撃トラフィックを取り除き、ファイアウォールは許可された接続だけを通して、すべての接続をセッションテーブルで追跡します。ロードバランサーは入ってきた接続を複数のサーバーに振り分け、スイッチはサーバー同士をつなぎます。

これらの機器に共通する弱点は、テーブルサイズとバッファサイズです。ファイアウォールのセッションテーブルがいっぱいになると新しい接続を受け付けられず、ロードバランサーはアイドル接続を一定時間後に消してしまい、スイッチの小さなバッファは、複数のサーバーが同じ瞬間に数千人へ一気にパケットを送ると(ワールドボスの出現など)1msもたたずにあふれます。さらに、機器が1台故障して予備機に切り替わる(フェイルオーバー)数秒の間は、全員が止まります。

たとえ

データセンターの入口は空港の保安検査場と搭乗ゲートです。検査場(ファイアウォール)は名簿にある人だけを通し、名簿の欄が埋まるとそれ以上受け付けられません。ゲートの係員(ロードバランサー)は、長い間じっと座っている乗客を「立ち去った人」とみなして名簿から消します。

この層でラグを生む原因

ファイアウォールのセッションテーブル飽和 Firewall session table exhaustion

ファイアウォールは、通過させたすべての接続をセッションテーブルに記録して追跡します。テーブルがいっぱいになると、新しい接続を受け付けられなくなります。

なぜ: 接続の殺到や攻撃でセッション数が上限に到達 → すると: 新しい接続を記録する空きエントリがなく拒否 → 画面では: 新たに入ろうとする人は接続不可・無限ロード、一部の既存の接続も切断

症状: 接続不可・無限ロード, 切断 · 主担当 インフラチーム・ネットワークインフラ · 副担当 ゲーム開発チーム・サーバー開発, ゲーム開発チーム・クライアント開発

DDoS対策の経由・誤検知 DDoS scrubbing latency, false positives

攻撃を防ぐためにトラフィックをスクラビングセンターに回すと経路が長くなり、正常なユーザーを攻撃と誤認してブロックすることもあります。

なぜ: 攻撃の検知後(または常時)、入ってくるトラフィックをスクラビングセンターに迂回 → すると: 経路が長くなり、一部の正常なパケットを攻撃と判定 → 画面では: 全体のPingが上昇、特定の地域・通信事業者だけ接続不可

症状: 入力遅延, 接続不可・無限ロード, ワープ · 主担当 インフラチーム・ネットワークインフラ · 副担当 ゲーム開発チーム・サーバー開発

ロードバランサーのアイドルタイムアウト Load balancer idle timeout

ロードバランサーは、アイドル状態の接続を一定時間後に削除します。ゲーム側は接続が維持されているものとみなしているうちに、切断されてしまいます。

なぜ: プレイヤーがしばらくパケットを何も送らない(会話ウィンドウ、離席) → すると: ロードバランサーがアイドル接続を整理(よくあるデフォルト値は60〜350秒) → 画面では: 再び動いた瞬間に切断

症状: 切断 · 主担当 インフラチーム・ネットワークインフラ · 副担当 ゲーム開発チーム・クライアント開発, ゲーム開発チーム・サーバー開発

クラウドのセキュリティグループによる接続追跡の期限切れ Cloud security group connection tracking timeout

クラウドのサーバーに付いているファイアウォール(セキュリティグループ)も接続を追跡し、アイドル接続の追跡エントリは決められた時間の後に期限切れになります。ロードバランサーを通さずに直接つなぐサーバーでも、しばらく放置していたプレイヤーが切断されることがあります。

なぜ: セキュリティグループがゲームの接続を追跡する設定(特定のアドレスだけ許可、アウトバウンドルールの制限、NLB経由など) → すると: しばらくアイドル状態だった接続の追跡エントリが期限切れになり、その後に届いたパケットをセキュリティグループが黙って破棄 → 画面では: 離席後に再び動くと反応がないまま切断。サーバープログラムはしばらく気づかない

症状: 切断 · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・クライアント開発, ゲーム開発チーム・サーバー開発

クラウドのNATゲートウェイの接続・ポート上限 Cloud NAT gateway connection / port limits

プライベートサブネットのサーバーから外部(プラットフォーム認証・決済・外部API)への接続は、NATゲートウェイがアドレスとポートを変換して送り出します。同じ宛先への同時接続がゲートウェイのポート上限を超えると、新しい接続が失敗します。

なぜ: サーバー群が、プラットフォーム認証・決済のような同じ外部アドレスへ短い接続を大量に開くか、接続を長く開いたままにする → すると: NATゲートウェイがその宛先に使う送信元ポートをこれ以上割り当てられず、新しい接続が失敗 → 画面では: ゲーム内は問題ないのに、ログイン・決済・報酬付与のように外部を呼び出す機能だけが失敗するか遅れる(接続不可・無限ロード、不発・ロールバック)

症状: 接続不可・無限ロード, 不発・ロールバック · 主担当 インフラチーム・ネットワークインフラ · 副担当 ゲーム開発チーム・サーバー開発

ロードバランサーの偏り・ヘルスチェックの誤判定 LB imbalance, bad health checks

接続が1台のサーバーだけに集中したり、すでに落ちたサーバーに人を送り続けたりします。

なぜ: 振り分けルールが合っていないか、ヘルスチェックが実際の状態を捉えられていない → すると: 1台のサーバーだけが過負荷、または落ちたサーバーへの接続試行 → 画面では: 一部のチャンネル・一部の人だけスローモーション、接続不可・無限ロード

症状: スローモーション, 接続不可・無限ロード · 主担当 インフラチーム・ネットワークインフラ · 副担当 ゲーム開発チーム・サーバー開発

スイッチのマイクロバースト Switch microburst drops

複数のサーバーが同じ瞬間に数千人へ一斉にパケットを送ると、そのトラフィックが集まるスイッチポートの小さなバッファが1ms足らずであふれます。

なぜ: ワールドボスの出現・大規模スキル、または複数サーバーのティックが同じ瞬間に重なって一斉に送信 → すると: 複数のポートが1つのポートに集まる場所や、速いポートから遅いポートへ渡る場所のバッファ(ポートあたり数百KB〜数MB)が瞬間的にいっぱいになる → 画面では: 一部のパケットが破棄され、多くの人が同時にワープ・スキル不発

症状: ワープ, 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・ネットワークインフラ, インフラチーム・サーバーインフラ

データセンター回線の飽和 Uplink saturation

アップデートデータの配信・ログ転送・バックアップがゲームと同じ回線を使うと、回線がいっぱいになります。

なぜ: 大容量の転送が同じ回線を占有 → すると: 回線のキューとパケットロスが増加 → 画面では: サーバー全体でPingの上昇とワープ

症状: 入力遅延, ワープ · 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ

ネットワーク機器のフェイルオーバー Network device failover

ルーター・ファイアウォールの1台が故障して予備機に切り替わる(フェイルオーバー)数秒の間、全員が止まります。

なぜ: 機器の故障またはメンテナンスで予備機に切り替え → すると: 切り替えに数秒、セッション情報が同期されていなければ接続がリセットされる → 画面では: サーバーの全ユーザーが同時にフリーズ、大量の切断

症状: フリーズ, 切断 · 主担当 インフラチーム・ネットワークインフラ · 副担当 ゲーム開発チーム・サーバー開発, ゲーム開発チーム・クライアント開発

ケーブル不良・ポートエラー Bad cable / optics (CRC errors)

光モジュールやケーブルが不良だと、その経路を通るパケットが一定の割合で壊れます。

なぜ: 光モジュール・ケーブルの不良でビットエラー → すると: 壊れたパケットは機器が黙って破棄 → 画面では: その経路を使う一部のサーバー・ユーザーだけが、継続的なパケットロスでワープ・引き戻し

症状: ワープ, 引き戻し · 主担当 インフラチーム・ネットワークインフラ

MTUの不一致(大きなパケットだけ消える) MTU black hole

途中の区間のMTU(一度に送れるサイズ)が小さくなっているのにサイズ超過の通知がブロックされると、大きなパケットだけが消え続けます。

なぜ: トンネル・VPNの区間でMTUが小さくなる → すると: サイズ超過の通知(ICMP)がファイアウォールでブロックされ、送信側が気づかない → 画面では: インベントリ・キャラクター一覧のような大きな画面を開いたときだけフリーズした後に切断

症状: フリーズ, 切断, 接続不可・無限ロード · 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ, ゲーム開発チーム・サーバー開発

サーバーのネットワークカード(NIC)

サーバーに挿さったネットワークカードは、1秒に数十万〜数百万個のパケットを受け取ってCPUに渡します。ここで処理が追いつかないと、サーバープログラムはパケットが届いたことすら知らないまま失います。

NICは届いたパケットをリングバッファ(決まった数のスロットを使い回す受信バッファ)に順に入れ、CPUに「パケットが来ました」と知らせます(割り込み)。CPUはリングバッファからパケットを取り出してOSに渡します。CPUが取り出す速度より速く入ってくるとスロットがすべて埋まり、その後に届いたパケットは破棄されます。ネットワークカードの統計(ethtool -S)の数字が黙って増えるだけで、ゲームサーバーのログには何のエラーも残らないため、見つけにくいラグです。

最近のNICには、受信キュー(リングバッファ)を複数持ち、複数のCPUコアに振り分けて知らせる機能(RSS)がありますが、設定されていなかったりトラフィックが1つのキューに偏ったりすると、1つのコアだけが100%になってボトルネックになります。クラウドのサーバーなら、NICの手前に1秒あたりのパケット数・帯域幅・接続数の上限が別にあり、超えた分はサーバーに届く前に破棄されます。CPUやリングバッファのようなふだんのメトリクスには現れず、AWSならENAドライバーの統計(ethtool -Sのpps_allowance_exceededなど)にだけ残ります。

たとえ

NICはマンションの郵便受け、リングバッファは郵便受けの区画の数、割り込みは配達員が鳴らすチャイムです。郵便物が大量に届いているのに取り出す人が1人しかいなければ、区画があふれて手紙が床に落ちます。RSSは取り出す人を複数置くことです。

この層でラグを生む原因

NIC割り込みの単一コア集中 Single-queue NIC / no RSS

NICがパケット到着の割り込みを1つのCPUコアにだけ送ると、そのコアがボトルネックになります。

なぜ: 受信キューが1つだけか、複数のコアに分散するRSSが無効 → すると: 1つのコアが100%になり、パケットを時間内に取り出せない → 画面では: 人が集中したときにサーバー全体でパケットロスと遅延(ワープ・入力遅延)

症状: ワープ, 引き戻し, 入力遅延 · 主担当 インフラチーム・サーバーインフラ

リングバッファ不足 RX ring buffer overflow

NICがパケットを一時的に入れておくリングバッファが小さいと、瞬間的に集中したときにバッファがあふれて破棄されます。

なぜ: リングバッファがデフォルト値(ドライバーごとにスロット256〜2,048個)のままで小さい → すると: バースト時にCPUが取り出す前にバッファがあふれる → 画面では: バーストの瞬間だけパケットロス(ワープ・スキル不発)。ゲームサーバーのログには痕跡がない

症状: ワープ, 不発・ロールバック · 主担当 インフラチーム・サーバーインフラ

過剰な割り込みコアレッシング Interrupt coalescing

CPUの負担を減らすために、パケットをまとめてから一度に知らせると、まとめる時間の分だけ遅れます。

なぜ: NICが一定の時間・個数だけまとめてから通知 → すると: まとめている間、パケットが待たされる → 画面では: わずかな遅延の増加。通常は小さいが、過剰だとms単位

症状: 入力遅延 · 主担当 インフラチーム・サーバーインフラ

クラウドのPPS上限超過 Cloud PPS / bandwidth allowance

クラウドのサーバーには種類ごとに毎秒のパケット数・帯域幅の上限があり、超えると黙って破棄されます。

なぜ: 同時接続数が増えて、毎秒のパケット数がインスタンスの上限を超える → すると: クラウドのネットワークが超過分を破棄 → 画面では: 原因のわからないパケットロスでワープ・スキル不発。サーバーのCPUには余裕がある

症状: ワープ, 不発・ロールバック · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発, 外部・外部

NIC帯域幅の飽和 NIC bandwidth saturation

1Gbps・10Gbpsのカードを限界まで使うと、送信キューが長くなり、最終的に破棄されます。

なぜ: ブロードキャストの増加で送信量がカードの限界に到達 → すると: 送信キューが長くなり、あふれると破棄 → 画面では: サーバー全体で遅延・パケットロス(入力遅延・ワープ)

症状: 入力遅延, ワープ · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

仮想化オーバーヘッド・ノイジーネイバー Noisy neighbors in virtualization

同じ物理サーバー上のほかの仮想マシンがネットワーク・CPUを大量に使うと、自分のサーバーの処理が不規則に遅れます。

なぜ: 同じ物理サーバー上のほかの仮想マシンがリソースを大量に使用 → すると: 自分の仮想マシンのパケット処理が不規則に遅れる → 画面では: はっきりした原因がないのに、ときどきジッター(到着間隔のばらつき)が生じてカクつき

症状: カクつき · 主担当 インフラチーム・サーバーインフラ · 副担当 外部・外部

クラウドホストのメンテナンス・ライブマイグレーション Cloud host maintenance / live migration

クラウド事業者は物理サーバー(ホスト)をメンテナンスするとき、仮想マシンを別のホストに移したり(ライブマイグレーション)、一時的に止めたりします。その間はサーバー全体が止まり、止まる時間が長いと接続が切れます。

なぜ: 事業者がホストのメンテナンスや故障予測のために、仮想マシンを別のホストに移すか一時停止 → すると: 移している間はCPU・メモリ・ネットワークが遅くなり、最後に仮想マシンが一瞬完全に止まる(事業者と方式によって1秒未満〜30秒前後) → 画面では: サーバーの全員が同時にフリーズした後に早送り・ワープ、停止がタイムアウトより長ければ大量の切断

症状: フリーズ, 早送り, ワープ, 切断 · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発, 外部・外部

NICドライバー・ファームウェアの問題 NIC hang / reset

ドライバーのバグや機能の誤動作でカードが止まり、再起動している間はすべての送受信が途切れます。

なぜ: ドライバーのバグ、オフロード機能の誤動作 → すると: NICが止まって再起動(数秒) → 画面では: そのサーバーの全員が一緒にフリーズした後、ワープするか切断

症状: フリーズ, 切断 · 主担当 インフラチーム・サーバーインフラ

GRO/LROの結合待ちによる遅延 GRO/LRO batching

複数のパケットを1つにまとめてCPUの負担を減らす機能です。設定によっては、小さなゲームのパケットが、一緒にまとめる次のパケットを少し待つことがあります。

なぜ: NIC・カーネルが到着したパケットをまとめて処理 → すると: ハードウェアによる結合(LRO)や結合の待ち時間の設定が有効だと、次のパケットを待って少し待機 → 画面では: わずかな遅延の増加(たいてい数十µs以下)

症状: 入力遅延 · 主担当 インフラチーム・サーバーインフラ

サーバーOS(カーネル)

サーバーのLinux・Windowsカーネルは、接続を受け付け、ソケットバッファを管理し、CPUとメモリをゲームサーバープログラムに分配します。ほとんどのデフォルト値はさまざまな用途に広く合わせた保守的な値なので、数万人が長時間接続し続けるゲームサーバーにはそのままでは合わないことが多いです。

新しい接続が来ると、カーネルは接続要求を接続待ちキュー(backlog)に入れておき、ゲームサーバーが1つずつ受け取ります。キューがいっぱいになると、Linuxは新しい要求を黙って破棄し、Windowsは拒否の応答を返します。Linuxでは接続ごとに、開いたファイルや接続に付く番号であるファイルディスクリプタ(fd)が1つずつ必要で、1つのプロセスが持てるfdの数にも上限があります。メンテ明けに数万人が同時に接続ボタンを押すと、接続待ちキューとfdが真っ先に尽きます。

カーネルはまた、メモリが足りなくなるとディスクに追い出し(スワップ、有効にしている場合)、Linuxは本当に尽きるとメモリを最も多く使っているプロセスを選んで強制終了させます(OOM Killer)。ゲームサーバーはたいていそのサーバーで最もメモリを使うプロセスなので、真っ先に終了の対象になります。コンテナにメモリ上限を設定していれば、サーバー全体には余裕があっても上限に達した瞬間に同じことが起きます。時刻同期(NTP)、定期ジョブ、コンテナのCPU上限、仮想マシンのCPUスチール(ほかの仮想マシンが物理CPUを使っている間の待ち時間)のように、ゲームとは関係なさそうな処理も、サーバーをときどき短時間止めたりタイマーをずらしたりします。

たとえ

サーバーOSは遊園地の入場ゲートと管理事務所です。開園時間(メンテ終了)に全員が押し寄せるとゲート前の列(backlog)があふれ、配るリストバンド(ファイルディスクリプタ)がなくなるとそれ以上入れません。

この層でラグを生む原因

接続待ちキュー(backlog)のあふれ Listen backlog / SYN queue overflow

メンテ明けに数万人が同時に接続すると、カーネルの接続待ちキュー(backlog)があふれ、接続要求が破棄されます。

なぜ: メンテ終了と同時に、ゲームサーバーがacceptで接続を処理する速度を上回る勢いで接続が殺到 → すると: カーネルの接続待ちキュー(backlog。サーバーのコードがlistenに渡した値とカーネルの上限のうち小さいほう)が満杯 → 画面では: 接続要求が破棄されて再試行が繰り返され、接続不可・無限ロード

症状: 接続不可・無限ロード · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ, ゲーム開発チーム・クライアント開発

ファイルディスクリプタの上限 File descriptor limit (ulimit)

接続ごとにファイルディスクリプタ(fd。OSが開いているファイルやソケットに付ける番号)が必要ですが、1つのプロセスが開けるfdの数には上限があります。

なぜ: 同時接続数がプロセスのファイルディスクリプタ上限に到達 → すると: サーバーが新しい接続を受け付けられない(Too many open files)。ログファイルやDB接続を開く処理も同時に失敗 → 画面では: ちょうど一定の人数から先は誰も入れない接続不可・無限ロード

症状: 接続不可・無限ロード · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発

カーネルのソケットバッファ不足 Small socket buffers

送受信バッファが小さいと、バーストトラフィックが集中したときに、UDPで受信したパケットは破棄され、TCPの送信はバッファに空きがなくブロックされます。

なぜ: SO_SNDBUF・SO_RCVBUFがデフォルト値のまま、または小さすぎる → すると: バーストや、受信スレッドが一瞬止まった間にUDPの受信バッファがあふれて破棄、TCPは送信バッファに空きがなく待機 → 画面では: ワープ(UDPのパケットロス)または早送り(TCPの待機)

症状: ワープ, 早送り · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発

スレッド過多とコンテキストスイッチ Thread oversubscription, context switching

コア数よりはるかに多いスレッドを動かすと、OSがそれらを切り替えて実行するだけでCPUを消費します。

なぜ: 接続ごとにスレッドを作るなどして、スレッドが数百〜数千個 → すると: コンテキストスイッチ(実行するスレッドの切り替え)のコストとキャッシュミスが増加 → 画面では: CPUはビジーなのにスループットは低く、ティックがばらついてカクつき・スローモーション

症状: カクつき, スローモーション · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

CPUスチール(仮想マシン) CPU steal time

物理サーバー(ハイパーバイザー)が仮想マシンのCPU時間を一時的にほかの仮想マシンに回している間(CPUスチール)、ゲームサーバーが止まります。

なぜ: 同じホスト上のほかの仮想マシンがCPUを大量に使用 → すると: 自分の仮想マシンが数ms〜数十msずつ実行機会を失う → 画面では: 原因不明のティック時間の急増で、カクつき・フリーズ

症状: カクつき, フリーズ · 主担当 インフラチーム・サーバーインフラ · 副担当 外部・外部

コンテナのCPUスロットリング(CFSクォータ) Container CPU throttling (CFS quota)

コンテナにCPU上限をかけると、決まった周期(通常100ms)の中でクォータを使い切った時点から、残りの時間は強制的に止められます(スロットリング)。

なぜ: Kubernetesなどで、ゲームサーバーのコンテナにCPU上限(limit)を設定している → すると: ティックの計算が集中した瞬間にクォータを使い切り、次の周期まで数十ms停止 → 画面では: 平均CPUは低いのにティックが周期的に跳ねて、カクつき・スローモーション

症状: カクつき, スローモーション · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発

サーバーの電源管理(C-state・周波数制御)による遅延スパイク CPU power management latency (C-states, frequency scaling)

使われていないCPUコアは、電力を節約するために深い省電力状態(C-state)に入り、周波数も下げます。パケットやタイマーが来ると、復帰して周波数を上げるまでに時間がかかるため、小さなパケットの処理に遅延が加わります。

なぜ: OSの周波数制御ポリシー(governor)やBIOSの電源設定が、深いC-stateと低い周波数を許可している → すると: 休んでいたコアが深い省電力状態から復帰するたびに最大数百µs遅れ、周波数が低く固定されているとティックの計算自体が遅くなる → 画面では: 普段は体感しにくいが、サーバー間の呼び出しが多いと積み重なり、空いているときにかえって応答が遅くなる入力遅延。周波数が低く固定されていると、人が集中したときにティックが遅れてスローモーション

症状: 入力遅延, スローモーション · 主担当 インフラチーム・サーバーインフラ

OOM Killer Out-of-memory killer

Linuxはメモリが尽きると、メモリを最も多く使っているプロセスを選んで強制終了します。たいていはゲームサーバーです。

なぜ: リークや急増でメモリが枯渇、またはコンテナのメモリ上限に到達 → すると: カーネルがゲームサーバーのプロセスを強制終了 → 画面では: そのサーバーの全員が同時に切断、直近の進行がロールバックされることもある

症状: 切断, 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

メモリの回収・コンパクションによる停止 Memory compaction / reclaim stalls (THP)

OSがヒュージページ(huge page)を作るためにメモリをコンパクションしたり、空きメモリを回収したりしている間、プロセスが止まります。

なぜ: 空きメモリが減る、またはヒュージページ機能(THP)がメモリのコンパクションを実行 → すると: メモリを要求したスレッドが、回収・コンパクションが終わるまで待機 → 画面では: 不規則なサーバーの停止(数ms〜数百ms)

症状: フリーズ, カクつき · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発

システム時刻のジャンプ(NTPステップ) Wall-clock jump (NTP step)

サーバーの時刻が一度に数秒前後に調整されると、システム時刻に依存するタイマーが一斉に発火したり止まったりします。

なぜ: 時刻同期が時刻を一度に大きく調整 → すると: タイマーがまとめて発火したり止まったりし、タイムアウトが誤って判定される → 画面では: バフ・クールタイムの異常、一斉に切断、早送り

症状: 早送り, 切断, 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

定期実行ジョブ Cron jobs (log rotation, backup, scans)

毎日同じ時刻に動くログ圧縮・バックアップ・セキュリティスキャンが、CPUとディスクを占有します。

なぜ: 決まった時刻にOSのジョブが実行される → すると: CPU・ディスクをゲームサーバーと取り合う → 画面では: 毎日早朝4時のように、決まった時刻にカクつき・スローモーション

症状: カクつき, スローモーション · 主担当 インフラチーム・サーバーインフラ

OS・カーネル・ドライバー・ファームウェアのアップデート後の性能変化 Performance regression after OS / kernel / driver / firmware update

ゲームのコードは変わっていないのに、サーバーのOS・カーネル・ドライバー・ファームウェアをアップデートしてから遅くなるケースです。アップデートによって、デフォルト値、スケジューラー、CPU脆弱性の緩和策(mitigations)、ドライバーの動作が変わることがあります。

なぜ: 定期的なセキュリティパッチや新しいサーバーイメージで、カーネル・ドライバー・ファームウェアが変わる → すると: デフォルト値やスケジューラーが変わったり新しい脆弱性の緩和策が有効になったりして、同じ処理により多くのCPU時間がかかり、スレッドにCPUが割り当てられる順序も変わる → 画面では: 問題なかったサーバーがアップデートした日から常に少し遅くなって入力遅延、人が集中するとカクつき・スローモーション

症状: 入力遅延, カクつき, スローモーション · 主担当 インフラチーム・サーバーインフラ

サーバーのconntrackテーブル飽和 conntrack table full

Linuxのファイアウォールがすべての接続を記録する接続追跡(conntrack)テーブルが上限に達すると、新しいパケットを破棄します。

なぜ: 接続の殺到や短い接続の繰り返しで、接続の記録が増加 → すると: テーブルが満杯になり、新しい接続と一部のパケットを破棄 → 画面では: 接続不可、原因不明のパケットロスでワープ

症状: 接続不可・無限ロード, ワープ · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発, ゲーム開発チーム・クライアント開発

サーバー間接続のエフェメラルポート枯渇 Ephemeral port exhaustion (TIME_WAIT)

ゲームサーバーがDBやほかのサーバーへの接続を短時間で頻繁に張っては切ると、切れた接続がしばらくポートを占有し、新しい接続を開けなくなります。

なぜ: リクエストごとに新しい接続を開いて閉じる → すると: 先に閉じた側が約60秒(Linux)の間ポートを占有し(TIME_WAIT)、使えるポートが尽きる → 画面では: 内部リクエストが失敗し、保存の失敗・機能のエラー

症状: 不発・ロールバック, 接続不可・無限ロード · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

ソケットとプロトコル:TCP、UDP、ソケットオプション

ゲームがネットワークでデータをやり取りする方法を決める部分です。同じ回線でも、どのプロトコルを使い、ソケットオプションをどう設定するかによって、パケットを1つ失ったときに「一瞬引っかかる」だけで済むこともあれば、「1秒止まってから一気に動く」ことにもなります。

TCPは、送った順番どおりに漏れなく届けることを保証します。その代わり、1つでも失うと、再び受け取るまでは後から届いたものまですべてゲームに渡さずに待ちます。UDPは何も保証しません。届いたものは待たずにすぐ渡しますが、失ったものはゲーム側で処理しなければなりません。そのため、アクション性の強いゲームはUDPの上に必要な分だけ信頼性を自前で実装し(信頼性UDP)、多くのMMOは実装が簡単なTCPを使って、その弱点を受け入れています。

ソケットオプションは、この動作の細かい設定です。小さなパケットをまとめてから送るか(TCP_NODELAY)、送受信バッファをどれだけ確保するか(SO_SNDBUF、SO_RCVBUF)、死んだ接続にいつ気づくか(SO_KEEPALIVE、TCP_USER_TIMEOUT)、閉じるときに残ったデータをどうするか(SO_LINGER)。デフォルト値はほとんどが、大きなデータを少ないパケットで効率よく送る方向に合わせてあるため、小さなパケットを頻繁にやり取りするゲームには不利なことが多いです。

ポイント

TCPは受け取ったデータを送られた順番どおりにしかゲームに渡しません。17番のパケットが消えると、18〜30番がすでに届いていても、17番が再び届くまで全部待ちます(HOLブロッキング)。UDPは届いた順に渡すので、17番が最後まで届かなくても、残りは時間どおりに処理されます。

再送がなぜ起きるのか(Wi-Fi、輻輳、MTUブラックホール、不要な再送など)と原因の探し方は、06 TCP再送で原因ごとに扱います。

この層でラグを生む原因

TCPのHOLブロッキング Head-of-line blocking

TCPは順序を守るため、失われたパケットを1つ受け取り直すまで、後から届いたパケットをゲームに渡しません。

なぜ: パケットが1つ消失 → すると: 後続のパケットは届いているが、受信バッファで待機 → 画面では: 止まった後に一気に解放されて早送り

症状: フリーズ, 早送り · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

TCPのRTOと指数バックオフ RTO and exponential backoff

再送がまた失敗するたびに待ち時間が2倍に延びるため、短い回線断が長い停止になります。

なぜ: 回線が一瞬切れて、再送も続けて失敗 → すると: 次の試行までの時間が0.3 → 0.6 → 1.2 → 2.4秒のように2倍ずつ延びる(Ping 100msの場合) → 画面では: 回線が切れたのは1秒なのに、ゲームは2秒以上止まる。さらに長く切れると最終的に切断

症状: フリーズ, 切断 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

Nagleアルゴリズム+遅延ACK Nagle + delayed ACK (TCP_NODELAY off)

小さなパケットをまとめて送るNagleアルゴリズムと、ACKを遅らせて送る遅延ACKがかみ合い、メッセージを分けて書き込むたびに40〜200msずつ遅延します。

なぜ: TCP_NODELAYを有効にしないまま、小さなメッセージを分けて書き込む → すると: 送信側はACKを待ち、受信側はACKを遅らせて送る → 画面では: 回線のPingは低いのに、すべての操作が一様にもたつく入力遅延

症状: 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

遅いクライアントによるブロッキング送信 Blocking send on a full socket

回線の遅い1人の送信バッファが満杯なのに、ブロッキング方式(バッファに空きができるまで呼び出しが戻らない送信)で送ると、サーバーのスレッドがその1人を待ちます。

なぜ: 遅いクライアントの送信バッファが満杯 → すると: ブロッキング送信のため、サーバーのスレッドがバッファに空きができるまで待機 → 画面では: そのスレッドが担当する全員がフリーズ・スローモーション

症状: フリーズ, スローモーション · 主担当 ゲーム開発チーム・サーバー開発

遅いクライアント(slow consumer)の処理ポリシー Slow-consumer policy

送るデータがたまり続けるクライアントに対して、サーバーが古い更新を破棄したり接続を切ったりします。

なぜ: クライアントの回線が、サーバーが送る量に追いつかない → すると: サーバーが古い更新を破棄するか、上限を超えたら接続を切断 → 画面では: その人だけワープまたは切断

症状: ワープ, 切断 · 主担当 ゲーム開発チーム・サーバー開発

keepaliveのデフォルト2時間 TCP keepalive defaults

相手が終了の合図なしに消えると、TCPはかなり時間がたってから検知します。keepalive(アイドル接続が生きているかを確認するTCPの機能)はデフォルトで無効で、有効にしても2時間アイドル状態が続かないと確認を始めません。

なぜ: クライアントが電源断や回線断で、終了の合図なしに消える → すると: サーバーは接続が生きているとみなす(keepaliveのデフォルトは7,200秒。送信中のデータがあれば再送をあきらめるまで約15分) → 画面では: キャラクターがゴーストとして残り、再接続すると「すでに接続中」エラー

症状: 接続不可・無限ロード, 表示されない・ゴースト · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発, インフラチーム・サーバーインフラ

UDPパケットのIPフラグメンテーション IP fragmentation of large UDP

MTU(一度に送れるサイズ)を超えるUDPパケットはIP層でフラグメント化され、フラグメントを1つ失うだけでパケット全体が破棄されます。

なぜ: 人の多い場所のスナップショットが1,500バイトを超える → すると: 複数のフラグメントに分割して送信、1つでも失うと全体を破棄 → 画面では: 大きなパケットほどロス率が数倍になる。混雑した場所でだけワープ

症状: ワープ · 主担当 ゲーム開発チーム・サーバー開発

信頼性UDPの再送設定 Reliable-UDP tuning (KCP, ENet…)

UDPの上に独自に作った再送ルールが保守的すぎると復旧が遅れ、攻撃的すぎると回線をさらに詰まらせます。

なぜ: 再送の間隔・回数・ウィンドウサイズの設定が回線に合っていない → すると: 復旧の遅れ、または重複送信による輻輳の悪化 → 画面では: スキル不発、早送り、輻輳時にさらにひどいラグ

症状: 不発・ロールバック, 早送り · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

アイドル後のスロースタート Slow start after idle

TCPはしばらくアイドル状態が続くと輻輳ウィンドウ(一度に送れる量)を再び縮めるため、急に大きなデータを送るときに何回かに分けて送ります。

なぜ: アイドル状態だった接続で、街への入場など大きなデータを送る → すると: 輻輳ウィンドウが縮んでいるため、複数の往復に分けて送信 → 画面では: 入場直後、周りのキャラクターやNPCが往復数回分遅れて表示される(遠いサーバーほど目立つ)

症状: 入力遅延, 表示されない・ゴースト · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発

輻輳制御による送信量の急減 Congestion control backoff

TCPはパケットロスを輻輳のシグナルとみなし、送信速度を30〜50%落とします。Wi-Fiでのパケットロスにも同じように反応します。

なぜ: 送る量が多いときに、Wi-Fiや回線でわずかなパケットロスが発生 → すると: TCPが送信速度を大きく落とし、ゆっくり回復(Linux・WindowsのデフォルトであるCUBICは30%落とす) → 画面では: 人の多い場所で更新が遅れて早送り・入力遅延

症状: 早送り, 入力遅延 · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発

RSTによる強制終了で最後のデータが消失 SO_LINGER, abrupt RST

サーバーが接続を急に切ると、最後に送った案内や保存完了の通知が失われます。

なぜ: サーバーが接続を強制終了(RST)で閉じる。SO_LINGERを0秒にしたり、受信したデータを読み切らずに閉じたりすると起きる → すると: まだ送信中だったキックの理由や最後のデータが破棄される → 画面では: 理由の分からない「不明なエラーにより接続が切断されました」

症状: 切断 · 主担当 ゲーム開発チーム・サーバー開発

ブロッキングI/O構造 Blocking I/O model

1つのソケットを待っている間、スレッドがほかの処理をできない構造では、人が増えるほど全体が遅くなります。

なぜ: 接続ごとに読み書きを待つ方式 → すると: 1つの接続の遅延が、同じスレッドのほかの接続に波及 → 画面では: 同時接続数が増えるほど、全体がスローモーション・入力遅延

症状: スローモーション, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発

SO_REUSEPORTの振り分けの偏り SO_REUSEPORT imbalance, stuck worker

同じポートを複数のプロセスで分担して受け付けると、カーネルは接続ごとにアドレスのハッシュで担当プロセスを決め、その後は変更しません。担当プロセスが1つ止まると、そこに割り当てられた人だけが待たされます。

なぜ: ゲートウェイ・ログインサーバーがSO_REUSEPORTで複数のプロセスを起動 → すると: 1つのプロセスがGCや過負荷で止まっても、そこに割り当てられた新しい接続とUDPパケットはほかのプロセスに回されない → 画面では: 一部の人だけ接続不可・フリーズ。プロセス数が変わる再起動時には、一部のUDPセッションが切れる

症状: 接続不可・無限ロード, フリーズ, 切断 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

WindowsのUDPソケットのWSAECONNRESETエラー WSAECONNRESET on a Windows UDP socket

Windowsサーバーがすでに去ったクライアントにUDPを送ると、「ポート到達不能」(ICMP)の通知が返ってきます。その通知のせいで次の受信呼び出しがエラーで終わりますが、サーバーのコードがこのエラーをソケット自体の故障として扱うと、そのソケットを使っている全員が影響を受けます。

なぜ: 出ていったばかりのクライアントのアドレスにUDPを送り続け、「ポート到達不能」(ICMP)の通知が返ってくる → すると: Windowsが次の受信呼び出しをWSAECONNRESET(10054)エラーで終わらせ、サーバーのコードが受信を止めるかソケットを閉じる → 画面では: そのソケットを使っていた全員が一斉にフリーズ・切断

症状: 切断, フリーズ · 主担当 ゲーム開発チーム・サーバー開発

サーバーのゲームプロセス:ティックとスレッド

ゲームロジックを実際に計算するプログラムです。移動、戦闘、モンスターAI、視界計算、ブロードキャストが、すべて「ティック」1回の中で終わらなければなりません。人が1か所に集まるほど、視界計算と送るパケットは人数の2乗で増えます。

サーバーは決まったティック間隔でゲームの状態を計算します。20ティックのサーバーなら50msに1回、その間にすべてのプレイヤーの入力を適用し、モンスターを動かし、誰が誰を見られるかを計算し(視界、AOI)、変化した内容を見えるすべての人に送ります。この50msがティックバジェットです。バジェットを超えると次のティックが遅れます。ティックごとにゲーム内時間を決まった分だけ進めるサーバーでは、ゲーム内の時間全体がゆっくり流れ(スローモーション)、実際に経過した時間分を一度に進めるサーバーでは、速度は保たれる代わりにパケットがまばらになり、カクついたりワープしたりします。どちらにしても反応は遅れます。ゲームスレッド1本がサーバー(チャンネル)全体を担当していればそのサーバーの全員が、エリアごとにスレッドを分けていればそのエリアの人たちが一緒に影響を受けます。

問題は人数です。全員同士を比べると、100人なら約1万回、1,000人なら約100万回を毎ティック調べなければなりません。そのためサーバーはマップをグリッドに分け、近いセル同士だけを比べますが、ワールドボス、攻城戦、街の広場のイベントのように全員が1つのセルの近くに集まると、グリッドの効果が薄れ、計算量と送るデータが爆発的に増えます。さらに、複数のスレッドが同じデータを巡って待つロックや、ティックの途中でDBの応答を待つ同期呼び出しが重なると、待っている間はそのスレッドが担当する全員が一緒に止まります。

たとえ

サーバーのティックは指揮者の拍子です。オーケストラの団員(プレイヤー)が増えるほど1拍の間に目を通す楽譜が増え、拍子を外すと曲全体が遅くなります。誰かが楽譜を1枚探しに倉庫(DB)へ行ってしまうと、全員がその人を待つことになります。

この層でラグを生む原因

ティックバジェット超過 Tick overrun

1ティックの処理がバジェットを超えるとサーバーのティック周期が延び、そのエリア全体がゆっくり進んだりカクついたりします。

なぜ: 1ティック(例:50ms)で処理する仕事がバジェットを超える → すると: 1秒に20回計算するはずのゲーム状態を8回しか計算できない → 画面では: そのエリア全体がスローモーション(サーバーの設計によってはカクつき)、スキルの反応が遅い

症状: スローモーション, 入力遅延, カクつき · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

視界(AOI)計算の急増(N²) Area-of-interest explosion

誰が誰を見られるかを全員同士で比較すると、人数が10倍になったとき計算は100倍になります。

なぜ: すべてのキャラクター同士で距離を比較しているか、グリッドに分割していても1つのセルの周辺に数百人が集中 → すると: 100人なら約1万回、1,000人なら約100万回の比較 → 画面では: ワールドボスや攻城戦のように人が集中した場所でティック時間が急増し、スローモーション・カクつき

症状: スローモーション, カクつき · 主担当 ゲーム開発チーム・サーバー開発

ブロードキャストの急増 Broadcast fan-out (N×N)

1人の動きを、その人が見えている全員に送ると、集まった人数の2乗に比例する数の更新を送ることになります。

なぜ: 1人の変化を、それが見える全員に送信 → すると: 1,000人が互いを見ていると、ティックごとに100万個の更新 → 画面では: 送信キューと帯域幅が飽和して遅延・パケットロス(入力遅延・早送り・ワープ)

症状: 入力遅延, ワープ, 早送り · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

シングルスレッドのエリア過負荷(ホットスポット) Single-threaded hot zone

エリアごとに1つのスレッドが担当する構造では、1か所に人が集中すると、そのコア1つだけが100%になります。

なぜ: 1つのエリア(チャンネル)を1つのスレッドが担当 → すると: 人が1か所に集中するとそのコアだけが飽和し、ほかのコアには余裕がある → 画面では: そのエリアだけラグが出て、ほかのエリアは問題ない

症状: スローモーション, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

ロック競合 Lock contention

複数のスレッドが同じデータを使うために1つのロックを待つと、スレッドを増やしても一度に1つずつしか実行されません。

なぜ: 取引所・ギルド倉庫のような共有データを、複数のスレッドが同時に使用 → すると: ロックを取ったスレッドが終わるまで、ほかのスレッドは待機 → 画面では: 特定の機能だけ遅い、ひどい場合は全体のティックが遅延

症状: 入力遅延, フリーズ · 主担当 ゲーム開発チーム・サーバー開発

デッドロック Deadlock

2つのスレッドが互いに相手の取ったロックを待つと、永遠に止まったままになります。

なぜ: スレッドAはロック1を取ったままロック2を、Bはロック2を取ったままロック1を待つ → すると: 両方とも永遠に止まり、関連するスレッドも次々に止まる → 画面では: サーバー全体が停止し、ウォッチドッグによる再起動で全員が切断

症状: フリーズ, 切断 · 主担当 ゲーム開発チーム・サーバー開発

ゲームスレッドの同期呼び出し Synchronous DB / file I/O on the game loop

ティックの途中でDBの応答やファイルの書き込みを待つと、その時間だけサーバーのゲーム進行全体が止まります。

なぜ: ティック内でDBの参照・保存、ログの書き込み、外部APIの呼び出しを待つ → すると: DBに100msかかればティックも100ms止まる → 画面では: DB・ディスクが遅くなるたびに、フィールド全体が一瞬止まる

症状: フリーズ, カクつき · 主担当 ゲーム開発チーム・サーバー開発

メッセージキューの滞留 Mailbox / job queue backlog

リクエストが処理速度より速く届いてキューにたまると、後ろのリクエストは数秒後にやっと処理されるか、破棄されます。

なぜ: リクエストが処理速度より速く到着 → すると: キューが長くなり、上限を超えると破棄 → 画面では: スキル・取引の反応が遅れるか、不発になる

症状: 入力遅延, 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発

タイマーの一斉発火 Synchronized timers

すべてのモンスターのリスポーン、すべてのバフの期限切れ、毎正時の報酬が同じティックに集中すると、そのティックだけ処理が数十倍重くなります。

なぜ: リスポーン・期限切れ・報酬・オートセーブのタイマーが同じ時刻にそろっている → すると: その1ティックに普段の数十倍の処理 → 画面では: 決まった時刻になるたびに一瞬止まる

症状: フリーズ, カクつき · 主担当 ゲーム開発チーム・サーバー開発

経路探索の急増 Pathfinding storms

数百体のモンスターが同時にプレイヤーを追いかけて経路を計算すると、CPUを大きく消費します。

なぜ: まとめ狩りや大量スポーンで、モンスターが一斉にプレイヤーを追跡 → すると: モンスターごとに経路探索を計算 → 画面では: その狩場だけスローモーション

症状: スローモーション · 主担当 ゲーム開発チーム・サーバー開発

シリアライズ・圧縮のコスト Serialization / compression cost

送るデータをバイト列に変換して圧縮するのにもCPUを使い、人が多いとこのコストが急増します。

なぜ: 更新のたびに構造体をバイト列に変換・圧縮 → すると: 人数の2乗に比例してコストが増加 → 画面では: 送信が遅れて入力遅延

症状: 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発

サーバークラッシュ Server process crash

未処理のエラーでサーバープロセスが落ちると、そのサーバーにいた全員が同時に切断されます。

なぜ: 存在しない対象を参照するエラー(null参照)、不正なデータ、メモリ不足などの致命的なエラー → すると: サーバー(またはゾーン)のプロセスが終了 → 画面では: 全員が同時に切断、最後の保存以降の進行はロールバックされることがある

症状: 切断, 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

スレッドプールの枯渇 Thread pool starvation

処理を担うワーカースレッドがすべて遅い処理に塞がれると、新しいリクエストはいつまでも待たされます。

なぜ: ワーカースレッドが外部API・DBの応答待ちで塞がる → すると: 新しいリクエストに割り当てるスレッドがない → 画面では: ログイン・ショップなど特定の機能が無限ロード

症状: 接続不可・無限ロード, 入力遅延, フリーズ · 主担当 ゲーム開発チーム・サーバー開発

無限ループ・ロジックの暴走 Infinite loop / runaway logic

バグで1ティックが終わらないとサーバーが止まり、ウォッチドッグが強制的に再起動します。

なぜ: 誤った条件でループが終わらない、または再帰が暴走 → すると: ティックが終わらずサーバーが停止 → 画面では: フリーズの後、全員が切断

症状: フリーズ, 切断 · 主担当 ゲーム開発チーム・サーバー開発

1体に集中する戦闘(ワールドボス) Hot entity / combat event fan-out

数百人が1体のボスを同時に攻撃すると、そのボス1体の計算が1か所に集中し、ヒット情報が見ている全員に送信されます。

なぜ: 数百人が1体のボスにスキル・バフ・デバフを絶え間なく使用 → すると: ボスのHP・ヘイトリスト・デバフの計算が1か所に集中し、ヒットのたびにダメージ数値・エフェクトのパケットを見ている全員に送信 → 画面では: スキルの反映が遅れ、ダメージ数値がまとめて表示される、ボスの周辺だけスローモーション

症状: 入力遅延, 早送り, スローモーション · 主担当 ゲーム開発チーム・サーバー開発

密集エリア進入時のスポーン集中 Spawn burst when entering a crowd

人でいっぱいの街にテレポートすると、サーバーは新たに見えるようになった数百人の外見・装備・状態を一度に送らなければなりません。

なぜ: テレポート・ログイン・チャンネル移動で、混雑した場所に突然現れる → すると: 数百人分の全情報を一度に作って送り、自分のPCも一度に読み込む → 画面では: 到着直後に一瞬止まる、キャラクターが遅れて1体ずつ現れ、入力の反応が遅い

症状: フリーズ, 入力遅延, 早送り · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発

オブジェクトの蓄積(消えずに残るアイテム・召喚物) Entity / timer buildup over uptime

消えるはずの地面のアイテム、召喚物、終わったタイマーが片付けられずにたまると、サーバーを長く稼働させるほど毎ティックの処理が増えます。

なぜ: 地面のアイテム・召喚物・期限切れのタイマー・空のパーティ情報が、本来のタイミングで削除されない → すると: ティックごとに走査するリストが日ごとに長くなる → 画面では: メンテ明けは問題ないが、数日たつとそのサーバー・エリアだけ次第に重くなる

症状: スローモーション, カクつき, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発

アップデートによるトラフィックパターンの変化 Patch changes traffic pattern

新しいコンテンツ・エフェクト・同期項目がパケットのサイズと頻度を増やすと、問題なく動いていたサーバーがアップデート後からMTU・帯域幅・パケット数の上限に引っかかります。

なぜ: アップデートで新しいスキルエフェクト・同期項目・アイテム情報が増え、パケットが大きくなるか頻繁になる → すると: 大きなパケットはMTUを超えてフラグメント化され、増えた分は帯域幅・クラウドのPPS上限・送信バッファに引っかかる → 画面では: アップデート直後から、混雑した場所でワープ・スキル不発・入力遅延。インフラは何も変えていないのにパケットロスが増える

症状: ワープ, 不発・ロールバック, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ, インフラチーム・ネットワークインフラ

メモリ

サーバーが覚えているすべてのもの、つまりキャラクター・モンスター・アイテム・マップはメモリに載っています。メモリ自体は速いのですが、GC(使わなくなったメモリの回収)で止まったり、少しずつ漏れたり(リーク)、足りなくなってスワップ(メモリの一部をディスクに移すこと)が起きたりした瞬間にラグになります。

Java・C#・Goのようにメモリを自動で管理する言語では、使い終わったメモリをガベージコレクター(GC)が集めて回収します。GCの方式によっては、すべてのスレッドを一瞬止めることもあります。ヒープ(プログラムが実行中に割り当てを受けて使うメモリ領域)全体を一度にGCすると、生きているデータが多いほど時間がかかり、数百msから数秒に達します。ZGCのような最新のGCは、停止を1ms未満に抑える代わりにCPUとメモリを多く使います。C++のサーバーにはGCがありませんが、解放し忘れたメモリがたまるリークや、空き領域が細かく分かれて大きなかたまりを使えなくなる断片化に悩まされます。GCがあっても、使い終わったオブジェクトをどこかで参照し続けていれば、同じようにリークが起きます。

メモリが遅くなるもう1つの理由はメモリ階層(CPUからどれだけ離れた記憶装置か)です。CPUのすぐ横のキャッシュは1ns、RAMは100ns、ディスクに追い出したメモリ(スワップ)を読み戻すとRAMの1,000倍以上かかります。下の「数字の感覚」の表で、この差を人間の時間に引き延ばしてみてください。

たとえ

メモリは料理人の作業台です。手の届くところ(キャッシュ)に材料があれば速く、冷蔵庫(RAM)まで行くと少し遅くなり、作業台がいっぱいで材料を倉庫(ディスク、スワップ)に置いていると、取り出すたびにかなり時間がかかります。洗い物(GC)をしている間は料理を止めなければなりません。

この層でラグを生む原因

サーバーGCの全停止 Stop-the-world GC pause

Java・C#のサーバーがガベージを回収するために全スレッドを止めている間(stop-the-world)、サーバー全体が止まります。

なぜ: ヒープが埋まってGCが始まる → すると: 全ゲームスレッドを止めて回収(生存データが多いほど長引く) → 画面では: サーバー上の全員が同時にフリーズし、その後早送り

症状: フリーズ, 早送り · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

スクリプトエンジンのGC停止 Scripting VM GC (Lua, etc.)

C++のサーバーでも、クエスト・AI・スキルをLuaなどのスクリプトで動かしていると、スクリプトエンジンのGCが走っている間そのゾーンが止まります。

なぜ: ゾーンごとにスクリプトエンジンがクエスト・AI・イベントを実行し、一時オブジェクトを大量に生成 → すると: スクリプトエンジンのGCが一度に大量に回収すると、そのゾーンのティックが止まる → 画面では: 特定のゾーン・特定のイベント中だけ周期的に一瞬止まる

症状: カクつき, フリーズ · 主担当 ゲーム開発チーム・サーバー開発

アロケーションの急増 Allocation storms

イベント中に一時オブジェクトを大量に生成すると、GCが普段よりはるかに頻繁に走ります。

なぜ: アイテムドロップ・戦闘ログ・イベント報酬で一時オブジェクトが急増 → すると: GCが数倍の頻度で走り、まだ破棄されていなかったオブジェクトがOld領域に移ってFull GCも早まる → 画面では: イベント時だけ周期的に一瞬止まる

症状: カクつき, フリーズ · 主担当 ゲーム開発チーム・サーバー開発

メモリリーク Memory leak

解放されないメモリが少しずつたまり、数日後にGCの多発・スワップ・強制終了につながります。

なぜ: ログアウトしたキャラクターの情報・イベントハンドラーが解放されない → すると: 数日かけて空きメモリが減っていく → 画面では: メンテ明けは正常、日を追うごとにラグが増え、最後はサーバーダウン

症状: スローモーション, フリーズ, 切断 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

GCスラッシング(ヒープの空き不足) GC thrashing (heap nearly full)

生存データがヒープの上限に近づくと、GCが走っても回収できるものがほとんどなく、GCが休みなく繰り返されます。

なぜ: イベントでの人数増加やリークで、生存データがヒープの上限近くまで埋まる → すると: GCがわずかしか回収できず、すぐにまたFull GC、CPUの大半をGCが使う → 画面では: サーバー全体が数分間スローモーション・フリーズを繰り返し、メモリ不足で終了

症状: スローモーション, フリーズ, 切断 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

スワップ Swapping

メモリが足りずOSが一部をディスクに退避させると、そのメモリを使うたびに1,000倍以上遅いディスクを待つことになります。

なぜ: 使用メモリが物理RAMを超える → すると: OSが一部をディスクに退避させ、必要なときに読み戻す → 画面では: ティックが数百msに跳ね上がり、サーバーの全ユーザーがスローモーション・フリーズ

症状: スローモーション, フリーズ · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発

キャッシュミス CPU cache misses

データがメモリのあちこちに散らばっていると、CPUが毎回遅いRAMまで取りに行って待つことになります。

なぜ: オブジェクトがポインターでつながって散らばり、順不同にアクセス → すると: CPUキャッシュにないので毎回RAMから読む(100倍前後遅い) → 画面では: 同じ処理でもティックのコストが数倍、ひどいとスローモーション

症状: スローモーション · 主担当 ゲーム開発チーム・サーバー開発

メモリの断片化 Heap fragmentation

アロケーションと解放を繰り返して空き領域が細かく分断されると、実際に使っている量よりはるかに多くのメモリを占有するようになります。

なぜ: サイズがまちまちのメモリを、複数のスレッドが長期間アロケーション・解放 → すると: 空き領域が細かく散らばってOSに返せず、使用量がリークのように増え続ける → 画面では: 長く稼働するほどスワップ・メモリ不足で遅くなり、最後は強制終了

症状: スローモーション, 切断 · 主担当 ゲーム開発チーム・サーバー開発

NUMAのリモートメモリ Remote NUMA access

CPUが2つあるサーバーで、反対側のCPUにつながったメモリを使うとアクセスが遅くなります。

なぜ: スレッドとメモリが別々のCPUソケットに配置される → すると: メモリアクセスが遅くなる(機器によって1.5〜2倍) → 画面では: 同じスペックなのにプロセスごとに性能差

症状: スローモーション · 主担当 インフラチーム・サーバーインフラ

ディスク

ログ、キャラクターの保存、マップデータ、DBファイルはすべてディスクにあります。ディスクはメモリより数百倍(SSD)から10万倍(HDD)も遅いので、ゲームサーバーがディスクを待つ構造なら、ディスクが忙しくなった瞬間にゲームも一緒に止まります。

ディスクの性能は「1秒に何回読み書きできるか」(IOPS)で測ります。古いHDDは150回ほど、SSDは数万〜数十万回です。クラウドのディスクは支払った料金に応じて上限が決まります(AWSのgp3は標準で3,000回)。一部のクラウドディスクや小さなサーバースペックは、ふだんの速度に加えて一時的にさらに高い性能を出せるバーストクレジットを与えますが、忙しい時間が長引くとクレジットが尽きて速度が急に落ちます。「毎晩、数時間たつとラグが出る」という報告がこの形です。

ポイントは誰が待つかです。ふつうのファイル書き込みは、OSがいったんメモリで受け取っておき、後でディスクに書き出すため、たいていすぐ終わります。問題になるのは、「ディスクに実際に書き込まれるまで」待つよう指示したとき(fsync)や、OSがメモリで受け取っておける上限に達したときです。このときゲームスレッドが自分で待つと(同期)、ディスクが100ms遅れればティックも100ms止まります。書き込みを別スレッドに任せれば(非同期)ゲームは止まりませんが、サーバーが突然落ちると、まだ書き込めていない内容が消えることがあります(不発・ロールバック)。

たとえ

ディスクは倉庫、IOPSは倉庫の扉の数です。扉が少なければ、物を出し入れする人が列を作ります。バーストクレジットは短い間だけ全力疾走できる体力で、使い切ると歩く速さに戻ります。

この層でラグを生む原因

同期ログ書き込み Synchronous logging

ゲームスレッドがログを1行書くたびにディスクへの書き込み完了を待っていると、ディスクが忙しいときにゲームの進行も一緒に止まります。

なぜ: 戦闘・取引ログをゲームスレッドから直接ファイルに書く → すると: 確実な書き込み(fsync)を要求したり、OSの書き込みバッファ(ページキャッシュ)が上限に達したりすると、ディスクが忙しいときに1回の書き込みが数十ms → 画面では: ログの多い戦闘で一瞬止まる

症状: カクつき, フリーズ · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

fsyncの集中 fsync storms

データを「確実に」ディスクに書き込むよう要求すると、ディスクによっては1回に0.1ms〜数十msかかり、要求が集中するとキューが長くなります。

なぜ: 定期保存・ログアウトラッシュで確実な書き込みの要求が集中 → すると: ディスクのキューが長くなる → 画面では: 保存のタイミングごとにラグ、ログアウト・チャンネル移動の遅延

症状: カクつき, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ, インフラチーム・DBインフラ

クラウドディスクのバーストクレジット枯渇 Burst credit depletion

一部のクラウドディスクや小さなサーバースペックには、一時的にベースラインより速く使えるバーストクレジットがあります。忙しい時間が長引いてクレジットが底をつくと、速度が急に落ちます。

なぜ: ベースライン性能を超えて長時間使用 → すると: バーストクレジットが底をつき、ベースライン性能まで急落 → 画面では: 毎晩、数時間たったころからラグが出始める

症状: カクつき, スローモーション, 入力遅延 · 主担当 インフラチーム・サーバーインフラ · 副担当 インフラチーム・DBインフラ

IOPS上限・キューの飽和 IOPS limit / queue saturation

ディスクが1秒間に処理できる要求数を超えると、キューが長くなって遅延が急増します。

なぜ: 読み書きの要求がディスクの処理能力に近づく → すると: キューが長くなる(たいてい利用率90%以上で急増) → 画面では: 保存・ロードの遅延、同期呼び出しならフリーズ

症状: 入力遅延, フリーズ · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発, インフラチーム・DBインフラ

ディスクフル Disk full

ログとダンプがたまってディスクがいっぱいになると書き込みが失敗し、備えがなければサーバーが落ちます。

なぜ: ログ・ダンプ・一時ファイルがたまって100% → すると: 書き込み失敗。エラー処理がなければクラッシュ、あれば保存失敗 → 画面では: 切断、進行状況のロールバック

症状: 切断, 不発・ロールバック · 主担当 インフラチーム・サーバーインフラ · 副担当 インフラチーム・DBインフラ, ゲーム開発チーム・サーバー開発

バックアップ・圧縮・スキャン処理 Backup / compression / scans

深夜のバックアップ、ログの圧縮、セキュリティスキャンがディスクを独占すると、ゲームサーバーの読み書きが詰まります。

なぜ: スケジュールされたバックアップ・圧縮処理が始まる → すると: ディスクの帯域幅とIOPSの大半を占有 → 画面では: 毎日同じ時刻にラグ

症状: カクつき, 入力遅延 · 主担当 インフラチーム・サーバーインフラ · 副担当 インフラチーム・DBインフラ

サーバーの遅延ロード Lazy loading on the server

サーバーがダンジョン・マップのデータを初めて要求されたときにディスクから読むと、そのティックの間、全員が止まります。

なぜ: 誰かが初めてダンジョン・エリアに入場 → すると: サーバーがゲームスレッドでデータをディスクから読む → 画面では: そのサーバーの全員が一瞬フリーズ

症状: フリーズ · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

コアダンプの書き出し Core dump writing

サーバーが落ちるときに数GBのメモリをディスクに書き出すため、再起動が数分遅れることもあります。

なぜ: サーバーのクラッシュでメモリ全体をファイルに書き出す → すると: 数GBを書き込む間は再起動できない → 画面では: サーバーが落ちて切断された後、しばらく接続できない

症状: 接続不可・無限ロード · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発

HDDのシーク遅延 HDD seek latency

HDDはヘッドがプラッタ上を移動する(シーク、seek)必要があるため、散らばったデータの読み書きに1回あたり10ms近くかかります。

なぜ: 古いサーバーや低価格ストレージでHDDを使用 → すると: ランダムな読み書きのたびに約10ms → 画面では: 全体的な保存・ロードの遅延

症状: 入力遅延 · 主担当 インフラチーム・サーバーインフラ · 副担当 インフラチーム・DBインフラ, ゲーム開発チーム・サーバー開発

データベース

キャラクター、アイテム、ゲーム内通貨、取引記録のように、絶対に失ってはいけないものが入っている場所です。DBが遅くなると、戦闘は問題ないのにアイテムの反映が遅れ、取引が失敗し、ログインが終わらなくなります。ゲームサーバーがDBを待つ構造なら、フィールド全体が止まります。

ゲームサーバーはDBとあらかじめいくつかの接続(コネクションプール)を張っておき、使い回します。クエリ(DBに送る要求)1つに時間がかかると、そのコネクションが使用中のままになり、プールのコネクションがすべて使用中になると、残りの要求はキューで待ちます。クエリが遅くなるよくある理由は2つです。インデックス(本の索引)がなくてテーブル全体を読む(フルスキャン)か、複数の要求が同じ行を同時に更新しようとしてロックを待つかです。

DBは信頼性を保ち、多くの要求を受けるために、いくつもの仕組みを使います。読み取りを分担するレプリカ、障害時に切り替わる予備のDB、変更分を定期的にまとめてディスクに書き込むチェックポイント。チェックポイントが集中すると一時的に遅くなります。レプリカが遅れると「さっき買ったアイテムが見えない」、レプリケーションが遅れたまま予備のDBに切り替わると「接続したら少し前の状態に戻っていた」といった不発・ロールバックの症状が起きます。ゲームサーバーがキャラクターを数分に1回しか保存しないなら、サーバーが落ちたときに「10分前に戻った」ことになります。

たとえ

DBは銀行の窓口です。窓口の数(コネクションプール)は決まっていて、1つの要求が帳簿全体をひっくり返して探す作業(フルスキャン)をすると、後ろの要求がすべて待たされます。全員が同じ金庫(ホットスポット)を開けようとすると、1人ずつしか入れません。

この層でラグを生む原因

インデックスのないクエリ Missing index / full table scan

インデックスがないと、条件に合う行を探すためにテーブル全体を読む必要があります(フルスキャン)。

なぜ: 新機能のデプロイで、インデックスのない条件検索が追加される → すると: 数百万行をすべてスキャンし、クエリ1つに数百ms〜数秒 → 画面では: 郵便受け・取引履歴のロード遅延、コネクションがふさがって他の要求まで待たされる

症状: 入力遅延, 接続不可・無限ロード · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ

ホットスポットの行ロック競合 Hot row lock contention

全員が同じ行(ギルド倉庫、オークションの人気アイテム、サーバー全体のカウンター)を更新しようとすると、ロックを取れるのは1人ずつです。

なぜ: イベント・人気アイテムで同じ行に更新が集中 → すると: ロックを取れるまで要求が待たされる → 画面では: 取引失敗、「しばらくしてからもう一度お試しください」、タイムアウト

症状: 不発・ロールバック, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ

DBのデッドロック Database deadlock

2つのトランザクション(ひとまとまりで処理されるDB操作)が互いに相手のロックした行を待つと、DBが片方を強制的に取り消します。

なぜ: 取引Aはアイテム→通貨、Bは通貨→アイテムの順にロック → すると: DBがデッドロックを検知して片方をロールバック → 画面では: 取引・製作がときどき失敗、アイテムが元に戻る

症状: 不発・ロールバック, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ

コネクションプールの枯渇 Connection pool exhaustion

DBとの接続数は決まっているため、遅いクエリが接続を占有すると、残りの要求は待たされます。

なぜ: 遅いクエリや要求の殺到で、すべての接続が使用中 → すると: 新しい要求は接続が空くまで待つ → 画面では: ログインの無限ロード、保存の遅延、タイムアウト

症状: 接続不可・無限ロード, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ

レプリケーション遅延 Replication lag

書き込みはプライマリに、読み込みはレプリカから行う構成で、レプリカの追従が遅れると、書いたばかりの内容が見えません。

なぜ: プライマリに書き込みが集中し、レプリカが数秒遅れる → すると: 保存したばかりの内容をレプリカから読むと、まだ反映されていない → 画面では: 買ったばかりのアイテムが表示されない、取引所の価格が古い値のまま、重複付与のバグ

症状: 不発・ロールバック · 主担当 インフラチーム・DBインフラ · 副担当 ゲーム開発チーム・サーバー開発

チェックポイント・ログフラッシュ Checkpoint / log flush stalls

DBがメモリ上の変更分を定期的にまとめてディスクに書き込む瞬間、クエリが遅くなります。

なぜ: 変更分がたまり、定期的にディスクへ書き出す → すると: その瞬間ディスクの負荷が上がり、クエリが遅延 → 画面では: 定期的に保存・ロードが遅くなる

症状: 入力遅延, カクつき · 主担当 インフラチーム・DBインフラ

コールドキャッシュ(再起動直後) Cold buffer pool after restart

DBを再起動するとメモリ上のキャッシュが空になっているため、しばらくはすべての読み込みがディスクから行われます。

なぜ: メンテナンスでDBを再起動 → すると: よく使われていたデータがメモリになく、ディスクから読む → 画面では: メンテ明けしばらくログイン・ロードが遅い

症状: 接続不可・無限ロード, 入力遅延 · 主担当 インフラチーム・DBインフラ · 副担当 ゲーム開発チーム・サーバー開発

ログイン殺到とN+1クエリ Login storm, N+1 queries

キャラクター1体を読み込むたびに数十回の個別クエリを発行していると、数万人の同時ログインは数百万件のクエリになります。

なぜ: キャラクターのロード時にアイテム・スキル・クエストを個別にクエリ → すると: メンテ明けの同時ログインでクエリが急増 → 画面では: ログインの無限ロード、プレイ中のユーザーの保存まで滞る

症状: 接続不可・無限ロード, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ

大規模なバッチ処理 Batch jobs during service

ランキング集計、郵便の一括送信、古いデータの整理をサービス中に実行すると、ロックとディスクを占有します。

なぜ: サービス時間中に大量の処理を実行 → すると: 広い範囲のロック、ディスク・CPUの占有 → 画面では: 特定の時間帯に取引・保存が失敗、ロード遅延

症状: 入力遅延, 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ

DBのフェイルオーバー Database failover

プライマリが落ちてスタンバイDBに切り替わる間は書き込みができず、レプリケーションが間に合わなかった最後のデータは失われることがあります。

なぜ: プライマリの障害でスタンバイDBが昇格 → すると: 切り替え中は数秒〜数分書き込み不可、非同期レプリケーションならレプリカに届いていないデータが失われる可能性 → 画面では: 一時的にすべての保存が失敗、アイテム・経験値のロールバック

症状: 不発・ロールバック, フリーズ, 切断, 接続不可・無限ロード · 主担当 インフラチーム・DBインフラ · 副担当 ゲーム開発チーム・サーバー開発

長い保存間隔による進行状況の消失 Periodic save window

負荷を減らすために数分に1回しか保存しないと、その間にサーバーが落ちた場合に進行状況が失われます。

なぜ: キャラクターの状態を数分ごとに1回保存 → すると: その間にサーバーのクラッシュ・障害が発生 → 画面では: 再接続すると数分前の状態(ロールバック)

症状: 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ

キャッシュスタンピード Cache stampede / thundering herd

人気データのキャッシュが同時に期限切れになると、数千件の要求が一斉にDBへ殺到します。

なぜ: Redisなどに保存した人気データが同時に期限切れ → すると: 同じデータを作り直そうとする要求が一斉にDBへ殺到 → 画面では: DBの過負荷で複数の機能が次々に遅くなったり止まったりする

症状: 入力遅延, フリーズ, 接続不可・無限ロード · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ

長時間開いたままのトランザクション Long-running transaction / MVCC purge lag

1つのトランザクションが長く開いたままだと、ロックを持ち続けるうえ、DBが古いバージョンのデータを整理(purge)できないため、全体が徐々に遅くなります。

なぜ: トランザクションを開いたまま別サーバーの応答を待つ、またはサービス中にプライマリで長い集計クエリを実行 → すると: 取ったロックが解放されず、整理すべき古いバージョンのデータがたまり続ける → 画面では: その行を使う機能がタイムアウト、数時間かけて保存・読み込みが全体的に遅くなる

症状: 入力遅延, 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ

Redisの遅いコマンド Redis blocking commands (single-threaded)

Redisはコマンドを1つずつ順番に処理するため、遅いコマンドが1つあると、その後ろのすべての要求が止まります。

なぜ: サービス中にKEYSで全件検索、要素が数百万個あるランキング・リストを丸ごと読んだり削除したりする → すると: そのコマンドが終わるまで、他のすべての要求が待たされる(数十ms〜数秒) → 画面では: セッション・ランキング・キャッシュを使う機能が一斉に一瞬止まる、ログイン遅延

症状: フリーズ, 入力遅延, 接続不可・無限ロード · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・DBインフラ

実行計画の変化によるクエリ遅延 Query plan regression (stats, parameter sniffing)

コードは変わっていないのに、DBが同じクエリの処理方法(実行計画)を変えると、昨日2msだったクエリが今日は数百msになります。

なぜ: 統計情報の自動更新、DBの再起動、データ分布の変化で、DBが実行計画を立て直す → すると: インデックスを使わない計画が選ばれ、同じクエリが数十〜数百倍遅くなり、コネクションがふさがる → 画面では: デプロイもなかったのに特定の機能のロードが急に遅くなり、他の要求まで待たされる

症状: 入力遅延, 接続不可・無限ロード · 主担当 インフラチーム・DBインフラ · 副担当 ゲーム開発チーム・サーバー開発

サービス中のスキーマ変更(DDL)によるロック Schema change lock (DDL / metadata lock)

サービス中にテーブルへカラムやインデックスを追加すると、一瞬だけ必要なロック1つのために、そのテーブルを使うすべての要求が待たされることがあります。

なぜ: ホットフィックスでサービス中のテーブルにカラム・インデックスを追加 → すると: スキーマ変更が先に開いていた長いトランザクションを待ち、後から来るすべての要求はそのスキーマ変更を待つ → 画面では: そのテーブルを使う機能(インベントリ、郵便など)が丸ごと止まり、タイムアウト

症状: 入力遅延, 不発・ロールバック, 接続不可・無限ロード · 主担当 インフラチーム・DBインフラ · 副担当 ゲーム開発チーム・サーバー開発

サーバー構成と運用

最近のMMOはたいてい、ログイン、ゲートウェイ、フィールド、ダンジョン、チャット、パーティ、オークション、キャッシュ、DBの各サーバーが互いに呼び出し合って動く構成です。1か所で障害が発生するとつながった先へ広がり、デプロイ・スケーリング・メンテナンスといった運用作業もラグを生みます。

サーバーを分けると、1か所の障害が全体に広がるのを防げますが、その代わりに呼び出しチェーン(サーバーが別のサーバーを順に呼び出すつながり)が生まれます。ゲームサーバーがオークションサーバーを呼び、オークションサーバーがキャッシュとDBを呼ぶ、という具合です。チェーンの末端のサーバーが遅くなると、手前のサーバーは応答を待ちながらスレッドとコネクションを占有し続け、最後には関係なさそうな機能まで止まります。これをカスケード障害といい、タイムアウトとサーキットブレーカー(失敗が続く呼び出しをしばらく遮断する仕組み)で広がりを防ぎます。

運用作業もラグの原因です。アップデートのデプロイ中の再起動、人が集中したときにサーバーを自動で増やすまでにかかる数分、ゾーン移動時にキャラクターを別のサーバーへ移す処理、ボットやマクロが生む目に見えない負荷は、どれもプレイヤーには「ラグ」に見えます。

たとえ

サーバー構成は複数の部署が決裁を回し合う会社です。決裁ルートの末端の部署(DB)が1つ遅くなると、手前の部署は書類を持って列を作り、最後には会社全体の業務が止まります。タイムアウトは「10分以上返事がなければいったん差し戻す」ルールで、ブレーカーは「差し戻しが続いたら、しばらくその部署には書類を送らずにすぐ返す」ルールです。

この層でラグを生む原因

ゲートウェイ・プロキシ経由 Gateway / proxy hop

クライアントとゲームサーバーの間に中継サーバーを置くと、経由するたびに処理時間が加わり、そのサーバーが単一障害点になります。

なぜ: クライアント ↔ ゲートウェイ ↔ ゲームサーバーの構成 → すると: 中継サーバーでの処理・待ちが加わり、過負荷になると全員に影響 → 画面では: 全体のPingが上昇、ゲートウェイ障害時はそこを経由するユーザー全員が切断

症状: 入力遅延, 切断 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ, ゲーム開発チーム・クライアント開発

ゾーン移動(サーバー間の引き継ぎ) Zone / server handoff

別のエリアやダンジョンに入るとき、キャラクター情報を別のサーバーへ引き渡す過程で遅延や失敗が起きます。

なぜ: ダンジョン入場や大陸移動で担当サーバーが変わる → すると: 保存 → 転送 → 読み込み、移動先サーバーが混雑しているか空いているダンジョンインスタンスがなければ待機 → 画面では: 長いロード、入場失敗、移動中の切断

症状: 接続不可・無限ロード, フリーズ, 切断, 引き戻し · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

カスケード障害 Cascading failure

1つのサービスが遅くなると、それを呼び出すサーバーが応答待ちで塞がり、関係のない機能まで止まります。

なぜ: DB・認証など1つのサービスが遅くなる → すると: 呼び出し側サーバーのスレッドと接続が応答待ちで塞がり、失敗したリクエストの再試行が負荷を上乗せ → 画面では: 関係なさそうな機能まで、すべて遅くなるか止まる

症状: フリーズ, 入力遅延, 接続不可・無限ロード · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・ネットワークインフラ

補助サーバーの障害 Auxiliary service outage

チャット・パーティ・オークションのように、ゲームサーバーとは別に動くサーバーで障害が起きると、その機能だけが動かなくなります。

なぜ: 機能専用サーバーが遅くなるか落ちる → すると: その機能のリクエストだけ応答なし → 画面では: チャットができない、パーティ招待に反応なし、取引所が無限ロード(戦闘は正常)

症状: 不発・ロールバック, 接続不可・無限ロード · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

デプロイ・再起動 Deploy / rolling restart

アップデートのためにサーバーを再起動するとき、接続を移さずに止めると、そのサーバーにいた人は切断され、終了直前の保存と再接続が一気に集中します。

なぜ: ホットフィックスのデプロイでサーバーを順番に再起動 → すると: 接続を別のサーバーに移さずに終了、そのサーバーにいた全ユーザーの保存がDBに集中 → 画面では: 告知なしの切断、再接続の殺到

症状: 切断, 接続不可・無限ロード, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

オートスケーリングの遅れ Autoscaling lag

人が集中するとサーバーを自動で増やしますが、準備に数分かかり、その間は既存のサーバーが過負荷になります。

なぜ: イベント開始で接続が急増 → すると: 新しいサーバーが起動して準備が整うまで数分 → 画面では: イベント開始直後の数分間、スローモーション・接続不可

症状: スローモーション, 接続不可・無限ロード · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発

ログ・監視の過負荷 Logging / monitoring overhead

障害が起きるとログが急増し、ログを同期で送るサーバーはログのせいでさらに遅くなります。

なぜ: エラー発生に伴い、ログ・メトリクスの送信量が急増 → すると: ログコレクターが詰まり、同期送信するサーバーは待たされる → 画面では: 障害時のカクつき・フリーズがログのせいでさらに悪化

症状: カクつき, フリーズ · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・サーバーインフラ

サーバー間の時刻のずれ Clock skew between servers

サーバーごとに時計が少しずつずれていると、クールタイム・バフ・イベント開始の判定がサーバーごとに食い違います。

なぜ: 時刻同期が止まったサーバーの時計が、ほかのサーバーと数百ms〜数秒ずれる → すると: バフの終了時刻のような絶対時刻をサーバー間で受け渡すと判定が食い違う → 画面では: 移動したらバフが消える、クールタイムがまた最初から始まる

症状: 不発・ロールバック · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発

大量のマクロ・ボット Bots and macros

ボットは人よりはるかに頻繁にリクエストを送り、サーバーのスループットを食いつぶします。

なぜ: 狩り・移動・取引を休まず繰り返すボットが大量に接続 → すると: サーバーの処理量とDB負荷が増加 → 画面では: 特定の狩場やサーバー全体が重くなる(スローモーション・入力遅延)

症状: スローモーション, 入力遅延 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 インフラチーム・ネットワークインフラ

外部サービスへの依存 External dependencies (auth, billing, platform)

プラットフォームのログイン、決済、本人確認などの外部サービスが遅くなったり止まったりすると、その段階で先に進めなくなります。

なぜ: 外部の認証・決済サービスの障害や遅延 → すると: その段階で応答待ち → 画面では: ログイン不可、決済失敗。すでにプレイ中の人は問題なし

症状: 接続不可・無限ロード, 不発・ロールバック · 主担当 外部・外部 · 副担当 ゲーム開発チーム・サーバー開発

マッチメイキング・リージョン割り当ての誤り Wrong region assignment (matchmaking / GeoDNS)

近いリージョンがあるのに遠いリージョンのサーバーに割り当てられると、回線に問題がなくても、そのユーザーだけPingが常に高くなります。

なぜ: GeoIPデータの誤り、VPN、パーティメンバーの平均Pingでパーティ全体を割り当て、人数が足りないときに遠いリージョンまで広げるルール、DNSリゾルバーの位置を基準にした割り当て → すると: 近いリージョンがあるのに、海の向こうのリージョンのサーバーに接続 → 画面では: 複数のリージョンにサーバーを置いたゲームで、自分だけ(または自分のパーティだけ)Pingが常に高く、入力遅延・引き戻し・スキル不発

症状: 入力遅延, 引き戻し, 不発・ロールバック · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発, インフラチーム・ネットワークインフラ, 外部・外部

TLS証明書の期限切れ・設定ミス TLS certificate expiry / misconfiguration

ログイン・API・アップデートサーバーの証明書が期限切れになったり中間証明書が抜けていたりすると、その瞬間から新たに接続するクライアントのTLS接続が失敗します。

なぜ: 証明書の有効期限が切れている、サーバーが中間証明書を含めずに送っている、またはユーザー端末の日付・時刻がずれている → すると: クライアントが証明書の検証に失敗し、TLS接続を切断 → 画面では: ログイン・アップデートの段階で接続不可・無限ロード、ショップなどHTTPSの機能だけ失敗。すでに接続していた人はたいてい問題なし

症状: 接続不可・無限ロード, 不発・ロールバック · 主担当 インフラチーム・ネットワークインフラ · 副担当 インフラチーム・サーバーインフラ, ゲーム開発チーム・クライアント開発

ログイン待機列の上限・再接続猶予の不足 Login queue cap / no reconnect grace

リリース直後やメンテ明けに接続が集中すると、ログイン待機列が上限に達して新たな待機を拒否し、待っていたユーザーは一瞬切れた間に順番を失って最後尾に戻されます。

なぜ: ログインサーバーが一度に受け付けられる人数より接続しようとする人が多いため待機列を設け、長くなりすぎるとサーバーを守るために新たな待機を拒否 → すると: 待機列が長いほど待ち時間が延び、その間にWi-Fi・モバイル回線が一瞬途切れただけで順番を失う → 画面では: 接続不可・無限ロード、待機中にエラーが出てゲームが終了、また最後尾から待ち直し

症状: 接続不可・無限ロード, 切断 · 主担当 ゲーム開発チーム・サーバー開発 · 副担当 ゲーム開発チーム・クライアント開発, インフラチーム・サーバーインフラ

T1ツール

診断ツール

ラグ報告を受けたら、「誰に、いつ、どんな形で」の3つだけを選んでみてください。この白書に載っている原因のうち、よく当てはまる候補をスコア順に表示します。確定診断ではありませんが、どのチームに最初に問い合わせるかを決めるには十分です。

T2ツール

観測データで切り分ける

報告やアラートが来たら、範囲 → 時点 → 階層の順に絞り込みます。異常がどこに集中しているかで担当が最も大きく分かれ、何と重なったかで原因が絞られ、どの階層のメトリクスが異常かで確かめます。原因カードごとにある「グラフでは」と「確認方法」をあわせて使えば、グラフの形で候補を選び、確認箇所をすぐに見つけられます。

切り分けの流れ

1 範囲

異常がどこに集中しているか

  • 特定の国・通信事業者(ASN) → インフラチームネットワーク 外部通信事業者
  • 特定のサーバー・チャンネル・ゾーン → ホストのメトリクスが正常なら ゲーム開発チームサーバー、異常なら インフラチームサーバー機器・OS
  • 特定のOS・端末・ビルド → ゲーム開発チームクライアント
  • 1人・同じ家 → 外部ユーザーの環境(複数人で同じ様子なら ゲーム開発チームクライアント)
  • 全体で同時に → 共用リソース(DB・ロードバランサー・ゲートウェイ)、または直前のデプロイ
2 時点

何と重なっているか

3 階層

どの階層のメトリクスが異常か

  1. ネットワーク:RTT・パケットロス・再送率、インターフェースのエラー・破棄
  2. ホスト:コアごとのCPU、CPUスチール、softirq、NICでの破棄、メモリ逼迫
  3. ゲームサーバー:ティック時間、ソケットの受信キュー(Recv-Q)、スレッドごとのCPU、GCログ
  4. DB:クエリ遅延、ロック待ち、レプリケーション遅延
  5. クライアント:フレームタイム、ネットグラフ、クラッシュレポート

切り分けシグナル表

確認するものこう見えたら最初に呼ぶ担当
サーバーのソケット受信キュー(Recv-Q)サーバープロセスが時間内に読み出せずにたまるゲーム開発チームサーバー(ティックの停止・GC・ロック)
接続ごとの再送・RTT一部の接続だけ、特定のASNに集中インフラチームネットワーク 外部通信事業者・ユーザーの回線
1台のホストのすべての接続インフラチームサーバー機器・OS(NIC・カーネル)
アップデート直後にサーバー全体で再送・帯域幅が増加パケットのサイズ・頻度が変わったゲーム開発チームサーバー インフラチームネットワーク(MTU・上限)
CPUスチール・スロットリング・softirq・NICでの破棄増加インフラチームサーバー機器・OS
1スレッドだけ100%、ランキュー遅延、GC停止増加ゲーム開発チームサーバー
DBの遅延が増加、クエリ数は変わらないIOPS・ロック・ほかのジョブインフラチームDBサーバー
DBのクエリ数・パターンがアップデート後に変わったN+1、新しいクエリゲーム開発チームサーバー
海外拠点からの外形監視(RTT・パケットロス)悪いインフラチームネットワーク 外部通信事業者
外形監視は正常なのにユーザーだけ悪いユーザーの環境、またはクライアント外部ユーザーの環境 ゲーム開発チームクライアント
切断理由の分布ハートビートのタイムアウト↑ / RST↑ / サーバーによる切断↑NAT・経路 / 機器 / サーバー
正確な周期(正時、N分)定期ジョブ・バックアップ・GC・イベントそのスケジュールを組んだ担当

グラフの形から探す

監視グラフがどんな形かがわかるだけでも、候補は大きく減ります。以下の13種類の形ごとに、その形を生む原因を集めました。原因カードの小さな図も同じ形です。実線は主に見るメトリクス、点線はあわせて見るメトリクス(人数、待ち・エラーなど)、薄い点線は平常時の水準です。

周期的なスパイク

普段は低く、数秒・数分ごとや毎正時のように同じ間隔で跳ね上がります。

クライアントのガベージコレクション, ゲームのセキュリティモジュール(アンチチート)の検査, Wi-Fiのバックグラウンドスキャン, 定期実行ジョブ, タイマーの一斉発火, サーバーGCの全停止, スクリプトエンジンのGC停止, fsyncの集中, バックアップ・圧縮・スキャン処理, チェックポイント・ログフラッシュ, 大規模なバッチ処理, キャッシュスタンピード

不定期なスパイク

決まった間隔なく不規則に跳ね上がり、すぐに戻ります。

フレームタイムのスパイク, 過度な外挿(デッドレコニング), クライアントサイド予測の不一致, 固定タイムステップの追いつき処理の暴走, バックグラウンドプロセスによるCPU占有, クライアントのメモリ不足・スワップ, NICの省電力・ドライバーの問題, Wi-Fiの干渉・電波の弱さ, 5G↔LTEの頻繁な切り替え(5Gエリアの境界), 回線品質の不良, リングバッファ不足, 仮想化オーバーヘッド・ノイジーネイバー, カーネルのソケットバッファ不足, CPUスチール(仮想マシン), メモリの回収・コンパクションによる停止, システム時刻のジャンプ(NTPステップ), 遅いクライアントによるブロッキング送信, 信頼性UDPの再送設定, RSTによる強制終了で最後のデータが消失, ゲームスレッドの同期呼び出し, 同期ログ書き込み, サーバーの遅延ロード, DBのデッドロック, Redisの遅いコマンド, ログ・監視の過負荷, ロックステップでの最も遅いプレイヤー待ち, ロールバックネットコードの予測失敗, タイムスタンプなしの受信即時再生, 厳しすぎるサーバー検証, コマンド同期の経路計算の不一致, 視界登録の順序の乱れ, 基準スナップショットの欠落, 消滅通知の欠落(ゴースト), オブジェクトIDの再利用による混同, 遅延の急上昇による不要な再送

ある時点から階段状に上昇

アップデート・設定変更・経路変更など特定の時刻を境に一段上がり、そのまま戻りません。

海底ケーブル・国際回線の障害, BGPの経路変更・収束, DDoS対策の経由・誤検知, OS・カーネル・ドライバー・ファームウェアのアップデート後の性能変化, アップデートによるトラフィックパターンの変化, インデックスのないクエリ, 実行計画の変化によるクエリ遅延, サービス中のスキーマ変更(DDL)によるロック, 外部サービスへの依存, 経路変更・ECMPの不良経路

人数・負荷に連動して上昇

同時接続数や一か所に集まった人数が増えると、それを上回る勢いで上がります。

大人数の描画負荷, メインスレッドのパケット処理ボトルネック, 受信バッファのあふれ, 同じ端末の他のアプリによる帯域幅の占有, バッファブロート(ルーターのキュー), スイッチのマイクロバースト, スレッド過多とコンテキストスイッチ, コンテナのCPUスロットリング(CFSクォータ), UDPパケットのIPフラグメンテーション, ブロッキングI/O構造, ティックバジェット超過, 視界(AOI)計算の急増(N²), ブロードキャストの急増, シングルスレッドのエリア過負荷(ホットスポット), ロック競合, 経路探索の急増, シリアライズ・圧縮のコスト, 1体に集中する戦闘(ワールドボス), アロケーションの急増, ホットスポットの行ロック競合, レプリケーション遅延, ゲートウェイ・プロキシ経由, ゾーン移動(サーバー間の引き継ぎ), 接続ごとの送信バジェット・優先度, 送信バーストによる浅いバッファのあふれ, デュプレックスの不一致

上限で頭打ち

スループット・接続数がある値に達するとそれ以上伸びず、そこから待ち・エラーが増えます。

ビデオメモリ(VRAM)不足, ルーターの性能不足・過熱, 通信事業者の速度制限・トラフィック管理, DDoSによる共有回線の飽和, ファイアウォールのセッションテーブル飽和, クラウドのNATゲートウェイの接続・ポート上限, データセンター回線の飽和, NIC割り込みの単一コア集中, クラウドのPPS上限超過, NIC帯域幅の飽和, ファイルディスクリプタの上限, サーバーのconntrackテーブル飽和, サーバー間接続のエフェメラルポート枯渇, メッセージキューの滞留, スレッドプールの枯渇, GCスラッシング(ヒープの空き不足), クラウドディスクのバーストクレジット枯渇, IOPS上限・キューの飽和, コネクションプールの枯渇, カスケード障害, ログイン待機列の上限・再接続猶予の不足, メモリ・VRAM不足によるストリーミングの失敗, ポリサーによる超過分の破棄, 受信サーバーのホストでのパケット破棄, ファイアウォール・接続追跡による破棄, 中間機器の処理上限超過(ファイアウォール・IPS・DDoS対策)

最初から常に高い

跳ねることなく、ずっと高い値にとどまります。距離・経路・設計など、構造に起因する場合です。

補間バッファがないか短い, V-Syncとレンダーキュー, タイマー分解能, ディスプレイ・入力デバイス・フレーム生成による遅延, 伝搬遅延(物理的な距離), 迂回ルーティング, 過剰な割り込みコアレッシング, GRO/LROの結合待ちによる遅延, サーバーの電源管理(C-state・周波数制御)による遅延スパイク, Nagleアルゴリズム+遅延ACK, キャッシュミス, HDDのシーク遅延, サーバー応答後にだけ演出(リクエスト・レスポンス方式), 逐次往復の多いプロトコル(chatty), スキルの先行入力なし, クライアント権威型, 二重のティック待ち, 低いスナップショット送信レート, 順序の入れ替わりによる不要な高速再送, RTOの設定が環境に合っていない, 中間機器によるTCPオプションの除去

一部だけ高い

大部分は正常で、特定のユーザー・地域・ISP・端末だけが高くなります。

ストレージが遅くアセットストリーミングが間に合わない, クライアントのクラッシュ, セキュリティソフトによるパケット検査, オーバーレイソフトの干渉, RRC状態遷移の遅延(モバイル無線の省電力), モバイル電波の弱さ・不感地帯, 公衆Wi-Fi・社内ネットワークの制限, 衛星インターネット(低軌道・静止軌道), ECMP経路のうち1本の不良, 国・通信事業者単位のUDP制限・パケット検査, DNSの障害・遅延, VPN・ラグ軽減ツール経由, ロードバランサーの偏り・ヘルスチェックの誤判定, ケーブル不良・ポートエラー, MTUの不一致(大きなパケットだけ消える), 遅いクライアント(slow consumer)の処理ポリシー, keepaliveのデフォルト2時間, アイドル後のスロースタート, SO_REUSEPORTの振り分けの偏り, NUMAのリモートメモリ, 大量のマクロ・ボット, マッチメイキング・リージョン割り当ての誤り, Pingに削られる短い判定の受付時間, ラグコンペンセーションのない判定, 過剰なラグコンペンセーション, ホスト(部屋主)型の構成, 先行演出後のサーバー拒否, 回線が重い人がほかの人の画面でまとめて動く, 受信即時処理のサーバーで起きる早送り, プレイヤーごとの入力バッファのサイズ, 回線が重いパーティメンバー1人とボスのギミック, モンスターの制御権が遅いクライアントにある, 特定キャラクターのデータ肥大化, チャンネル・インスタンス・フェーズの違い, ロード中に届いた出現通知の破棄, 固定UDPポートの衝突, IP・端末基準のセッション識別バグ, 多重起動の制限, キャッシュ・アセットファイルへの同時アクセスの競合, 表示オプションの違い, クライアントのバージョン・データの不一致, 時刻推定の誤差によるオブジェクトの保留, 無線区間のパケットロス, 物理エラー(不良ケーブル・光モジュール・コネクター), MTUブラックホール(大きいパケットだけ繰り返し失われる), ACKの遅れ・消失(上り回線の飽和)

途切れた後にまとめて到着

しばらく受信量が0になった後、一気にまとめて届きます。

ウィンドウの最小化・非アクティブ時の処理制限, 基地局のハンドオーバー(移動中), クラウドホストのメンテナンス・ライブマイグレーション, NICドライバー・ファームウェアの問題, TCPのHOLブロッキング, TCPのRTOと指数バックオフ, バックグラウンドウィンドウの処理制限, thin streamの遅い回復, ゼロウィンドウ(再送のように見える停止)

接続が一斉に切れる

接続数がガクッと落ちるか、切断数が一瞬で跳ね上がります。

モバイルアプリのバックグラウンド移行, Wi-Fi ↔ LTE・5Gの切り替え, NATマッピングの期限切れ, 通信事業者の共有IP(CGNAT), ロードバランサーのアイドルタイムアウト, クラウドのセキュリティグループによる接続追跡の期限切れ, ネットワーク機器のフェイルオーバー, OOM Killer, WindowsのUDPソケットのWSAECONNRESETエラー, デッドロック, サーバークラッシュ, 無限ループ・ロジックの暴走, コアダンプの書き出し, DBのフェイルオーバー, 長い保存間隔による進行状況の消失, 補助サーバーの障害, デプロイ・再起動, TLS証明書の期限切れ・設定ミス, 接続中のNAT・ロードバランサーのマッピング期限切れ

接続直後・メンテ明けに急増

サーバーのオープンやイベント開始の直後に大きく跳ね上がり、徐々に落ち着きます。

メインスレッドでの同期ロード・シェーダーコンパイル, 接続待ちキュー(backlog)のあふれ, 密集エリア進入時のスポーン集中, コールドキャッシュ(再起動直後), ログイン殺到とN+1クエリ, オートスケーリングの遅れ, 入場直後に集中する出現情報の欠落, 接続要求(SYN)の再送

ゲームのコードなしでどこまで確認できるか

原因ごとに、最も手軽な確認手段を数えました。インフラのツールは、OS・ネットワーク・クラウド・DBのツールとランタイムの起動オプション(GCログなど)で確認できるので、ゲームのコードを変更しなくて済みます。ゲームのログ・メトリクスは、ティック時間や切断理由のように、ゲームが記録しないと見えないものです。この欄が多い層ほど、開発チームに計測を依頼する根拠になります。

数字の読み方

平均はスパイクを隠します。1秒に20ティックのサーバーでは、ティックの1%が遅いだけでも5秒に1回ほど全員の動きが一瞬止まりますが、平均ティック時間はほとんど変わりません。そのため、パーセンタイルもあわせて確認します。p50(中央値)は半分がこれより速い値、p99は100回のうち最も遅い1回付近の値です。ユーザーが「ラグ」として記憶するのは、たいていp99のほうです。

集計間隔もスパイクを隠します。1分平均のグラフでは、1秒の停止が1/60に薄まります。停止を探すときは、同じグラフの最大値やp99、より短い間隔のグラフもあわせて確認します。

ジッターは、パケットが届く間隔がどれだけばらつくかを表します。平均のPingが低くてもジッターが大きいと、補間バッファが空になってカクつき・ワープが起きます。

測り方何を測るか注意点
ping (ICMP)機器までの往復時間ルーター・サーバーがICMP応答を後回しにしたり数を制限したりすることがあるので、ゲームのパケットとは違う値になることがある。ブロックされていると応答がまったくない
mtr·traceroute区間ごとの遅延・パケットロス途中の機器1台だけロスが高く、その先の区間が正常なら、その機器がICMP応答だけを減らしている可能性が高い。最後まで続くロスだけが本当のロス
TCP RTT(ss -tiのrtt)カーネルが接続ごとに測った往復時間実際のゲーム接続の値なので、最も信頼できる。サーバー側でユーザーごとに確認できる
ゲーム内のPingゲームが独自のメッセージで測った往復時間ゲームループの中で測ると、フレーム・ティックの待ちが混ざる。回線が正常でも、サーバー・PCが忙しいと上がる

すぐできること、ゲームのコードに追加すること

ゲームのコードなしで
  • ディメンションの付与:接続・ロードバランサーのログにあるクライアントIPに国・通信事業者(ASN)を付け、「海外だけ」「特定の通信事業者だけ」が見えるようにします。
  • 接続品質:サーバーでss -tiやeBPFツールを使って接続ごとのRTT・再送を集め、ASN別に確認します。
  • サーバーの外からサーバーの中を見る:ソケットのキュー、スレッドごとのCPU(pidstat -t)、ランキュー遅延、起動オプションだけで有効にできるGCログ。
  • 経路の測定:対象の国・通信事業者側からの外形監視(RIPE Atlas、クラウドリージョンの測定用サーバー)とmtr。
  • 変更の記録:デプロイ・アップデート・設定変更・ネットワーク作業を、すべてのグラフに縦線で表示します。「アップデート後」かどうかを切り分ける出発点です。
ゲームのコードに最小限だけ
  • クライアントのサマリー報告:30〜60秒ごとにRTTのp50・p95、ジッター、パケットロス、FPS、フレームスパイクの回数、ビルド、サーバー・チャンネル。
  • サーバーのティックメトリクス:ティック時間のp50・p99、ティック超過の回数、ゾーンごとの人数、接続ごとの送信キュー。
  • 切断理由コード:ハートビートのタイムアウト・RST・サーバーによる切断・認証失敗・メンテナンスを、両側で同じコードに。
  • セッションIDと時刻:すべてのログにセッション・キャラクター・サーバーIDと、同期されたUTC時刻。
  • ラグ報告ボタン:直近60秒のRTT・FPS・ティックの空白を、セッションIDと一緒に送信します。
T3ツール

事例と手順

よく出くわす2つの状況での確認手順と、開発元・運営会社が自ら公開した実際の障害事例を集めました。各ステップと事例から、関連する原因カードにたどれます。

状況別の手順

アップデート後のラグ

特定のアップデート・デプロイの後からラグ報告が増えたとき。「今回のアップデートからおかしい」という報告が集まったときや、グラフがある時刻から階段状に上がって高止まりしている場合に使う。

  1. 開始時刻を確定し、その前後の変更をすべて集める: 報告が最初に集中した時刻と、グラフが階段状に上がった時刻を特定し、その前後に入った変更を漏れなく書き出す。クライアントのアップデート、サーバーのデプロイ、設定変更、DBのスキーマ変更(DDL)と再起動、ネットワーク・ファイアウォールの作業、インフラの入れ替え(インスタンスタイプ・カーネル・ドライバー)をあわせて確認する。デプロイのたびに監視ツールの注釈(annotation)機能ですべてのグラフに縦線を残しておけば、このステップはすぐに終わる。ゲームのアップデートとインフラ作業が同じメンテナンスで行われていたなら、両方を候補に残す。最初に呼ぶ担当:変更を入れたゲーム開発チームとインフラチームの両方。
  2. 範囲を切り分ける:ビルド・端末・サーバー・地域: 異常がどの軸に偏っているかを確認する。新しいビルドのユーザーだけが悪ければクライアント、特定のOS・グラフィックカード・端末だけならクライアントの性能やドライバー、特定のサーバー・チャンネル・ゾーンだけならサーバー、特定の国・通信事業者だけならネットワーク経路、全員が同時に悪ければ共有リソース(DB・ロードバランサー・ゲートウェイ)か直前のサーバーデプロイを、まず疑う。クライアントのテレメトリにビルド番号があれば、旧ビルドと新ビルドのPing・FPS・フレームスパイク・切断回数を並べて比較する。Pingは変わらずFPSだけが悪化したなら、ネットワークよりもクライアントの性能の問題だ。最初に呼ぶ担当:ビルド・端末に偏るならゲーム開発チーム(クライアント)。サーバー・チャンネルに偏るなら、ホストのメトリクスが正常な場合はゲーム開発チーム(サーバー)、異常な場合はインフラチーム(サーバー機器・OS)。国・通信事業者に偏るならインフラチーム(ネットワーク)。
  3. 新旧バージョンを同じ時間帯で比較する: デプロイ前後の比較だけでは、曜日・時間帯・イベントによる変化が混ざり、判断がぶれる。可能なら新バージョンを一部のサーバー(カナリア)に先に入れ、同じ時間帯の旧バージョンのサーバー(対照群)と、ティック時間のp50・p99、ティック超過回数、CPU、メモリ、エラー率を並べて比較する。すでに全体にデプロイ済みなら、先週の同じ曜日・同じ時間帯と比較する。サーバー全体の平均だけでは一部のサーバー・ゾーンの問題が埋もれるので、サーバー・ゾーン別に分けて確認する。最初に呼ぶ担当:ゲーム開発チーム(サーバー)。
  4. トラフィックのフィンガープリントを前後で比較する: サーバーのコードを知らなくても、ネットワーク側から見える値で、アップデートがトラフィックの形を変えたかどうかを確認する。ユーザーあたりの秒間パケット数(pps)とバイト数、平均・最大パケットサイズ、接続数、ティックごとに一気に送り出される送信バーストの大きさを前後で比較する。UDPパケットが経路MTU(通常1,500バイト)を超え始めたなら、IPフラグメンテーションが起きている。フラグメントが一つ失われるだけでパケット全体が失われ、フラグメントを最初から破棄するNAT・ファイアウォールもある。途中でMTUの小さい区間(トンネル・VPN)を通るユーザーでは、大きなパケットだけが消える。ppsが増えたなら、クラウドインスタンスのPPS上限や、ファイアウォール・DDoS対策機器の処理上限に達していないかを確認する。最初に呼ぶ担当:フィンガープリントが変わっていれば証拠を添えてゲーム開発チーム(サーバー)、変わっていないのにパケットロス・再送だけ増えたならインフラチーム(ネットワーク)。
  5. DBクエリの種類と回数を前後で比較する: DBの遅延が増えたなら、まずクエリ数(QPS)も一緒に増えたかを確認する。PostgreSQLのpg_stat_statementsやMySQL Performance Schemaのdigestサマリーは、値だけが異なるクエリをひとまとめにして実行回数と合計時間を集計してくれる。アップデート前後の上位クエリ一覧を比較すれば、新たに現れたクエリ、回数が数倍に増えたクエリ(N+1)、インデックスを使わずにテーブル全体を読むクエリ(MySQLではSUM_NO_INDEX_USEDカラム)が浮かび上がる。最初に呼ぶ担当:QPSやクエリの形が変わっていればゲーム開発チーム(サーバー)、クエリは同じで遅延だけ増えたならインフラチーム(DB:実行計画・IOPS・ロック)。
  6. ホストとサーバープロセスのメトリクスで階層を切り分ける: コードに頼らず、OSから見える値でサーバープロセスの内側とホストを切り分ける。サーバーソケットの受信キュー(Recv-Q)がたまっていれば、サーバープロセスが時間どおりに読み出せていない(ティックの停止・GC・ロック)。一つのスレッドだけが100%ならシングルスレッドのボトルネック、GCログの停止時間が延びていればメモリの使い方が変わったということだ。ログレベルを上げたままデプロイしてログ書き込みが増えていないかも確認する。逆に、CPUスチール・スロットリング・NICのドロップが増えていれば、同じ時刻に変わったインフラ(インスタンスタイプ・カーネル・コンテナの上限)を確認する。最初に呼ぶ担当:プロセス内側のシグナルならゲーム開発チーム(サーバー)、ホストのシグナルならインフラチーム(サーバー機器・OS)。
  7. 元に戻して確定し、記録を残す: 最も有力な変更を一部のサーバーや一部のユーザーに対してだけ元に戻す(ロールバック、フィーチャーフラグをオフ)か、設定を以前の値に戻し、症状も一緒に消えるかを確認する。戻した側だけが改善すれば原因が確定する。戻す作業でも再起動とコールドキャッシュで一時的に重くなることがあるので、急ぎでなければ空いている時間帯に行う。結果は原因IDとともに障害記録に残し、パケットサイズ・クエリ数・ティック時間の上限を、次のアップデートのデプロイ前チェック項目に加える。最初に呼ぶ担当:変更を入れたチーム。

海外の国・地域の追加

サービス提供国を新たに開くとき、または新しいリージョン・データセンターを追加するとき。オープン前の点検と、「国内は問題ないのに新しい国のユーザーだけラグい」という報告の切り分けの両方に使う。

  1. 現地の通信事業者ごとの経路品質をオープン前に測る: 対象国の主要な通信事業者(ASN)ごとに、ゲームサーバーの候補地までの往復時間(RTT)の分布、ジッター、パケットロスを測る。平均値一つでは通信事業者ごとの差が埋もれるので、通信事業者別の中央値と95パーセンタイルを、夜のピークと深夜に分けて確認する。公開測定網のRIPE Atlasでは、国・ASNを指定して世界中のプローブからping・tracerouteを送れる。候補リージョンに一時的なVMを立てて測ってもよい。途中の機器がICMP応答をレート制限することもあるので、可能ならゲームと同じプロトコル・ポートでも測る。特定の通信事業者だけが際立って遠い都市を経由していれば、ピアリング・経路の問題だ。通信事業者は遅延よりもコストの低い経路を選ぶため、近い場所でも遠回りすることがある。最初に呼ぶ担当:インフラチーム(ネットワーク)、経路が通信事業者側の問題なら外部(通信事業者・IX)。
  2. 測定値を、ゲーム設計が耐えられる上限と比較する: 測ったRTT・ジッターを、ゲームの判定の受付時間(回避・パリィなどの反応時間)、ラグコンペンセーションの上限、補間バッファの長さ、入力バッファのサイズと比較する。たとえばパリィの判定が0.2秒なら、往復遅延と補間バッファを足した値がそれより長い通信事業者のユーザーは、タイミングどおりに反応しても間に合わない。ラグコンペンセーションを広げて合わせると、今度は攻撃を受ける側から「壁の裏にいたのに当たった」という報告が増える。上限を超える通信事業者が多ければ、インフラチームはリージョン・エッジPoPをより近くに置く案を、ゲーム開発チームは判定・補間・ラグコンペンセーションの値を検討する。白書の「同期方式」の章が基準表になる。最初に呼ぶ担当:ゲーム開発チーム(サーバー・クライアント:設計上の上限)、インフラチーム(ネットワーク:リージョン・PoPの位置)。
  3. MTUとUDPが通るかを確認する: 現地のネットワークで、ゲームの最大パケットが欠けずに通るかを確認する。フラグメント化禁止(DF)フラグを立てたpingをサイズを変えながら送って経路MTUを測り、PPPoE・トンネル・モバイル回線のように1,500バイトより小さい区間がないかを確認する。UDPのようなデータグラム転送の標準(RFC 8899)は、IPv4でほとんどの経路を通過できる基本サイズとして1,200バイトを推奨している。ゲームの最大パケットがこれより大きければ、小さくするか分割して送る方法をゲーム開発チームと決める。公衆Wi-Fi・社内ネットワーク・一部の通信事業者でUDPやゲームのポートがブロックされたり速度制限されたりしないかも確認し、ブロックされたときの代替経路(TCP・443番ポート)があるかを確認する。最初に呼ぶ担当:インフラチーム(ネットワーク)とゲーム開発チーム(サーバー:パケットサイズ)。
  4. NAT・CGNATのアイドルタイムアウトを測り、ハートビート間隔を合わせる: 現地の家庭用ルーターとモバイル回線(CGNAT)が、アイドル状態のUDP接続のマッピングをどれくらいで消すかを測る。試験ごとに、テスト端末からサーバーへパケットを一つ送ってマッピングを作り、その後は端末から何も送らず、決めておいた時間(30秒、60秒、120秒…)が過ぎてからサーバーが端末へパケットを送るようにする。端末がそのパケットを受け取れなくなり始める時間が、そのネットワークのアイドルタイムアウトだ。標準(RFC 4787)は、UDPマッピングを2分未満で期限切れにしてはならず、デフォルトは5分以上を推奨しているが、機器によって値は大きく異なり、もっと短く消す機器もある。マッピングが確実に更新されるのは端末から出ていくパケットだけなので、ハートビートはクライアントから送る。その間隔が、測った値とロードバランサー・クラウドのセキュリティグループのアイドルタイムアウトのうち最も短い値の半分以下になっているかを確認する。最初に呼ぶ担当:ゲーム開発チーム(クライアント:ハートビート間隔、サーバー:タイムアウト値)、インフラチーム(ロードバランサー・セキュリティグループの設定)。
  5. 現地で経由する外部サービスとセキュリティ機器を確認する: 現地のプラットフォームのログイン・決済・本人認証が本来の速さで応答するか、現地のDNSでログインサーバー・アップデートサーバーのアドレスが正しく解決されるか、CDNがその国に近い拠点からアップデートデータを配信しているかを確認する。DDoS対策・ファイアウォールの国別ブロックルールやレート制限に新しい国のIPアドレス帯が引っかからないかを確認し、特に複数の加入者が一つのIPを共有するCGNATのアドレス帯がまとめてブロックされないかを確認する。最初に呼ぶ担当:インフラチーム(セキュリティ機器・DNS・CDN)、外部(プラットフォーム・決済事業者・通信事業者)。
  6. オープン後は国・ASN別に分けて確認する: 接続ログ・ロードバランサーログのクライアントIPに国とASNを付与し、国・通信事業者別にRTT、再送、切断の回数と理由(ハートビートタイムアウト・RST・サーバーからのキック)を確認する。MaxMind GeoLite ASNのような無料データベースでIPをASNと組織名に変換できる。現地の個人情報保護規制に合わせて、IPは/24やASN単位に丸めて保管する。一つのASNだけに集中していればその通信事業者の経路(インフラチーム・外部)、新しい国全体が悪ければ距離と設計上の上限(インフラチーム・ゲーム開発チーム)、夜だけ悪化するならピアリングの輻輳を、まず疑う。一部のユーザーだけ常にPingが高ければ、GeoIPの誤り・VPN・パーティリーダー基準の割り当てによって遠いリージョンに割り当てられていないかを、ゲーム開発チーム(サーバー)と一緒に確認する。外形監視は正常なのにユーザーだけが悪ければ、ユーザー環境かクライアント側の問題だ。
  7. 遠い地域のユーザーがほかのユーザーに与える影響を確認する: 遠くから接続するユーザーが増えると、その人の画面が悪くなるだけでは済まない。遅延の大きい人の入力がまとめて届くため、ほかの人の画面ではそのキャラクターだけが早送りで動き、サーバーの速度・クールタイムのチェックに引っかかって引き戻しやスキルの拒否が起きる。パーティギミックでは、遅延の大きい一人の反応の遅れがパーティ全体の失敗につながり、ロックステップ方式では最も遅い人を全員が待つ。新しい国のオープン後に既存ユーザーからの「特定のキャラだけおかしく見える」という報告が増えていないかを確認し、入力バッファ・検証の許容値・マッチング地域の分離をゲーム開発チームと決める。最初に呼ぶ担当:ゲーム開発チーム(サーバー)。

実際の障害事例

ゲーム会社とインフラ企業が自ら公開したポストモーテム(事後分析)だけを選びました。要約は原文が明らかにしている範囲内で書いています。詳しい経緯は原文を参照してください。

CCP Games 2014: EVE OnlineのHED-GP大規模艦隊戦でのサーバー過負荷

2014年1月のポストモーテムで取り上げられたHED-GP星系の大規模艦隊戦で、サーバーが深刻な過負荷に陥った。Time Dilation(過負荷時にゲーム内の時間の進みを遅くする機能)が下限の10%に達し、戦場全体がスローモーションになった後も負荷はたまり続けた。モジュールの停止や繰り返し作動を処理する作業の遅れ(Dogma Lateness)は、最大でゲーム内時間193秒、実時間で約32分に達した。規模がほぼ同じだった2013年7月の6VDTの戦闘では、最大42秒(実時間で約7分)だった。 CCPは、性能分析ツール自体が負荷を増やすためこうした状況では動かしておらず、確実なことは言えないと前置きしたうえで、2つを有力な原因に挙げた。1つは、戦闘が長引くにつれて処理しきれない負荷がたまり続けたことだ。もう1つはドローンの使用増加で、戦闘中に展開されたドローンの数(重複を除く)は6VDTが21,123機、HED-GPが38,852機と84%多かった。一人の行動を、それが見える全員に知らせる送信は人数の二乗(O(n²))で増えるが、ドローンは1回の攻撃で発生するメッセージがさらに多い。ドローンが攻撃対象を選ぶコードも、同じ戦場で攻撃可能な対象を頻繁に総当たりで調べるため、コストがn²に近い形で増える。

人が集中した一つのエリアの処理量が限界を超えると、そのエリア全体がスローモーションになり、戦闘が長引くほど処理の遅れがたまって入力遅延が大きくなる。確認すべきシグナルは、そのエリアを担当するサーバー(ノード)のティック時間・滞留した作業量と、人数・オブジェクト数だ。ほかのエリアは正常なのが特徴だ。主担当はゲーム開発チーム(サーバー)で、一つの行動を通知する相手の範囲と、AIの対象探索コストが改修ポイントになる。ゲーム内の時間を遅くする設計で過負荷そのものはなくせないが、全員が同じ速さで遅くなるので、一部の行動だけが際限なく後回しになることを防げる。 原文

Riot Games 2015: 遠回りしていたLeague of LegendsのトラフィックとRiot Direct

Riot Gamesが、インターネットがリアルタイムゲームに向いていない理由を解説した技術記事だ。League of Legendsのユーザーが報告した実際のトラフィックは、サンフランシスコからポートランドへまっすぐ向かうべきところをロサンゼルス、デンバー、シアトルを経由しており、直行なら14msで済むところが70msかかっていた。Riotは、ルーターがあふれてパケットが破棄されると、ほかのチャンピオンが画面上で飛び跳ねるように動き、投射物がワープしたように見えると説明した。 Riotは経路とルーターを原因に挙げた。バックボーン事業者と通信事業者は、遅延が最も短い経路よりもコストが最も安い経路でトラフィックを流し、BGPで決まった経路が遠回りになれば経由するルーターの数も増える。ルーターの処理負荷は、パケットのサイズに関係なく個数に比例する。ゲームのパケットは55バイト前後なので、同じデータ量なら1,500バイトのパケットより個数が27倍になり、その分ルーターの入力バッファを早く埋める。Riotの説明によれば、過負荷になるとUDPパケットから先に破棄するルーターも多い。解決策としてRiotは、米国の主要なインターネット拠点10か所にルーターを置き、できるだけ多くの通信事業者と直接接続(ピアリング)する自社ネットワークRiot Directを構築した。第2部によると、Pingが80ms未満でプレイするユーザーの割合は9か月あまりで31%から50%に上がり、ゲームサーバーをシカゴに移すと一晩で80%になった。

同じ国の中でも特定の通信事業者のユーザーだけPingが際立って高ければ、経路を疑う。確認すべきシグナルは、通信事業者(ASN)別のRTT分布と、tracerouteに表れる経由都市だ。主担当はインフラチーム(ネットワーク)で、通信事業者との直接ピアリング、IX接続、サーバーの設置場所の選定で解決する。通信事業者側の経路ポリシーは、外部(通信事業者)と協議する事項だ。サーバーをユーザー分布の中心近くに移すだけでも効果が大きいことも、この事例は示している。 原文

Riot Games 2020: League of Legendsの欧州・ブラジルサーバーでのエッジホスト過負荷

2020年2月末、League of LegendsのEUW・EUNE・BRサーバーで障害が何度も発生し、新たに始まるゲームの数が大きく減った。マッチング・ゲームサーバーなどのバックエンドサービスはどれも正常な状態だったが、流入するトラフィックがほとんどなかった。Riotは、不安定になりうるクラスターでトーナメントモード(Clash)を開催しないよう、日程を1週間延期した。ポストモーテムには、障害ごとの継続時間は書かれていない。 3つの要素が重なった。あるサービスへのリクエストが誤った形で組み立てられており、特定の条件で失敗と再試行を繰り返したため、リクエストが急増した。コンテナシステムとOSバージョンの既知の相性問題でOS内部のメモリがリークしていたが、アップグレードはRiotのコンテナ環境全体の約60%でしか終わっておらず、欧州・ラテンアメリカのクラスターは作業中だった。インターネットからのトラフィックを受けてフィルタリングし、バックエンドへ渡すエッジコンテナは、同じシャード(サーバー群)の中では別々のホストに配置されていたが、異なるシャード同士が同じホストに載るのは防げていなかった。そのため障害のたびに、少なくとも3つのシャードのエッジコンテナが1台のホストに集中していた。再試行の急増がそのホストに重なり、メモリリークがそのホストを停止させた。

バックエンドのサービスがどれも「正常だがトラフィックが来ない」という状態なら、その手前(エッジ・ゲートウェイ・ロードバランサー)を確認する。確認すべきシグナルは、ホスト別のインバウンド接続数の偏りと、特定リクエストの失敗・再試行の比率だ。主担当はゲーム開発チーム(サーバー:誤ったリクエストと再試行の方式)で、コンテナの配置ルール・OSのアップグレード・偏りのアラートはインフラチーム(サーバー機器・OS)が受け持つ。Riotはリクエストのコードを修正して再試行が急増しないように変え、シャード間の分散配置を実装するまでの間、偏りを検知するアラートを設けた。 原文

Riot Games 2021: League of Legends EUWの5時間障害:補助的なDB一つでサーバー全体が停止

2021年1月22日、League of LegendsのEUWサーバーが5時間強にわたって正常に動作しなかった。ログイン中のユーザー数とゲーム中のユーザー数のメトリクスが一斉に途切れ、2回の再起動の間は、ログインは増えてもゲームはほとんど始まらなかった。 重要度の低い機能を担うDBのプライマリサーバーでハードウェア故障が起き、そのDBには予備サーバーへの自動フェイルオーバーが設定されていなかった。コネクションプールはDBごとに分かれていたが、すべてのプールが同じスレッドプールを使っており、故障したDBに送った処理が終わらないままスレッドを占有したため、システム全体で使えるスレッドが枯渇した。大量のアラートが鳴る中、最近受けた悪意あるネットワーク攻撃や別リージョンでのハードウェア作業を先に疑ったため、故障したDBのアラートに気づいたのは約1時間後だった。すべてのシステムが1つのJVMで動く構成だったため、再起動後の再接続の負荷の中でGCがプロセスを数秒ずつ止めると、メトリクス収集にも大きな空白が生じた。ログイン待機列も設定した上限を守らず、流入が安定しなかった。

重要ではないと考えていた補助的なDB一つでも、スレッドプールのような共有リソースを通じて全体を止めうる。確認すべきシグナルは、DB別の待機中リクエスト数とスレッドプール使用率、そしてログイン数に対してゲーム開始数が少なすぎる比率だ。担当はゲーム開発チーム(サーバー:スレッドプールの分離・タイムアウト)とインフラチーム(DB:自動フェイルオーバー)だ。アラートが大量に出ているときは最近経験した問題(攻撃など)から疑いがちなので、切り分けの順序(範囲 → 時点 → 階層)に沿って一つずつ除外する。再起動後は、ログイン待機列が設定どおりに流入を制限しているかもあわせて確認する。 原文

Roblox 2021: Robloxの73時間障害:サービスディスカバリ(Consul)クラスターでの競合

2021年10月28日午後(太平洋時間)、Consulサーバー1台の高いCPU負荷から始まり、16時35分に接続中のユーザー数が普段の半分に落ちた後、サービス全体が停止した。すべてのユーザーが再び入れるようになったのは10月31日16時45分で、障害発生から73時間かかった。Robloxは、毎日5千万人が利用していると公表している。 Robloxはサービスディスカバリ(サービス同士が互いのアドレスを見つける仕組み)、ヘルスチェック、KVストアにHashiCorp Consulを使っており、1つのConsulクラスターが複数のワークロードをまとめて担っていた。根本原因は2つあった。1つ目は、数か月かけて適用範囲を広げてきたConsulの新しいstreaming機能を、障害の前日にトラフィックルーティングサービスでも有効にし、そのサービスのノード数を50%増やしたことだ。読み込みと書き込みがどちらも非常に多い負荷のもとで、この機能は1つの共有リソース(Goのチャネル)での競合を引き起こした。障害中に入れ替えた、コア数がより多いデュアルソケット(NUMA)サーバーでは、競合がさらに激しくなった。2つ目は、ConsulがRaftログの保存に使うBoltDBで空きページリスト(freelist)の管理が異常に遅くなり、16kB以下のデータを追加するたびに7.8MBをディスクに書き込んでいたことだ。普段は300ms未満だったKV書き込みレイテンシの中央値は2秒になり、遅いリーダーサーバーではTCPバッファが満杯になるゼロウィンドウも観測された。テレメトリもConsulに依存していたため、原因調査に必要なメトリクスまで一緒に失われた。

複数のサービスが共通して依存する基盤システム(サービスディスカバリ・設定ストア・認証)が遅くなると、すべての機能が一斉に止まる。確認すべきシグナルは、そのシステムの書き込みレイテンシ・リーダー交代・CPUと、障害直前の設定変更だ。担当はゲーム開発チーム(サーバー)とインフラチーム(サーバー機器・OS)の両方だ。障害時にもメトリクスを確認できるよう、監視は監視対象のシステムに依存しない形で分離しておく。復旧時はキャッシュが空で、一気に受け入れると再び崩れるおそれがあるため、RobloxはDNSで入場できるユーザーの割合を調整しながら約10%ずつ増やした。 原文

Square Enix 2021: FINAL FANTASY XIVの拡張パッケージ発売時の混雑とログイン待機列のエラー

2021年12月、拡張パッケージ『暁月のフィナーレ』(Endwalker)のアーリーアクセス開始から、各ワールドが極度に混雑した。ログイン待機列が長くなり、キャラクター選択画面からログインするときや待機列で待っている間にエラー2002が頻発した。一部のワールド・ゾーンのダウン(エラー3001)や待機列のタイムアウト(エラー4004)も起きた。12月11日のお知らせの時点でも、アーリーアクセス8日目で混雑が続いていた。 エラー2002は2つのケースで発生する。1つは、論理データセンターごとの待機人数が17,000人を超えたときだ。待機列が長くなりすぎてログインサーバーがダウンするのを防ぐための上限で、このときはクライアントが完全に終了する。12月7日に開発用の予備機材をロビーサーバーに投入して上限を引き上げると、このエラーは減ったものの、待機列はかえって長くなった。もう1つは、待機中のユーザーの回線が不安定なときだ。待ち時間が長くなるにつれ、インターネット経路のパケットロスやWi-Fiの不安定さで接続が一瞬切れることが増えた。ロビーサーバーは数十秒から1分ほど再接続を待ち、その間に再接続できれば待機列の途中から再開できるが、それを過ぎると最後尾に並び直しになる。スクウェア・エニックスは、報告の大半がこのケースだとしている。半導体不足のため、ワールドをすぐに増やすこともできなかった。

待機列が長くなるほど、待機中のユーザー回線で起きる瞬断が接続エラーに変わる。同じ混雑の中でも、Wi-Fiや不安定な回線を使う人にエラーが集中する「一部のユーザーだけに起きる問題」になる。確認すべきシグナルは、待機列の長さ・待ち時間と、切断理由のうち待機中の切断が占める割合だ。主担当はゲーム開発チーム(サーバー:待機列の上限と再接続の猶予時間)で、ロビー・ワールドサーバーの増設はインフラチームが一緒に行う。再接続の猶予時間を十分に取れば、ユーザー回線の瞬断が待機順を失う事態に発展するのを減らせる。 原文

Cloudflare 2020: Cloudflareのバックボーン設定ミスで一部都市のトラフィックが途絶

多くのゲームがWeb・API・DDoS対策をCDN事業者に任せているため、ゲームも巻き込まれるタイプのインフラ障害だ。2020年7月17日21:12から21:39(UTC)までの27分間、Cloudflareネットワーク全体のトラフィックが約50%減少した。影響はバックボーンに接続された米国・欧州・ロシア・ブラジルの一部都市の拠点に限られ、ほかの拠点は正常だった。 ニューアークとシカゴを結ぶバックボーン区間の障害でアトランタとワシントンを結ぶ区間が輻輳したため、エンジニアがアトランタのバックボーントラフィックを減らそうとルーターの設定を変更した。ポリシーの項目(term)全体を無効にすべきところ、その中の条件(prefix-list)だけを無効にしたため、アトランタのルーターがすべてのBGP経路をより高い優先度(local-preference 200)でバックボーン全体に広報した。各拠点が自拠点のサーバーへの経路に設定していた優先度は100だったため、バックボーンに接続された拠点のトラフィックがすべてアトランタに集中した。アトランタは過負荷になり、影響を受けた拠点では処理するトラフィックがほとんどなくなった。アトランタのルーターをバックボーンから外すと復旧した。Cloudflareは、攻撃や侵害とは関係がないと説明した。

特定の都市・地域のユーザーだけが一斉に切断されたり接続不可・無限ロードになったりして、ほかは正常なら、直前の経路設定の変更をまず疑う。グラフでは一つの拠点だけCPU・トラフィックが急上昇し、影響を受けた拠点はむしろ0近くまで落ちる。主担当はインフラチーム(ネットワーク)で、事業者側の障害なら外部だ。Cloudflareは、バックボーンのBGPセッションに受信できる経路数の上限(maximum-prefix)を設けることにし、ある拠点がほかの拠点のトラフィックを引き寄せられないよう優先度を調整した。 原文

Fastly 2021: Fastly CDNで世界規模のエラー

多くのゲームがアップデートファイル・ランチャー・WebページをCDNで配信しているため、ゲームも巻き込まれるタイプのインフラ障害だ。2021年6月8日09:47(UTC)から、Fastlyネットワークの85%がエラーを返した。49分以内にネットワークの95%が正常に戻り、12:35に障害は収束した。 5月12日に始まったソフトウェアのデプロイに、特定の顧客設定が特定の条件を満たしたときに発動するバグが含まれていた。6月8日、ある顧客が正当な設定変更を反映したことで、その条件がそろった。Fastlyは1分で異常を検知し、原因となった顧客設定を特定して無効にすると復旧が始まった。バグ修正のデプロイは同日17:25に開始した。

デプロイから数週間たったコードでも、まれな条件に当たると一瞬で世界規模の障害になる。ゲーム側で確認すべきシグナルは、アップデート・ランチャー・WebリクエストのHTTPエラー率がすべての地域で同時に上がることと、CDN事業者のステータスページだ。接続済みのゲーム通信はCDNを経由していなければ正常で、新規接続・アップデートのダウンロード・Webログインだけが止まるのが特徴だ。主担当は外部(CDN事業者)で、ゲーム開発チーム・インフラチームは、CDNを複数使うか、オリジンサーバーから直接取得する迂回経路を用意しておく。 原文

Meta 2021: バックボーンへのコマンド一つでDNSまで消えたFacebookの障害

ゲーム会社の自社ネットワークとDNSにもそのまま当てはまるインフラ障害だ。2021年10月4日、Facebook(現Meta)のサービスに世界中で接続できなくなった。データセンター間をつなぐバックボーンがすべて切れ、インターネット側からFacebookのDNSサーバーを見つけられなくなった。ポストモーテムには、障害の継続時間は書かれていない。 定期メンテナンス作業中、世界全体のバックボーン容量を確認するために実行したコマンドが意図に反してバックボーンのすべての接続を切断し、こうしたコマンドを止めるはずの監査ツールはバグのため止められなかった。小規模拠点のDNSサーバーは、データセンターと通信できないと自らを異常と判断してBGP広報を取り下げる仕組みだったため、DNSサーバーは動いているのにインターネットから到達できなくなった。通常のアクセス経路も帯域外(out-of-band)アクセスもすべて断たれ、内部ツールもDNSを失ったため、エンジニアをデータセンターへ直接派遣する必要があり、セキュリティ手順のためにさらに時間がかかった。復旧時は、データセンターごとに電力使用量が数十MWずつ落ちていたため、一気に戻すと電力設備からキャッシュまで危険にさらされうると判断し、負荷を段階的に上げた。

すべての地域・すべての通信事業者で同時に接続不可・無限ロードが起きたら、ゲームサーバーよりも先にDNSとBGP経路を確認する。外部からのDNS問い合わせと公開されているBGP経路情報を使えば、社外からでも確認できる。主担当はインフラチーム(ネットワーク)だ。障害時に使う帯域外アクセス経路や内部ツールが同じDNS・ネットワークに依存していないかを事前に点検し、復旧時は再接続が一気に集中しないよう負荷を段階的に上げる。 原文

AWS 2021: AWS us-east-1の内部ネットワーク輻輳

多くのゲームがサーバー・ログイン・データをパブリッククラウドに置いているため、ゲームも巻き込まれるタイプのインフラ障害だ。2021年12月7日午前7時30分(太平洋標準時)、北バージニアリージョン(us-east-1)の内部ネットワークが輻輳した。7時33分からEC2 APIのエラーと遅延が増えて新しいインスタンスを起動しにくくなり(インスタンスの起動は午後2時40分に回復)、コンソールへのログイン失敗、Route 53の設定変更不可、CloudWatchメトリクスの遅延と一部欠損が続いた。ネットワーク機器は午後2時22分に完全に回復した。すでに稼働していたEC2インスタンスと既存のDNS応答は影響を受けなかった。 メインネットワーク上のあるサービスの容量を増やす自動処理が、内部ネットワークの多数のクライアントで予期しない動作を引き起こし、接続試行が急増した。内部ネットワークとメインネットワークをつなぐ機器があふれて通信が遅延し、その遅延がさらに接続試行と再試行を増やして輻輳が続いた。クライアントにはこうした輻輳時にリクエスト間隔を広げるバックオフの仕組みがあったが、潜在的な不具合のため正しく動作しなかった。内部の監視も同じネットワークに依存していたため、運用チームはリアルタイムのメトリクスなしにログを頼りに対応した。

再試行の間隔を広げられないと、短い輻輳が数時間の障害になる。ゲーム側から見ると、稼働中のゲームサーバーは正常でも、新しいサーバーの増設(オートスケーリング)、クラウドAPIを使うログイン・マッチング・決済、監視がまとめて止まることがある。確認すべきシグナルは、クラウド事業者のステータスページ、クラウドAPIのエラー率、インスタンスの起動失敗だ。主担当は外部(クラウド事業者)だ。ゲーム開発チームはすべての再試行にランダムな間隔の指数バックオフと回数制限を設け、インフラチームは増設できなくても持ちこたえられる余剰容量と、別リージョンという代替手段を用意する。 原文

Cloudflare 2025: CloudflareのパブリックDNS 1.1.1.1の障害

ユーザーが端末やルーターに自分で設定して使うパブリックDNSリゾルバーの障害で、その設定を使うユーザーに限って、すべてのゲームとサービスがまとめて使えなくなるタイプだ。2025年7月14日21:52から22:54(UTC)までの62分間、1.1.1.1リゾルバーが世界中で応答しなかった。Cloudflareは、多くの利用者にとってこれは事実上すべてのインターネットサービスが使えないことを意味したと述べている。UDP・TCP・DNS over TLSによる問い合わせが影響を受け、ドメイン名で接続するDNS over HTTPSは比較的安定していた。 6月6日、今後使う予定の別サービスのサービストポロジー(どの拠点からIPアドレス帯を広報するかを定めた構成)を準備する際、1.1.1.1リゾルバーのIPアドレス帯が誤ってその構成に含められた。7月14日にそのサービスの構成を変更すると、リゾルバーのアドレス帯を広報する拠点が全拠点からオフラインの1か所に減り、世界中でBGP経路が取り下げられた。この変更はカナリアリリースを経ずに、すべてのデータセンターへ即座に反映された。22:20に設定を戻すとトラフィックは約77%まで回復したが、その間にエッジサーバーの約23%で必要なIP設定が消えていたため再設定が必要になり、正常に戻ったのは22:54だった。Cloudflareは、攻撃やBGPハイジャックとは関係のない内部の設定ミスだと説明した。

ゲームサーバーもほかのユーザーも正常なのに、一部のユーザーだけがログインサーバーやアップデートサーバーに接続不可・無限ロードになるなら、そのユーザーが使っているDNSを疑う。接続済みのセッションは維持され、新規接続だけが失敗するのが特徴だ。ユーザーにDNS設定を変えてもらうか、サーバーのアドレスを直接問い合わせてもらえば、すぐに見分けがつく。主担当は外部(DNS運営者・通信事業者)だ。ゲーム開発チーム(クライアント)が名前解決の失敗をほかのエラーと区別して表示すれば、カスタマーサポートがその場で切り分けられる。 原文

AWS 2025: AWS us-east-1のDynamoDB DNS障害と長引いた復旧

多くのゲームがサーバー・ログイン・データをパブリッククラウドに置いているため、ゲームも巻き込まれるタイプのインフラ障害だ。2025年10月19日午後11時48分から20日午後2時20分(太平洋夏時間)まで、北バージニアリージョンで3段階にわたって影響が続いた。20日午前2時40分まではDynamoDB APIのエラーが増え、午前2時25分から10時36分までは新しいEC2インスタンスの起動が失敗し(一部の新しいインスタンスの接続問題は午後1時50分に解消)、午前5時30分から午後2時9分までは一部のNetwork Load Balancer(NLB)で接続エラーが増えた。 DynamoDBのDNSを管理する自動化の仕組みに、潜在的な競合状態(race condition)があった。異なるアベイラビリティーゾーンでDNSプランを適用する実行コンポーネント(DNS Enactor)のうち、異常に遅れていた1つが古いプランで新しいプランを上書きした直後に、別の実行コンポーネントのクリーンアップ処理がその古いプランを削除し、リージョンエンドポイント(dynamodb.us-east-1.amazonaws.com)のDNSレコードが空になった。自動化の仕組みではこれを修復できず、人手で復旧する必要があった。EC2の物理サーバー管理システムはDynamoDBに依存していたため、その間に物理サーバーごとに維持していたリース(lease)が期限切れになった。DynamoDBが復旧した後は、物理サーバーの数が多すぎてリースを結び直す処理が終わる前にタイムアウトし、再試行の処理が再びたまって「輻輳崩壊(congestive collapse)」の状態に陥った。新たに起動したインスタンスのネットワーク設定の反映が遅れたため、NLBのヘルスチェックが成功と失敗を行き来し、正常なノードまでDNSから外れては戻ることを繰り返した。

一か所のDNSレコードの誤りが、そのサービスに依存する別のサービスへ波及し、原因が解消した後も、滞留した処理とヘルスチェックの不安定さのせいで復旧にさらに数時間かかる。ゲーム側から見ると、稼働中のサーバーは持ちこたえても新しいサーバーを起動できずにオートスケーリングが止まり、ヘルスチェックが不安定になるとロードバランサーが正常なサーバーを外してしまうことがある。確認すべきシグナルは、クラウドのステータスページ、マネージドサービスのAPIエラー率、インスタンスの起動失敗、ロードバランサーの正常なターゲット数だ。主担当は外部(クラウド事業者)で、インフラチームはヘルスチェックの失敗で一斉に外れるサーバー数を制限し、別リージョンという代替手段を用意する。 原文

T4ツール

ラグ報告ガイド

ゲーム開発チームやインフラチームが原因を探すとき、最も時間がかかるのは「いつ、どこで、誰に」起きたかを突き止める作業です。下の項目を埋めてもらえれば、ログやグラフからその瞬間をすぐに見つけられます。

T5ツール

用語集

ゲーム開発チームやインフラチームと話すときによく出てくる言葉です。検索欄に日本語か英語で入力してみてください。

Ping Ping, RTT
自分が送った信号がサーバーまで行って戻ってくるまでの時間(往復)。ゲームに表示されるPingには、サーバーの処理待ち時間が含まれていることもあります。
遅延 Latency
パケットが送り出されてから到着するまでの時間。片道を指すことが多く、Pingのおよそ半分です。
ジッター Jitter
到着間隔のばらつき。平均Pingが同じでも、ジッターが大きいと画面がカクつきます。
パケット Packet
ネットワークで一度に送るデータのまとまり。通常は最大1,500バイトで、ゲームの更新データは数十〜数百バイトです。
パケットロス Packet loss
送ったパケットが届かずに消えること。TCPを使うゲームでは1%でも数秒〜十数秒に一度カクッと止まるのが感じられ、補間や入力の重複送信を備えたUDPのゲームなら数%まで隠せることもあります。
帯域幅 Bandwidth
回線が1秒間に送れる最大データ量(Mbps)。どれだけ早く届くか(遅延)とは別の概念です。
ティック Tick
サーバーがゲーム状態を一度計算する単位。20ティックのサーバーは1秒に20回、50msごとに計算します。
ティックレート Tick rate
1秒間にティックを何回回すか。高いほど反応が速くなりますが、サーバーコストと通信量が増えます。通信量を抑えるため、パケットを送る回数はティックレートより低く設定することもあります。
ティックバジェット Tick budget
1ティックを終えなければならない時間の上限。超えると次のティックが遅れ、ティック間隔が延びます。
FPS Frames per second
1秒間に画面を何回描画するか。60FPSなら1フレームあたり16.7ms。
フレームタイム Frame time
1フレームの描画にかかった時間。平均FPSよりも、ときどき跳ねるフレームのほうが体感には重要です。
スナップショット Snapshot
サーバーがティックごとに送る「今のゲーム状態」の要約。位置、HP、状態などが入っています。たいていは、受信側がすでに持っている状態との差分だけを送ります(デルタ圧縮)。
補間 Interpolation
受信した2つのスナップショットの間をつないで描き、滑らかに見せる技術。その代わり、少し過去の状態を表示します。
補間バッファ Interpolation buffer
補間のためにわざと遅らせて描く時間。ジッターや1〜2個のパケットロスを吸収する余裕です。通常はパケット間隔の2倍(1秒に20回受信するなら100ms)で、ジッターが大きくなると自動で延ばすゲームもあります。
外挿 Extrapolation, Dead reckoning
新しいパケットが来ないとき、最後の速度からこの先どこにいるかを推測して描く技術。外れるとワープのように見えるため、多くのゲームは0.25秒前後までしか推測せずに止めます(Sourceエンジンのデフォルト値は0.25秒)。
クライアントサイド予測 Client-side prediction
サーバーの確認を待たずに、自分のキャラクターを先に動かして見せる技術。
サーバー補正 Reconciliation
サーバーの結果が届いたら予測と比べ、自分のキャラクターの位置を修正すること。サーバーが確認した位置から、まだ確認されていない自分の入力を適用し直して計算します。差が大きいと引き戻しのように見えます。
ラグコンペンセーション Lag compensation
サーバーが攻撃の当たり判定をするとき、攻撃者が見ていた過去の時点まで巻き戻して当たったかどうかを確かめる技術。撃たれた側が理不尽に感じないよう、巻き戻す幅に上限を設けます。競技性の高いシューターでは0.2〜0.25秒前後が一般的で、Sourceエンジンのデフォルト値のように1秒まで巻き戻す例もあります。
サーバー権威型 Authoritative server
最終的な判定はサーバーだけが行うという設計。チートを防げますが、すべての結果がサーバーとの往復を経ます。そのため予測・先行演出で待ち時間を隠します。
ロックステップ Deterministic lockstep
全員が入力だけをやり取りし、同じターンで同じ計算をする方式。入力に一定の遅延を付け、誰か一人の入力が遅れると全員が待ちます。
サーバー側入力バッファ Server-side input buffer
サーバーがプレイヤーごとに入力を少しためておき、1ティックに1つずつ取り出して使うバッファ。ジッターが大きい人もほかの人からは滑らかに見えますが、その人の行動がサーバーで確定するタイミングはその分遅れます。
リッスンサーバー Listen server
プレイヤー1人のPCが、ゲームをしながらサーバーの役割も兼ねる方式。ホストはPingが0ですが、ホストの回線やPCが遅いと全員がラグの影響を受けます。
フェーズ Phasing
同じ場所でも、クエストの進行度によって見えるNPCや地形を変える機能。2人のキャラクターの進行度が違えば、片方にだけNPCがいないのは正常です。
ロールバックネットコード Rollback netcode (GGPO)
相手の入力を予測して先に進め、実際の入力が違っていたら過去のフレームまで巻き戻して計算し直す方式。格闘ゲームでよく使われます。DBのロールバックとは別の意味です。
先行入力 Input buffer, spell queue
クールタイムや動作が終わる少し前に押された次の入力を受け付けておき、終わった瞬間に実行すること。連続技の合間に往復時間が挟まらないようにします。
先行演出 Client-side feedback
サーバーの確認を待たずに、アニメーション・サウンド・エフェクトを先に再生すること。ダメージ・報酬のように確定が必要な結果だけ、サーバーの応答を待ちます。サーバーが拒否したら、見せたものを元に戻す必要があります。
TCP Transmission Control Protocol
順番どおりに、漏れなく届けるプロトコル。失われたパケットを受け取り直すまで、後続のパケットをゲームに渡しません。
UDP User Datagram Protocol
何の保証もなく、送ったとおりに届けるプロトコル。待ちがない代わりに、パケットロスや順序はゲームが自分で処理します。
信頼性UDP Reliable UDP (KCP, ENet…)
UDPの上に、必要な分だけ再送・順序保証を自前で実装した方式。
HOLブロッキング Head-of-line blocking
先頭の1つが詰まると、後ろのすべてが待たされる現象。TCPで早送りが起きる原因です。
RTO Retransmission timeout
再送タイマー。TCPがパケットを失ったと判断して送り直すまでに待つ時間。LinuxではPing + 200ms以上で、失敗するたびに2倍になります。
Nagleアルゴリズム Nagle’s algorithm
先に送ったデータの確認(ACK)が返るまで小さなデータをためておき、まとめて送ることでパケット数を減らすTCPの機能。ゲームではたいていオフにすべきです。
TCP_NODELAY TCP_NODELAY
Nagleアルゴリズムを無効にするソケットオプション。小さなメッセージをすぐに送ります。
遅延ACK Delayed ACK
受け取ったという確認を少し遅らせて、ほかのデータとまとめて送る機能。Linuxは通常40ms(最大200ms)、Windowsは古いバージョンが200msで、最近のバージョンは40ms。
ソケットバッファ SO_SNDBUF / SO_RCVBUF
OSがソケットごとに持つ、送信・受信の待機領域のサイズ。小さすぎるとあふれ、大きすぎると古いデータがたまって待たされます。
keepalive SO_KEEPALIVE
アイドル接続が生きているかを確認するTCPの機能。デフォルトでは無効で、有効にしてもデフォルト設定では2時間後にようやく確認します。
RST TCP reset
接続をその場で強制的に切るTCPの信号。まだ送れていないデータは破棄されます。
ハートビート Heartbeat
ゲームが自ら定期的に送る「生きている」という信号。切れた接続の検知や、途中の機器で接続を維持するのに使います。
タイムアウト Timeout
この時間応答がなければ失敗とみなす基準。短すぎると誤判定、長すぎると検知が遅れます。
NAT Network Address Translation
ルーターが家庭内の複数の機器を1つのグローバルIPで外に出し、その接続をNATテーブルに記録する機能。
CGNAT Carrier-grade NAT
通信事業者が、複数の契約者に1つのIPアドレスを共有させる大規模なNAT。
MTU Maximum Transmission Unit
一度に送れるパケットの最大サイズ。通常は1,500バイトで、VPN・PPPoEの区間ではさらに小さくなります。
バッファブロート Bufferbloat
機器がキューを大きくため込みすぎて、遅延が数百msまで膨らむ現象。
SQM Smart Queue Management (fq_codel, CAKE)
キューを短く保ち、フローごとに公平に送り出すルーターの機能。バッファブロートの解決策です。
QoS Quality of Service
重要なトラフィックを優先して送るよう、優先度を付ける機能。
ピアリング Peering
通信事業者どうしが互いのネットワークを接続する地点。夜に混雑しやすくなります。
BGP Border Gateway Protocol
インターネットでどの経路を使って送るかを、通信事業者どうしで伝え合うためのプロトコル。変わると経路とPingが変わります。
DDoS Distributed Denial of Service
多数の場所から大量のトラフィックを送りつけ、サービスを停止させる攻撃。
スクラビングセンター DDoS scrubbing center
DDoS攻撃の際、サーバー宛てのトラフィックをいったん引き受けて攻撃を取り除き、正常なトラフィックだけを渡すDDoS対策事業者の拠点。拠点が遠いと経路が長くなります。
ファイアウォール Firewall
許可された接続だけを通す機器やソフトウェア。接続をセッションテーブルで追跡します。
ロードバランサー Load balancer
入ってくる接続を、複数のサーバーに振り分ける機器。
セッションテーブル Session table, conntrack
機器やOSが、現在の接続を追跡するテーブル。サイズに上限があります。
マイクロバースト Microburst
平均は低くても、1ms以下のごく短い瞬間にトラフィックが集中する現象。
NIC Network Interface Card
サーバーのネットワークカード。
リングバッファ Ring buffer
NICが受信したパケットを、CPUが取り出すまで入れておくバッファ。決まった数のスロットを使い回し、スロットがすべて埋まると新しいパケットは破棄されます。
割り込み Interrupt
デバイスがCPUに「処理すべきことが発生した」と知らせる信号。
RSS Receive Side Scaling
受信したパケットを複数の受信キューに分け、複数のCPUコアで処理させるNICの機能。
PPS Packets per second
1秒あたりのパケット数。ゲームサーバーは、帯域幅よりもこの数値で先に限界に達しがちです。
カーネル Kernel
OSの中核。ネットワーク、メモリ、CPUの割り当てを担います。
backlog Listen backlog
サーバーがまだ受け取っていない新規接続の要求が待つキュー。キューが満杯になると、Linuxは新しい要求を黙って破棄し、Windowsは拒否の応答を返します。
TIME_WAIT TIME_WAIT
先に接続を閉じた側が、遅れて届くパケットに備えて、そのポートの組み合わせをしばらく(Linuxでは60秒)保持する状態。
CPUスチール Steal time
仮想マシンがCPUを使おうとしたのに、物理サーバーがほかの仮想マシンにCPUを割り当てていたために待たされた時間。topのst値で確認します。
CPUスロットリング CFS throttling
コンテナが決められた周期(CFS period、通常100ms)の中でCPUのクォータ(quota)を使い切ると、次の周期まで強制的に止められること。
ファイルディスクリプタ File descriptor
プロセスが開いたファイル・接続ごとに付く番号(fd)。数に上限があります。
スレッド Thread
プログラムの中で独立して実行される処理の単位。複数のスレッドが同時に実行されることもあります。
コンテキストスイッチ Context switch
CPUが実行中のスレッドを別のスレッドに切り替えること。コストがかかります。
ロック Lock, Mutex
共有データを一度に1つのスレッドだけが使えるようにする排他制御。
デッドロック Deadlock
スレッドどうしが互いに相手の持つロックを待ち、永遠に止まってしまった状態。
スレッドプール Thread pool
あらかじめ作っておいたワーカースレッドの集まり。すべて使用中だと、新しい処理は待たされます。
非同期I/O epoll, IOCP, io_uring
入出力の完了を待たずにほかの処理を進め、完了したら通知を受け取る方式。
AOI Area of Interest
各プレイヤーが「見える範囲」。この範囲内の変化だけを送って通信量を減らします。誰が範囲内にいるかを調べるコストを下げるため、通常はマップをグリッドに分けて近くのセルだけを調べます。
ブロードキャスト Broadcast, fan-out
1つの変化を、それが見える複数のプレイヤーに送ること。集まった全員が互いを見ている場合、送る量は人数の2乗で増えます。
GC Garbage collection
使い終わったメモリを自動で回収する機能。GCの間、プログラムが止まることもあります。
ヒープ Heap
プログラムが実行中に、必要に応じて確保して使うメモリ領域。
メモリリーク Memory leak
使い終わったメモリを解放しないため、使用量が増え続けるバグ。GCがあっても、使い終わったオブジェクトをどこかで参照し続けていると起きます。
スワップ Swap, paging
RAMが足りず、メモリの一部をディスクに退避すること。退避したメモリを再び使うときは、RAMより1,000倍以上遅くなります。
OOM Killer Out-of-memory killer
メモリが枯渇すると、Linuxがメモリを最も多く使っているプロセスを選んで強制終了する機能。コンテナでは、メモリ上限に達しただけでも発動します。
キャッシュミス Cache miss
CPUに近いキャッシュにデータがなく、遅いメモリまで取りに行かなければならないこと。
IOPS I/O operations per second
ディスクが1秒間に処理できる読み書きの回数。クラウドのディスクは、支払った料金に応じて上限が決まります。
fsync fsync
データがディスクに確実に書き込まれるまで待つ命令。通常の書き込みはまずOSのメモリに入り、あとからディスクに書き出されるため、その間にサーバーの電源が落ちると失われることがあります。fsyncは安全ですが遅くなります。
バーストクレジット Burst credits
クラウドのディスク・サーバーが一時的にベースライン以上の性能を出せるように、ためておくクレジット残高。使い切るとベースライン性能に落ちます。
インデックス Index
DBの索引。ないとテーブル全体を読む必要があります。
フルスキャン Full table scan
インデックスを使わずに、テーブルの全行を調べる検索。
実行計画 Query plan
DBがクエリをどの順序で、どのインデックスを使って処理するかを決めた方法。コードが同じでも、DBが実行計画を変えると同じクエリが急に遅くなることがあります。
トランザクション Transaction
「すべて成功するか、すべて失敗するか」を1つにまとめたDBの処理。取引は必ずトランザクションで処理します。終わるまで更新した行をロックしておくため、短いほど良いです。
コネクションプール Connection pool
あらかじめ確立しておいたDB接続の集まり。すべて使用中だと、新しいリクエストは待たされます。
ホットスポット Hot row
多くのリクエストが同時に更新しようとする1つの行。ロック競合の原因。
レプリケーション遅延 Replication lag
レプリカのDBがプライマリのDBに追いつけず、遅れている時間。
ロールバック Rollback
保存が取り消されて、以前の状態に戻ること。プレイヤーは「アイテムが消えた」と感じます。
キャッシュ Cache (Redis etc.)
よく使うデータを、高速な場所にコピーしておくもの。DBの負荷を減らします。
チェックポイント Checkpoint
DBがメモリにためた変更分を、定期的にまとめてディスクに書き込む処理。その瞬間、保存・参照が一時的に遅くなることがあります。
フェイルオーバー Failover
プライマリのサーバーやDBが落ちたとき、スタンバイ側に切り替えること。切り替え中はしばらく保存できず、レプリケーションが遅れていれば直近のデータが失われることがあります。
MVCC Multi-version concurrency control
読む側と更新する側が互いをブロックしないよう、DBが古いバージョンを一時的に保持する方式。長時間開いたままのトランザクションがあると、古いバージョンがたまって遅くなります。
キャッシュスタンピード Cache stampede
キャッシュが一斉に切れて、リクエストがオリジン(DB)に殺到する現象。
ゲートウェイ Gateway
クライアントの接続を受けて、後ろのゲームサーバーに中継する中間サーバー。
サーキットブレーカー Circuit breaker
失敗が続くサービス呼び出しを一時的に遮断し、すぐに失敗として扱うことでカスケード障害を防ぐ仕組み。しばらくしてから1〜2回試しに呼び出し、復旧していれば呼び出しを再び許可します。
カスケード障害 Cascading failure
1か所の障害が、呼び出しチェーンをたどってほかのサービスに広がること。
オートスケーリング Autoscaling
負荷に応じてサーバー台数を自動で増減する機能。増えるまでに時間がかかります。
ウォッチドッグ Watchdog
サーバーが止まっていないかを監視するタイマー。ゲームループが決められた時間(数秒〜数十秒)以上止まると、状態の記録(ダンプ)を残してサーバーを強制終了し、再起動させます。
利用率 Utilization
ワーカー(CPUコア・スレッド・DBコネクションのように、リクエストを処理する主体)がビジーな時間の割合。80〜90%を超えると待ちが急激に増えます。
p99 99th percentile
100回のうち99回はこれより速く、1回はこれより遅い値。平均よりも体感のラグをよく表します。
V-Sync Vertical sync
画面のリフレッシュ周期に合わせてフレームを出力する機能。ティアリング(画面のずれ)はなくなりますが入力遅延が生じ、FPSがリフレッシュレートを下回ると60と30の間を行き来してカクつくこともあります。
可変リフレッシュレート VRR, G-Sync, FreeSync
フレームの準備ができたタイミングに合わせて、モニターが画面を更新する機能。V-Syncで60と30を行き来して起きるカクつきと入力遅延を減らします。
アンチチート Anti-cheat
ゲームのチート(不正改造)を防ぐセキュリティモジュール。定期的な検査やサーバーとのハートビートが失敗すると、カクつきや切断を引き起こすこともあります。
オーバーレイ Overlay
チャット・録画・FPS表示などのソフトが、ゲーム画面の上に描き重ねる機能。ゲームの描画処理に割り込むため、カクつきの原因になることがあります。
シェーダーコンパイル Shader compilation
グラフィック効果のプログラムをGPU用に変換する処理。事前に済ませておかないと初めて表示するときに画面が一瞬止まり、グラフィックドライバーを更新すると保存済みの結果が無効になってやり直します。
メインスレッド Main thread, Game thread
ゲームロジックの計算と描画の準備を順番に処理する、ゲームの中心となるスレッド。ここで時間のかかる処理が1つでもあると、その間画面が止まります。
タイマー分解能 Timer resolution
OSが、スリープ中のプログラムを起こせる最短の間隔。Windowsのデフォルト値は15.6msなので、プログラムが個別に変更しなければ「1ms後に起こして」と頼んでも遅れて起きます。
サーマルスロットリング Thermal throttling
端末が熱くなると、自らCPU・GPUのクロックを下げる保護機能。スマホでは数分〜数十分ゲームをすると頻繁に起きます。
VRAM Video memory
グラフィックカードに搭載された専用メモリ。テクスチャやモデルをここに載せて描画します。足りなくなると、PCのメモリと遅い経路でやり取りするためカクつきます。
ネットグラフ Net graph
ゲーム画面にPing・パケットロス・FPS・ティックをリアルタイムのグラフで表示する、開発・デバッグ用の表示。ラグ報告の動画に一緒に映っていると、原因の特定がずっと楽になります。
再送率 Retransmission rate
送信したTCPパケットのうち、再送した割合。公的な基準はありませんが、サーバー全体の平均が0.1%未満なら健全な部類で、1%を超えると多くのユーザーがラグを感じやすくなります。普段の値の何倍に増えたかもあわせて見ます。
SACK Selective ACK
受信側が「この範囲は受け取り、この部分だけ抜けている」と詳しく伝えるTCPの機能。複数のパケットを失っても、一度に回復できます。
RACK-TLP Recent ACK, Tail Loss Probe
時間を基準にロスを判断し、しばらくACKが来なければ末尾のパケットをもう一度送って回復を早めるTCPの機能。最新のLinux・Androidのデフォルトです。WindowsはWindows 10(1607)・Server 2016からTLPとRACKがデフォルトで、失った再送パケットまで回復する新しいRACKはServer 2022からです。SACKが有効な接続でのみ動作します。
不要な再送 Spurious retransmission
失われていないのに、遅れて届いたり順序が入れ替わったりしたためにロスと誤認して送り直したもの。回線を無駄にし、送信量を不必要に絞ってしまいます。
ゼロウィンドウ Zero window
受信側のバッファが満杯になり、「しばらく送らないで」と通知した状態。再送のように見えますが回線は正常で、受信側のプログラムが時間内に読み出せていないことが原因です。
thin stream Thin stream
ゲームのように、小さなパケットをまばらに送る接続。高速再送のきっかけとなる信号が集まりにくく、ロスのときに長く止まります。
ポリサー Policer
決められた速度を超えたパケットを、キューに入れずにすぐ破棄する帯域制限の方式。キューに入れてからゆっくり送り出す方式はシェーパーと呼びます。
ペーシング Pacing
送るパケットを一度に吐き出さず、時間的に均等に分けて送ること。小さなバッファがあふれるのを防ぎます。
ECN Explicit Congestion Notification
輻輳時にパケットを破棄せず「輻輳あり」の印を付け、送信側に速度を落とさせる機能。ロスなしで輻輳を伝えます。両端と、混雑している区間の機器がすべて対応していないと効果がありません。
MSS Maximum Segment Size
TCPが1つのパケットに入れるデータの最大サイズ。通常は1,460バイトで、トンネル区間に合わせて小さくするとMTUブラックホールを防げます。
ハンドオーバー Handover
移動中のスマホが、接続先の基地局を切り替えること。
パーセンタイル Percentile (p50, p95, p99)
値を小さい順に並べたとき、何%目に来る値か。p50は中央値、p99は100回のうち最も遅い1回付近の値です。平均では隠れてしまうスパイクがわかります。
テールレイテンシ Tail latency
大半は速いのに、ときどき発生する長い遅延。平均にはほとんど表れませんが、ユーザーがラグとして記憶するのはこの部分です。
外形監視 Synthetic monitoring
実際のユーザーの代わりに、計測用の端末・サーバーが決まった場所から定期的にping・tracerouteなどを送り、経路の品質を測ること。RIPE Atlasが代表的な公開ツールです。
集計間隔 Aggregation interval
グラフの1点が、何秒・何分の値をまとめたものか。間隔が長いほど、短いスパイクが平均に埋もれて見えにくくなります。
ポストモーテム Postmortem
障害が収まった後に、何が起き、なぜ起き、何を変えるかをまとめた文書。責任追及より再発防止を目的に書きます。
C-state CPU idle state
CPUが休んでいるときに入る省電力状態。深い状態ほど電力を節約できますが、復帰に時間がかかります。
ライブマイグレーション Live migration
クラウドがホストのメンテナンスなどのために、実行中の仮想マシンを別のホストに移すこと。移す瞬間に一時的に止まることがあります。
SNAT Source NAT
送信パケットの送信元アドレスを、グローバルアドレスに書き換えるNAT。1つのグローバルアドレスで使えるポート数には上限があり、使い切ると新しい接続が失敗します。
NATゲートウェイ NAT gateway
プライベートネットワーク内のサーバーがインターネットに出るとき、1つのグローバルアドレスを共有させるクラウドの仕組み。宛先ごとの同時接続数に上限があります。
低軌道衛星インターネット LEO satellite internet
高度数百〜数千kmの衛星群で接続するインターネット。静止軌道衛星より遅延はずっと短いものの、接続する衛星が切り替わるときに遅延が跳ねることがあります。
GeoIP IP geolocation
IPアドレスから国・都市・通信事業者を推定するデータベース。誤った項目や古い項目があり、遠い地域のサーバーに割り当てられる原因になることもあります。
TLS証明書 TLS certificate
サーバーが本物であることを証明する電子文書。有効期限があり、期限が切れると暗号化通信の確立に失敗して接続できなくなります。
フレーム生成 Frame generation
グラフィックカードが実際に描いたフレームの間に予測したフレームを挟み込み、FPSを上げる技術。画面は滑らかになりますが、入力から画面表示までの遅延は増えることがあります。
T6ツール

参考文献

白書の数値・デフォルト値・動作説明の根拠です。標準文書(RFC)、カーネル・OSのドキュメント、クラウド・エンジン・DBの公式ドキュメント、講演・論文など、信頼できる資料だけを集めました。原因カードや各章末の「出典」からも同じ資料にたどれます。バージョンが変わるとデフォルト値も変わることがあるので、実際に適用する前に、使っているバージョンのドキュメントを確認してください。

資料616件、発行元83組織。一覧はテキスト版の参考文献にあります。