負荷試験は「数字の羅列」ではない――パケットの悲鳴を聴くためのAPIパフォーマンス・チューニング
多くのエンジニアがJMeterやk6を回して「スループットが出ない」「レイテンシが跳ねる」と嘆く。しかし、ダッシュボード上のグラフを眺めるだけで終わらせてはいないだろうか。
APIの負荷試験とは、単なる負荷の押し付けではない。それは、OSのネットワークスタック、TCPの輻輳制御アルゴリズム、そしてTLSハンドシェイクという「物理的な制約」と我々との対話である。今回は、インフラアーキテクトが知っておくべき、パケットレベルの深い領域にまで踏み込んだパフォーマンス最適化とボトルネック分析の手法を紐解こう。
—
1. 測定指標を「解像度高く」見るということ
スループット(RPS)や平均レイテンシといったマクロな指標は、あくまで結果論だ。真に追うべきは、「テールレイテンシ(P99/P99.9)」と「TCP再送率」である。
- P99の異常値: CPU負荷やDBのロックだけが原因ではない。多くの場合、
TCP_NODELAYの設定ミスによるNagleアルゴリズムの弊害や、GC(ガベージコレクション)の停止時間が影響している。 - TCP再送率: これが上昇している時点で、ネットワーク帯域の飽和か、バッファ溢れによるパケットロスが発生している。
netstat -sやnstatを見て、RetransSegsが積み上がっていないか確認せよ。
—
2. トランスポートとTLS:そのハンドシェイクを削ぎ落とせ
APIのレイテンシを語る上で、TLSハンドシェイクのオーバーヘッドを無視することはできない。特にRTT(Round Trip Time)が大きい環境では、TCPとTLSのハンドシェイクだけで数往復の通信が発生する。
TLS 1.3の採用と0-RTT
TLS 1.3ではハンドシェイクが1往復に短縮された。さらに 0-RTT (Early Data) を有効化することで、クライアントは接続確立と同時にデータを送信できる。ただし、リプレイ攻撃のリスクがあるため、冪等な GET リクエスト以外での利用には極めて慎重であるべきだ。
TCPバッファの最適化
Linuxカーネルのデフォルト設定は、現代の高速なAPI環境にはあまりに保守的すぎる。以下のsysctlパラメータで、ウィンドウサイズを適切に拡張せよ。
# /etc/sysctl.conf に記述する推奨設定
# 受信バッファの最小値、デフォルト値、最大値を設定
net.ipv4.tcp_rmem = 4096 87380 16777216
# 送信バッファの最小値、デフォルト値、最大値を設定
net.ipv4.tcp_wmem = 4096 65536 16777216
# TCPウィンドウのスケーリングを有効化(広帯域な通信に必須)
net.ipv4.tcp_window_scaling = 1
# 輻輳制御アルゴリズムをBBRに変更(パケットロスに強い)
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
—
3. ヘッダー圧縮とHTTP/2の真実
HTTP/2の HPACK によるヘッダー圧縮は非常に強力だが、サーバー側の実装やプロキシの構成によっては、かえってオーバーヘッドを招くこともある。
特に、APIゲートウェイを経由する場合、内部ネットワークで HTTP/1.1 にダウングレードしていないか確認してほしい。プロトコルの変換処理(プロトコルスタックの行き来)は、CPUを激しく消費し、マイクロ秒単位のレイテンシを積み上げる。エンドツーエンドで HTTP/2 または HTTP/3 (QUIC) を維持する構成を検討すべきだ。
—
4. ボトルネック特定のための現場的アプローチ
負荷試験中にパケットロスやレイテンシのスパイクが起きたとき、私はまず tcpdump でパケットのシーケンス番号を追跡する。
tcpdump による再送パケットのキャプチャ
# 特定のクライアントIPからのパケット再送を検知するコマンド
tcpdump -i eth0 'tcp[tcpflags] & (tcp-push|tcp-ack) != 0' and host <クライアントIP> -w capture.pcap
もし、サーバーからクライアントへの ACK が返るのが遅い場合、アプリケーション層で詰まっているのではなく、カーネルのバックログキューが溢れている可能性が高い。ss -nlt コマンドで Send-Q や Recv-Q を確認し、listen 中のソケットがキューを捌ききれているかを見極めろ。
—
5. 最後に:セキュリティとパフォーマンスのトレードオフ
最後に警告しておく。極限のパフォーマンスを求めて TLS の暗号化強度を下げたり、WAF の検査ルールを緩めたりしてはならない。
現代のインフラアーキテクトは、「暗号化処理をオフロードする専用ハードウェア(SSL/TLSアクセラレータ)」や、「XDP(eXpress Data Path)を用いたカーネル空間でのパケットフィルタリング」を駆使して、セキュリティを維持したままネットワークスタックのオーバーヘッドを極小化する知恵を持つべきだ。
パフォーマンスの数値は、ただの「結果」ではない。それは、君が設計したシステムの「呼吸」そのものだ。パケットの挙動を深く理解し、OSの深淵を制御できたとき、APIは真に美しく、そして強靭なものへと進化する。
さあ、次はターミナルを開き、netstat の数字から、システムが何を語りかけているのかを読み解いてみてほしい。
コメント