🌐
概念 #システムパフォーマンス #Brendan Gregg #Linux #SRE #読書ノート #ネットワーク #TCP 📚 詳解 システム・パフォーマンス

詳解 システム・パフォーマンス - 第10章:ネットワーク分析

TCP/IP・NICレート・TCPリトランスミッション・接続状態分析。ss/sar/tcpretrans/tcplifeの実践的な使い方とネットワークUSE法。

ネットワークのUSE法

リソースUtilizationSaturationErrors
NICsar -n DEV の %ifutilip -s link の drop 数ip -s link の errors
TCP接続数 / 最大接続数sar -n TCP の retranssar -n ETCP のエラー
ソケットバッファ受信/送信バッファ使用率ss -m の buffer overflownetstat -s

基本確認コマンド

NIC の統計

# NIC の送受信レート(1秒間隔)
sar -n DEV 1 5
# IFACE  rxpck/s  txpck/s  rxkB/s  txkB/s  rxcmp/s  txcmp/s  rxmcst/s
# eth0   10000.0   5000.0   125.0    62.5      0.0      0.0       0.0

# ポイント:
# rxkB/s + txkB/s が NIC の帯域(1Gbps = 125MB/s)に近い → NIC 飽和
# 10Gbps NIC = 1250 MB/s が理論最大

# NIC の詳細統計(エラー・ドロップ)
ip -s link show eth0
# RX: bytes  packets  errors  dropped  overrun  mcast
#       100G    10M       0        0        0     0

# NIC の設定確認
ethtool eth0
# Speed: 10000Mb/s
# Duplex: Full
# Link detected: yes

TCP 統計

# TCP の状態統計
sar -n TCP,ETCP 1 5
# active/s: 新規接続の開始数(client 側)
# passive/s: 新規接続の受け入れ数(server 側)
# retrans/s: TCP リトランスミッション数 ← 0 に近いほど良い

# retrans/s > 1 → パケットロスが発生している(ネットワーク品質問題)

# TCP の状態集計(ss を使う)
ss -s
# Total: 500
# TCP:   350 (estab 200, closed 50, orphaned 10, timewait 100)

# 接続数の詳細
ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn
# 200 ESTABLISHED
# 100 TIME-WAIT
#  50 CLOSE-WAIT  ← アプリが接続を閉じていない可能性

ss コマンドの完全ガイド

netstat の後継。ss を使う。

# リッスンポート一覧(プロセス名付き)
ss -tlnp
# -t: TCP / -l: LISTEN / -n: 名前解決なし / -p: プロセス名

# 確立済み接続(プロセス名付き)
ss -tnp
# ESTAB   0   0   192.168.1.1:8080   10.0.0.5:54321   users:(("java",pid=1234,fd=10))

# 特定ポートの接続
ss -tnp | grep :5432   # PostgreSQL への接続

# ソケットバッファ情報
ss -tnm
# Recv-Q: 受信バッファに溜まっているデータ(0以外 → アプリの読み出しが追いつかない)
# Send-Q: 送信バッファに溜まっているデータ(0以外 → ネットワークが遅い or 受信側が遅い)

# TIME-WAIT 状態の接続数(多すぎると問題になることがある)
ss -tan state time-wait | wc -l

# CLOSE-WAIT が多い(アプリのバグの可能性)
ss -tan state close-wait | head -10

TCP 接続状態の読み方

SYN_SENT → (3-way handshake) → ESTABLISHED → FIN_WAIT → TIME_WAIT → CLOSED
状態意味問題の兆候
ESTABLISHED接続中(正常)多すぎる = 接続プールが溢れている
TIME_WAIT接続終了後の待機(正常)非常に多い = 短命接続が多い(keep-alive 推奨)
CLOSE_WAITアプリが接続を閉じていない増加 = アプリのバグ(close() を呼んでいない)
SYN_RECV接続受け付け中大量 = SYN Flood 攻撃の可能性
FIN_WAIT2相手の FIN 待ち増加 = ネットワーク問題

BCC tools でネットワークをトレース

# TCP 接続の開始をリアルタイムで追跡
sudo tcpconnect
# PID  COMM   IP SADDR            DADDR            DPORT
# 1234 java    4 192.168.1.1      10.0.0.5          5432  ← DB への接続

# TCP 接続の受け入れを追跡
sudo tcpaccept

# TCP リトランスミッションを検出(パケットロスの証拠)
sudo tcpretrans
# TIME  PID  IP  LADDR:LPORT      RADDR:RPORT      STATE     TYPE
# 12:00 1234  4  192.168.1.1:8080 10.0.0.5:54321   ESTAB     R   ← 再送信

# TCP セッションの詳細ログ(接続時間・データ量)
sudo tcplife
# PID  COMM   LADDR      LPORT RADDR      RPORT  TX_KB  RX_KB  MS
# 1234 nginx  0.0.0.0    80    10.0.0.5   54321    0.5   10.2  25.3

# TCP レイテンシ(RTT)の分布
sudo tcpsynbl  # SYN バックログの状態

# bpftrace で TCP 接続の接続先を集計
sudo bpftrace -e '
  tracepoint:syscalls:sys_enter_connect {
    @connections[pid, comm] = count();
  }
' -c "sleep 30"

ネットワークレイテンシの分析

# RTT の測定
ping -c 100 target_host
# 平均と最大の差が大きい → ジッターが多い(ネットワーク不安定)

# DNS 解決時間の確認
time dig +short example.com
# DNS が遅い場合、アプリのレイテンシ増加の原因になる

# HTTP レイテンシの詳細(curl の -w オプション)
curl -w "
DNS:         %{time_namelookup}s
Connect:     %{time_connect}s
TLS:         %{time_appconnect}s
TTFB:        %{time_starttransfer}s
Total:       %{time_total}s
" -o /dev/null -s http://example.com/api/health

# tcpdump でパケットキャプチャ(詳細デバッグ)
sudo tcpdump -i eth0 -w capture.pcap host 10.0.0.5 and port 8080
# wireshark で分析: tcpretransmissions, TCP window size 等

ネットワークチューニング

TCP バッファサイズ

# 現在の設定
sysctl net.core.rmem_max        # 最大受信バッファ
sysctl net.core.wmem_max        # 最大送信バッファ
sysctl net.ipv4.tcp_rmem        # TCP 受信バッファ(min/default/max)
sysctl net.ipv4.tcp_wmem        # TCP 送信バッファ

# 高スループットが必要な場合の設定例
sysctl -w net.core.rmem_max=134217728
sysctl -w net.core.wmem_max=134217728
sysctl -w net.ipv4.tcp_rmem="4096 87380 134217728"
sysctl -w net.ipv4.tcp_wmem="4096 65536 134217728"

TIME_WAIT と接続数

# TIME_WAIT の再利用(短命接続が多い場合)
sysctl -w net.ipv4.tcp_tw_reuse=1

# バックログキュー(同時接続受け付け数)
sysctl -w net.core.somaxconn=65535
sysctl -w net.ipv4.tcp_max_syn_backlog=65535

# 確認
ss -s | grep TCP

ネットワーク問題のチェックリスト

□ sar -n DEV 1 で NIC の帯域使用率を確認(1Gbps = 125MB/s 上限)
□ sar -n TCP,ETCP で retrans/s を確認(> 1 でパケットロス疑い)
□ ss -s で TCP 状態の内訳を確認
□ CLOSE_WAIT が多い場合:アプリのコネクション close 漏れを調査
□ TIME_WAIT が非常に多い場合:keep-alive の設定を確認
□ tcpretrans でリトランスミッションが発生しているか確認
□ ping で RTT とジッターを測定
□ DNS 解決が遅くないか確認(dig / time dig)
□ ソケットバッファ(Recv-Q/Send-Q)が溜まっていないか(ss -tnm)

出典: 詳解 システム・パフォーマンス 第2版 Brendan Gregg著