ゲームラグ白書 › L8 ソケットとプロトコル
遅いクライアントによるブロッキング送信 Blocking send on a full socket
原因ID sk-block-send · 主担当 ゲーム開発チーム・サーバー開発
図と実験のあるメインページでこのカードを開く →
回線の遅い1人の送信バッファが満杯なのに、ブロッキング方式(バッファに空きができるまで呼び出しが戻らない送信)で送ると、サーバーのスレッドがその1人を待ちます。
なぜ 遅いクライアントの送信バッファが満杯 → すると ブロッキング送信のため、サーバーのスレッドがバッファに空きができるまで待機 → 画面では そのスレッドが担当する全員がフリーズ・スローモーション
- 症状
- フリーズ, スローモーション
- 要因
- ストール
- 誰に起きるか
- 特定の場所・チャンネル, サーバー全体
- いつ
- ときどきランダムに, 人が集中したとき
- 担当
- 主担当 ゲーム開発チーム・サーバー開発
- ゲーム開発チームの対応
- ノンブロッキング送信、クライアントごとの送信キューの上限、古い更新の破棄。
- グラフでは
- 不定期なスパイク · サーバーのティック時間、接続ごとのSend-Q
- 確認箇所
- ss -tnで、接続ごとのSend-Q(ACKを受け取っていないか、まだ送れていないバイト)が送信バッファいっぱいまでたまった接続を探し、ティックが跳ねた瞬間のゲームサーバーのスレッドダンプ(スタック)で、send呼び出しで止まっているスレッドがあるかを確認
- 該当する場合
- Send-Qが満杯の遅い接続があるとき、その接続を担当するスレッドがsendで止まっており、同じスレッドが担当する人たちだけが一緒に止まる
- 該当しない場合
- 止まったスレッドがsend以外(ロック、DB呼び出し)で待っていれば「ロック競合」「ゲームスレッドの同期呼び出し」
- 確認手段
- インフラのツールで確認(ゲームコード不要)
出典
- send(2) — Linux manual page Linux man-pages
送信バッファに空きがなければsend()がブロックし、ノンブロッキングモードならEAGAINですぐに戻る - send function (winsock2.h) Microsoft
Winsockも、バッファに空きがなければノンブロッキングモードでない限りsendがブロック - net/ipv4/tcp_diag.c (Linux v6.12) Linux kernel
ssのRecv-Q・Send-Qの値:リッスンソケットではacceptを待っている接続数とbacklogの上限、接続済みソケットではアプリがまだ読んでいないバイト数とACKを受け取っていない送信バイト数
あわせて読みたい原因
同じ層:L8 ソケットとプロトコル
同じ症状(フリーズ)を起こすほかの層の原因
図と実験のあるメインページでこのカードを見る