- Authors
- Name
- 概要
- 1. コアネットワークパフォーマンス指標
- 2. ネットワーク診断ツール
- 3. 帯域幅テストとボトルネックの特定
- 4. ネットワークインターフェース統計とエラーカウンタ
- 5. TCPウィンドウ分析と輻輳制御
- 6. MTUとフラグメンテーション問題
- 7. Prometheus/Grafanaによるネットワークモニタリング
- 8. 実務パフォーマンス診断シナリオ
- まとめ
概要
ネットワークパフォーマンスの問題は、アプリケーションの応答速度低下、ファイル転送の失敗、ストリーミング品質の劣化など、さまざまな形で現れます。問題を効果的に解決するには、コアとなるパフォーマンス指標を理解し、適切なツールを用いて体系的に診断することが不可欠です。
本記事では、ネットワークパフォーマンスの測定と分析に必要なすべての内容を取り上げます。基本指標の理解から、実務で頻繁に発生する問題シナリオの解決まで、幅広く解説します。
1. コアネットワークパフォーマンス指標
1.1 レイテンシ(遅延時間)
レイテンシは、パケットが送信元から宛先に到達するまでにかかる時間です。通常はRTT(Round Trip Time)として測定されます。
# 基本的なpingテスト
ping -c 20 target-server.example.com
# タイムスタンプ付きping
ping -c 100 -D target-server.example.com
# 出力例
# PING target-server.example.com (10.0.1.50): 56 data bytes
# 64 bytes from 10.0.1.50: icmp_seq=0 ttl=64 time=0.523 ms
# 64 bytes from 10.0.1.50: icmp_seq=1 ttl=64 time=0.481 ms
# ...
# round-trip min/avg/max/stddev = 0.481/0.512/0.623/0.042 ms
レイテンシは以下の要素で構成されています。
- 伝搬遅延(Propagation Delay):物理的距離に比例する光速の制限
- 伝送遅延(Transmission Delay):データをリンクに載せる時間(パケットサイズ / 帯域幅)
- 処理遅延(Processing Delay):ルータでパケットヘッダを処理する時間
- キューイング遅延(Queuing Delay):ルータバッファで待機する時間
# レイテンシ分布の詳細分析スクリプト
#!/bin/bash
TARGET="target-server.example.com"
COUNT=1000
echo "=== Latency Distribution Analysis ==="
ping -c $COUNT $TARGET | tail -1
# hping3を使用したTCPベースのレイテンシ測定(ICMPがブロックされている場合に有効)
sudo hping3 -S -p 443 -c 20 $TARGET
1.2 スループット
スループットは、単位時間あたりに実際に転送されるデータ量です。帯域幅(bandwidth)と混同されがちですが、帯域幅は理論上の最大容量であり、スループットは実際に達成可能な転送レートです。
# iperf3でTCPスループットを測定
# サーバ側
iperf3 -s -p 5201
# クライアント側 - 基本テスト
iperf3 -c server-ip -p 5201 -t 30
# 双方向同時テスト
iperf3 -c server-ip -p 5201 -t 30 --bidir
# 出力例
# [ ID] Interval Transfer Bitrate Retr
# [ 5] 0.00-30.00 sec 3.28 GBytes 939 Mbits/sec 12 sender
# [ 5] 0.00-30.00 sec 3.27 GBytes 937 Mbits/sec receiver
1.3 パケットロス
パケットロスは、送信されたパケットのうち宛先に到達しなかった割合です。1%以上のロスは、目に見えるパフォーマンス低下を引き起こします。
# パケットロスの測定
ping -c 1000 -i 0.01 target-server.example.com
# mtrでホップごとのパケットロスを確認
mtr -r -c 100 target-server.example.com
# 出力例
# HOST: myhost Loss% Snt Last Avg Best Wrst StDev
# 1.|-- gateway 0.0% 100 0.5 0.6 0.3 1.2 0.2
# 2.|-- isp-router 0.0% 100 3.2 3.5 2.8 5.1 0.5
# 3.|-- core-router 2.0% 100 8.1 12.3 7.5 45.2 8.1
# 4.|-- target-server 2.0% 100 10.2 14.1 9.8 48.3 9.2
1.4 ジッタ
ジッタは、パケット到着時間の変動幅です。VoIPやビデオ通話などのリアルタイム通信では特に重要です。
# iperf3 UDPモードでジッタを測定
# サーバ
iperf3 -s
# クライアント - UDPモード、100Mbpsターゲット
iperf3 -c server-ip -u -b 100M -t 30
# 出力例
# [ ID] Interval Transfer Bitrate Jitter Lost/Total
# [ 5] 0.00-30.00 sec 358 MBytes 100 Mbits/sec 0.042 ms 12/45892 (0.026%)
2. ネットワーク診断ツール
2.1 iperf3 - 帯域幅テスト
iperf3は、ネットワーク帯域幅の測定に最も広く使用されているツールです。
# マルチストリームテスト(並列接続でフル帯域幅を活用)
iperf3 -c server-ip -P 4 -t 30
# 帯域幅制限付きテスト
iperf3 -c server-ip -b 500M -t 30
# TCPウィンドウサイズ指定
iperf3 -c server-ip -w 256K -t 30
# JSON形式の出力(自動化に便利)
iperf3 -c server-ip -t 30 -J > iperf3_result.json
# 逆方向テスト(サーバからクライアント方向)
iperf3 -c server-ip -R -t 30
# MSS設定
iperf3 -c server-ip -M 1400 -t 30
# レポート間隔の設定
iperf3 -c server-ip -t 60 -i 5
2.2 mtr - 経路分析
mtrはtracerouteとpingを組み合わせたツールで、ネットワーク経路の各ホップでのパフォーマンスを継続的にモニタリングします。
# 基本レポートモード
mtr -r -c 200 target-server.example.com
# TCPモード(ICMPブロック環境)
mtr -r -c 100 -T -P 443 target-server.example.com
# UDPモード
mtr -r -c 100 -u target-server.example.com
# 詳細レポート(AS番号含む)
mtr -r -c 200 -w -z target-server.example.com
# CSV出力
mtr -r -c 100 --csv target-server.example.com > mtr_report.csv
mtrの結果を解釈する際の注意点は以下の通りです。
- 中間ホップでのみロスが見られ、最終宛先でロスがない場合、ICMPレートリミティングの可能性が高い
- 特定のホップからレイテンシが急増する場合、その区間がボトルネック
- 最後の数ホップでロスが増加する場合、実際の問題がある可能性が高い
2.3 traceroute
# ICMP traceroute
traceroute target-server.example.com
# TCP traceroute(ファイアウォール回避に有効)
sudo traceroute -T -p 443 target-server.example.com
# UDP traceroute(特定ポート)
traceroute -U -p 33434 target-server.example.com
# 最大ホップ数指定
traceroute -m 30 target-server.example.com
# Paris-traceroute(ロードバランサ環境での正確な経路追跡)
paris-traceroute target-server.example.com
2.4 netperf - 高度なパフォーマンステスト
# netperfサーバの起動
netserver -p 12865
# TCPストリームテスト
netperf -H server-ip -p 12865 -t TCP_STREAM -l 30
# TCP RR(Request/Response)テスト - トランザクション性能測定
netperf -H server-ip -p 12865 -t TCP_RR -l 30
# TCP CRR(Connect/Request/Response)- コネクション確立含む
netperf -H server-ip -p 12865 -t TCP_CRR -l 30
# メッセージサイズ指定
netperf -H server-ip -t TCP_STREAM -l 30 -- -m 65536
# UDPストリームテスト
netperf -H server-ip -t UDP_STREAM -l 30
3. 帯域幅テストとボトルネックの特定
3.1 体系的な帯域幅テスト
#!/bin/bash
# bandwidth_test.sh - 体系的な帯域幅テストスイート
SERVER="10.0.1.50"
PORT=5201
DURATION=30
LOGDIR="/var/log/bandwidth_tests"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
mkdir -p $LOGDIR
echo "=== Bandwidth Test Suite - $TIMESTAMP ==="
# 1. シングルストリームTCP
echo "[1/5] Single Stream TCP Test"
iperf3 -c $SERVER -p $PORT -t $DURATION -J > "$LOGDIR/tcp_single_${TIMESTAMP}.json"
# 2. マルチストリームTCP
echo "[2/5] Multi Stream TCP Test (4 streams)"
iperf3 -c $SERVER -p $PORT -t $DURATION -P 4 -J > "$LOGDIR/tcp_multi_${TIMESTAMP}.json"
# 3. リバースTCP
echo "[3/5] Reverse TCP Test"
iperf3 -c $SERVER -p $PORT -t $DURATION -R -J > "$LOGDIR/tcp_reverse_${TIMESTAMP}.json"
# 4. UDP帯域幅
echo "[4/5] UDP Bandwidth Test"
iperf3 -c $SERVER -p $PORT -t $DURATION -u -b 1G -J > "$LOGDIR/udp_${TIMESTAMP}.json"
# 5. 双方向同時
echo "[5/5] Bidirectional Test"
iperf3 -c $SERVER -p $PORT -t $DURATION --bidir -J > "$LOGDIR/bidir_${TIMESTAMP}.json"
echo "=== Tests Complete. Results in $LOGDIR ==="
3.2 ボトルネックの特定
# ステップ1: ローカルインターフェース速度の確認
ethtool eth0 | grep -i speed
# Speed: 10000Mb/s
# ステップ2: ループバック性能の確認(NIC/CPU限界の把握)
iperf3 -c 127.0.0.1 -t 10
# ステップ3: 同一スイッチ内のサーバ間テスト
iperf3 -c same-switch-server -t 30
# ステップ4: 異なるサブネットのサーバテスト(ルーティングの影響)
iperf3 -c different-subnet-server -t 30
# ステップ5: WAN区間テスト
iperf3 -c remote-server -t 30
# 各ステップでスループットが大幅に低下する区間がボトルネック
4. ネットワークインターフェース統計とエラーカウンタ
4.1 ethtool統計
# インターフェース基本情報
ethtool eth0
# 詳細統計
ethtool -S eth0
# 主要確認項目
ethtool -S eth0 | grep -E "(rx_errors|tx_errors|rx_dropped|tx_dropped|rx_crc|collisions)"
# ドライバ情報
ethtool -i eth0
# リングバッファサイズの確認
ethtool -g eth0
# リングバッファサイズの調整(ドロップ削減のため)
sudo ethtool -G eth0 rx 4096 tx 4096
# オフロード設定の確認
ethtool -k eth0
# TSO/GSO/GRO設定
sudo ethtool -K eth0 tso on gso on gro on
4.2 ipコマンドによるインターフェース統計
# インターフェース統計サマリ
ip -s link show eth0
# 出力例
# 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
# RX: bytes packets errors dropped overrun mcast
# 948271623 1523847 0 0 0 12847
# TX: bytes packets errors dropped carrier collsns
# 523841267 892341 0 0 0 0
# 詳細統計
ip -s -s link show eth0
# 全インターフェース統計
ip -s link show
# 統計変化量の追跡スクリプト
#!/bin/bash
IFACE="eth0"
while true; do
echo "=== $(date) ==="
ip -s link show $IFACE | grep -A 2 "RX\|TX"
sleep 5
done
4.3 エラーカウンタのモニタリング
# /proc/net/devからリアルタイム統計確認
cat /proc/net/dev
# netstat -iによるインターフェース統計
netstat -i
# エラーカウンタの継続モニタリングスクリプト
#!/bin/bash
IFACE="eth0"
INTERVAL=10
echo "Monitoring $IFACE errors every ${INTERVAL}s..."
echo "Time | RX_errors | TX_errors | RX_dropped | TX_dropped"
while true; do
STATS=$(ip -s link show $IFACE)
RX_ERR=$(echo "$STATS" | awk '/RX:/{getline; print $3}')
TX_ERR=$(echo "$STATS" | awk '/TX:/{getline; print $3}')
RX_DROP=$(echo "$STATS" | awk '/RX:/{getline; print $4}')
TX_DROP=$(echo "$STATS" | awk '/TX:/{getline; print $4}')
echo "$(date +%H:%M:%S) | $RX_ERR | $TX_ERR | $RX_DROP | $TX_DROP"
sleep $INTERVAL
done
5. TCPウィンドウ分析と輻輳制御
5.1 TCPウィンドウサイズ分析
# 現在のTCP接続のウィンドウサイズを確認
ss -ti dst target-server.example.com
# 出力例
# State Recv-Q Send-Q Local Address:Port Peer Address:Port
# ESTAB 0 0 10.0.1.10:42856 10.0.1.50:443
# cubic wscale:7,7 rto:204 rtt:1.523/0.742 ato:40 mss:1448
# pmtu:1500 rcvmss:1448 advmss:1448 cwnd:10 ssthresh:7
# bytes_sent:15234 bytes_acked:15235 bytes_received:45678
# send 76.1Mbps pacing_rate 152.1Mbps delivery_rate 45.2Mbps
# 主要フィールドの説明
# cwnd: 輻輳ウィンドウサイズ(セグメント数)
# ssthresh: スロースタート閾値
# rtt: ラウンドトリップ時間 / 標準偏差
# mss: 最大セグメントサイズ
5.2 TCP輻輳制御アルゴリズム
# 現在使用中の輻輳制御アルゴリズムを確認
sysctl net.ipv4.tcp_congestion_control
# net.ipv4.tcp_congestion_control = cubic
# 利用可能なアルゴリズム一覧
sysctl net.ipv4.tcp_available_congestion_control
# net.ipv4.tcp_available_congestion_control = reno cubic bbr
# BBRに変更
sudo sysctl -w net.ipv4.tcp_congestion_control=bbr
# BBR使用のためのfqスケジューラ設定
sudo tc qdisc replace dev eth0 root fq
# TCPバッファサイズチューニング
# 最小/デフォルト/最大(バイト)
sudo sysctl -w net.ipv4.tcp_rmem="4096 131072 16777216"
sudo sysctl -w net.ipv4.tcp_wmem="4096 65536 16777216"
# TCPウィンドウスケーリングの有効化
sudo sysctl -w net.ipv4.tcp_window_scaling=1
5.3 tcpdumpによるTCP分析
# TCPハンドシェイクのキャプチャ
sudo tcpdump -i eth0 -c 50 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0' -nn
# 特定ホストとのTCP通信をキャプチャ
sudo tcpdump -i eth0 host target-server.example.com -w capture.pcap
# 再送パケットの確認
sudo tcpdump -i eth0 'tcp[tcpflags] & tcp-syn != 0' -nn
# ゼロウィンドウパケットの検出
sudo tcpdump -i eth0 'tcp[14:2] = 0' -nn
# キャプチャファイルをtsharkで分析
tshark -r capture.pcap -q -z io,stat,1
tshark -r capture.pcap -q -z conv,tcp
6. MTUとフラグメンテーション問題
6.1 MTU確認とパスMTU探索
# インターフェースMTUの確認
ip link show eth0 | grep mtu
# パスMTU探索(Path MTU Discovery)
# DFビットを設定してフラグメンテーションなしで送信を試みる
ping -c 5 -M do -s 1472 target-server.example.com
# PING target-server.example.com: 1472 data bytes
# 1480 bytes from 10.0.1.50: icmp_seq=1 ttl=64 time=0.523 ms
# パケットサイズを減らしながら最大MTUを探索
ping -c 3 -M do -s 1473 target-server.example.com
# ping: local error: message too long, mtu=1500
# 自動MTU探索スクリプト
#!/bin/bash
TARGET=$1
SIZE=1500
while [ $SIZE -gt 0 ]; do
ping -c 1 -M do -s $SIZE $TARGET > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "Path MTU: $((SIZE + 28)) bytes (payload: $SIZE + 20 IP + 8 ICMP)"
break
fi
SIZE=$((SIZE - 1))
done
6.2 フラグメンテーション問題の診断
# フラグメンテーション統計の確認
cat /proc/net/snmp | grep -i frag
# Ip: ... FragCreates FragOKs FragFails
# netstatでフラグメンテーションを確認
netstat -s | grep -i frag
# フラグメンテーション発生のリアルタイムモニタリング
watch -n 1 'cat /proc/net/snmp | grep Ip: | head -2'
# MTUの変更
sudo ip link set dev eth0 mtu 9000 # Jumbo Frame
# PMTUDステータスの確認
sysctl net.ipv4.ip_no_pmtu_disc
# 0 = PMTUD有効(推奨)
6.3 Jumbo Frameの設定と検証
# Jumbo Frameサポートの確認
ethtool -i eth0
# Jumbo Frameの有効化
sudo ip link set dev eth0 mtu 9000
# Jumbo Frame経路の検証
ping -c 5 -M do -s 8972 target-server.example.com
# Jumbo Frameのパフォーマンス比較
echo "=== MTU 1500 ==="
iperf3 -c server-ip -t 10 -M 1460
echo "=== MTU 9000 ==="
iperf3 -c server-ip -t 10 -M 8960
7. Prometheus/Grafanaによるネットワークモニタリング
7.1 node_exporterの設定
# /etc/prometheus/prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'node'
static_configs:
- targets:
- 'server1:9100'
- 'server2:9100'
- 'server3:9100'
scrape_interval: 5s
node_exporterが収集する主要なネットワークメトリクスは以下の通りです。
node_network_receive_bytes_total: 受信バイト総計node_network_transmit_bytes_total: 送信バイト総計node_network_receive_errs_total: 受信エラー総計node_network_transmit_errs_total: 送信エラー総計node_network_receive_drop_total: 受信ドロップ総計node_network_transmit_drop_total: 送信ドロップ総計
7.2 PromQLクエリの例
# インターフェースごとの受信トラフィックレート(bps)
rate(node_network_receive_bytes_total{device!="lo"}[5m]) * 8
# インターフェースごとの送信トラフィックレート(bps)
rate(node_network_transmit_bytes_total{device!="lo"}[5m]) * 8
# パケットエラー率(%)
rate(node_network_receive_errs_total{device="eth0"}[5m])
/ rate(node_network_receive_packets_total{device="eth0"}[5m]) * 100
# パケットドロップ率
rate(node_network_receive_drop_total{device="eth0"}[5m])
# 帯域幅使用率(%)
rate(node_network_receive_bytes_total{device="eth0"}[5m]) * 8
/ node_network_speed_bytes{device="eth0"} / 8 * 100
# TCP再送率
rate(node_netstat_Tcp_RetransSegs[5m])
/ rate(node_netstat_Tcp_OutSegs[5m]) * 100
# 状態別TCP接続数
node_netstat_Tcp_CurrEstab
7.3 Grafanaアラートルール
# Grafana Alert Rules
groups:
- name: network_alerts
rules:
- alert: HighPacketLoss
expr: |
rate(node_network_receive_errs_total{device="eth0"}[5m])
/ rate(node_network_receive_packets_total{device="eth0"}[5m]) > 0.01
for: 5m
labels:
severity: warning
annotations:
summary: 'High packet loss on {{ $labels.instance }}'
description: 'Packet loss rate is {{ $value | humanize }}%'
- alert: HighBandwidthUsage
expr: |
rate(node_network_receive_bytes_total{device="eth0"}[5m]) * 8
/ 10000000000 > 0.85
for: 10m
labels:
severity: warning
annotations:
summary: 'High bandwidth usage on {{ $labels.instance }}'
- alert: NetworkInterfaceDown
expr: node_network_up{device="eth0"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: 'Network interface down on {{ $labels.instance }}'
- alert: HighTcpRetransmission
expr: |
rate(node_netstat_Tcp_RetransSegs[5m])
/ rate(node_netstat_Tcp_OutSegs[5m]) > 0.05
for: 5m
labels:
severity: warning
annotations:
summary: 'High TCP retransmission rate on {{ $labels.instance }}'
7.4 SNMP Exporterの活用
# SNMP exporter設定(ネットワーク機器のモニタリング)
# /etc/prometheus/snmp.yml(generatorで生成)
# prometheus.ymlにSNMPターゲットを追加
scrape_configs:
- job_name: 'snmp'
static_configs:
- targets:
- 'switch01.example.com'
- 'router01.example.com'
metrics_path: /snmp
params:
module: [if_mib]
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: snmp-exporter:9116
8. 実務パフォーマンス診断シナリオ
8.1 シナリオ:アプリケーション応答遅延
# ステップ1: DNS解決遅延のチェック
dig target-server.example.com | grep "Query time"
# Query time: 245 msec <-- DNSが遅い
# 解決策: ローカルDNSキャッシュまたはより高速なDNSサーバの使用
# /etc/resolv.confのnameserverを変更
# ステップ2: TCPコネクション確立時間の確認
curl -o /dev/null -s -w "\
DNS: %{time_namelookup}s\n\
Connect: %{time_connect}s\n\
TLS: %{time_appconnect}s\n\
TTFB: %{time_starttransfer}s\n\
Total: %{time_total}s\n" \
https://target-server.example.com
# ステップ3: 経路上の問題を確認
mtr -r -c 50 target-server.example.com
8.2 シナリオ:ファイル転送速度の低下
# ステップ1: ローカルインターフェースの状態確認
ethtool eth0 | grep -E "(Speed|Duplex|Link)"
# Speed: 1000Mb/s
# Duplex: Full
# Link detected: yes
# オートネゴシエーション失敗で100Mbpsに固定された場合
sudo ethtool -s eth0 speed 1000 duplex full autoneg on
# ステップ2: エラーカウンタの確認
ethtool -S eth0 | grep -E "(error|drop|crc|collision)"
# ステップ3: TCPチューニング状態の確認
sysctl net.ipv4.tcp_rmem
sysctl net.ipv4.tcp_wmem
sysctl net.core.rmem_max
sysctl net.core.wmem_max
# ステップ4: 帯域幅の測定
iperf3 -c remote-server -t 30 -P 4
8.3 シナリオ:間欠的な接続断
# ステップ1: 長時間pingでパターンを把握
ping -c 3600 -i 1 target-server.example.com | while read line; do
echo "$(date '+%Y-%m-%d %H:%M:%S') $line"
done | tee ping_log.txt
# ステップ2: インターフェースフラッピングの確認
dmesg | grep -i "link\|eth0\|carrier"
journalctl -u NetworkManager --since "1 hour ago" | grep -i "disconnect\|connect"
# ステップ3: ARPテーブルの異常確認
ip neigh show | grep -i "FAILED\|STALE"
# ステップ4: スイッチポート統計の確認(SNMPまたは管理インターフェース)
snmpwalk -v2c -c public switch01 IF-MIB::ifOperStatus
snmpwalk -v2c -c public switch01 IF-MIB::ifInErrors
8.4 シナリオ:VoIP品質問題
# ステップ1: ジッタとパケットロスの測定
iperf3 -c voip-server -u -b 100K -t 60 -l 160
# VoIPは通常64-160バイトの小さなパケットを使用
# ステップ2: QoS設定の確認
tc qdisc show dev eth0
tc class show dev eth0
tc filter show dev eth0
# ステップ3: QoSポリシーの適用(VoIPトラフィックの優先)
sudo tc qdisc add dev eth0 root handle 1: htb default 30
sudo tc class add dev eth0 parent 1: classid 1:1 htb rate 1000mbit
sudo tc class add dev eth0 parent 1:1 classid 1:10 htb rate 100mbit ceil 200mbit prio 1
sudo tc class add dev eth0 parent 1:1 classid 1:30 htb rate 900mbit ceil 1000mbit prio 3
# VoIPトラフィックを高優先度クラスに分類
sudo tc filter add dev eth0 parent 1: protocol ip prio 1 \
u32 match ip dport 5060 0xffff flowid 1:10
まとめ
ネットワークパフォーマンス分析は、以下の順序で体系的にアプローチすることが重要です。
- 指標の収集: レイテンシ、スループット、パケットロス、ジッタを測定する
- 区間分析: mtr、tracerouteで問題区間を特定する
- インターフェース検査: ethtool、ipコマンドで物理的な問題を確認する
- プロトコル分析: TCPウィンドウ、輻輳制御の状態を点検する
- MTU確認: パスMTUとフラグメンテーション問題を検証する
- 継続モニタリング: Prometheus/Grafanaでトレンドを観察する
各ステップで正しいツールを選択し、結果を正確に解釈する能力が重要です。単一のツールに依存せず、複数のツールの結果をクロスバリデーションして、問題の根本原因を正確に特定してください。