한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

ゲームラグ白書 › L7 サーバーOS(カーネル)

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

原因ID so-sockbuf · 主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発

図と実験のあるメインページでこのカードを開く →

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

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

症状
ワープ, 早送り
要因
パケットロス, ストール
誰に起きるか
サーバー全体
いつ
人が集中したとき
担当
主担当 インフラチーム・サーバーインフラ · 副担当 ゲーム開発チーム・サーバー開発
ゲーム開発チームの対応
トラフィックに見合ったバッファサイズ(SO_SNDBUF・SO_RCVBUF)をコードで設定、TCPはサイズを明示するとLinuxの自動サイズ調整が無効になるので注意、大きくしすぎると古いデータがバッファにたまって遅延が増えるので適度に、受信スレッドが止まらないようにする。
インフラチームの対応
カーネルの上限(rmem_max・wmem_max。コードで設定したバッファサイズもこの値を超えられない)とデフォルト値(rmem_default)の調整、バッファあふれのカウンター(RcvbufErrors)の監視。
数値の目安
LinuxのUDP受信バッファのデフォルト値は約208KBです。小さなパケットでも1個でカーネルメモリを実際のサイズよりはるかに多く消費するため、数十〜数百個で満杯になります。毎秒10万個を受信するサーバーなら、受信スレッドが数ms止まるだけであふれます。
グラフでは
不定期なスパイク · UDP受信バッファのあふれ(UdpRcvbufErrors)
確認箇所
nstat -azでUdpRcvbufErrorsの増加量を、ss -uamnでskmem(rbは受信バッファサイズ、dはソケットに入れられず破棄したパケット数)を確認し、TCPはss -tmのskmemで送信待ちメモリ(w)が送信バッファサイズ(tb)に達しているかを確認
該当する場合
バーストや受信スレッドが止まった時刻にUdpRcvbufErrors(またはソケットのd)が増え、rbがデフォルト値(約208KB)付近。TCPはwがtbに張り付いたままsendがブロック
該当しない場合
カウンターが増えていないのにパケットロスがあれば、NICの段階(「リングバッファ不足」)かネットワーク区間
確認手段
インフラのツールで確認(ゲームコード不要)

出典

  1. socket(7) — Linux manual page Linux man-pages
    SO_RCVBUF・SO_SNDBUFのデフォルト値はrmem_default・wmem_default、上限はrmem_max・wmem_max、設定値はカーネルが2倍にして確保
  2. include/net/sock.h (Linux v6.18) Linux kernel
    デフォルトのソケットバッファを、sk_buffのオーバーヘッドを含む256バイトのパケット256個分(SKB_TRUESIZE(256)×256)と定義、小さなフレームもsk_buff+MTU分として計算される(約208KBはx86-64での計算値)
  3. IP Sysctl Linux kernel
    tcp_rmem・tcp_wmem:SO_RCVBUF・SO_SNDBUFを明示すると、そのソケットの自動サイズ調整が無効になる
  4. net/ipv4/udp.c (Linux v6.12) Linux kernel
    UDPの受信キューがソケットバッファサイズを超えると即座に破棄し、RcvbufErrorsを加算
  5. net/ipv4/proc.c (Linux v6.12) Linux kernel
    nstatが表示するカウンター名:UdpグループのRcvbufErrors・SndbufErrors
  6. ss(8) — Linux manual page iproute2
    -mのskmem:rbは受信バッファサイズ、tbは送信バッファサイズ、wは送信待ちメモリ、dはソケットに入れる前に破棄したパケット数

あわせて読みたい原因

同じ層:L7 サーバーOS(カーネル)

同じ症状(ワープ)を起こすほかの層の原因

図と実験のあるメインページでこのカードを見る