TCP ハンドシェイクの後に固まるクエリは、ルーティングの問題ではない。経路の障害はハンドシェイクを失敗させるので、確立した後に沈黙するセッションは経路の内側を指している。インスペクション、MTU、あるいはトンネルの UDP パケットの届き方だ。目の前の判断は、その経路を直すか、トンネルを TCP に移すかである。三つの条件で決まり、どれもデータベースの話ではない。

トンネルを疑う前に停止を分類する

四つの結果は利用者には同じに見えるが、技術者にはまったく別の意味を持つ。

What the client seesWhat it rules out
Connection refusedNothing is listening on the address and port the client reached
Timeout before the handshakeA filter, a missing route, or the wrong address
Handshake completes, query hangsThe session exists, so look at inspection, MTU and packet order
Stalls that recover on retryOften reordering, or a state table entry expiring

トンネルに時間をかける価値があるのは最後の二行だけだ。VPN 越しの接続拒否はふつう、データベースが loopback だけで待ち受けているというリスナーの問題であり、ハンドシェイク前のタイムアウトはフィルタか経路の問題だ。どちらもカプセル化を変えても改善しない。

まず分類をチケットに書く。いちばん安い手順で、探索空間の大半が消える。

UDP と TCP を分ける三つの条件

カプセル化された IPsec の通信は UDP で流れ、UDP は経路に並べ替えや破棄の自由を誰にも告げずに与える。並べ替えがパケットをトンネルの再送防止ウィンドウの外へ押し出すと、それらは静かに捨てられ、内側の TCP セッションはただ待つ。ハンドシェイクが成功し、クエリが決して戻らないのは、この仕組みのせいだ。

経路を直すか TCP に切り替えるかは三つで決まる。一つ目、経路に本当のパケット損失があるのか、並べ替えだけなのか。二つ目、インスペクションの場所を変えられるか、並べ替えるコンポーネントからこのトンネルを外せるか。三つ目、負荷が停止のパターンに敏感か、たとえば一本のリンクを共有する多数の多重化セッションか。

一つ目の答えが損失で、二つ目がいいえなら、443 の TCP が現実的な代替だ。二つ目の答えがはいなら、経路を直して UDP のままにする。

アプリケーションのエラーではなく、ファイアウォールの記録を読む

アプリケーションはタイムアウトを報告するが、原因については何も語らない。破棄やブロックが現れるのはファイアウォール自身のログなので、データベースとアプリケーションのアドレスで絞り込み、許可だけでなく破棄も探す。脅威対策ブレードは、アプリケーション層のエラーを出さずにパケットを破棄できる。これはまさに固まるクエリの形だ。ログの沈黙もデータである。ログを残さない何か、たとえば並べ替えを指している。

クラスタも確認する。設定を誤ったクラスタは、パケットが別のメンバーの経路を通るのに、セッションを一方のメンバーのステートテーブルに保持することがあり、状態のない場所に応答が届く。そうした停止は不規則に見え、負荷と相関しない。

何かを変える前に両端を比較し、パケット数ではなく到着順を比べる。

tcpdump -ni any udp port 4500 -w /tmp/encap.pcap
tcpdump -ni any tcp port 5432 -w /tmp/inner.pcap

443 の TCP が実際に何を犠牲にするか

トンネルを TCP に移すと並べ替えの症状は消える。中間装置が順序のあるストリームを見るからだ。ただし TCP over TCP を生む。外側の接続が、内側の接続がすでに再送したものを再送し、一度の損失で多重化された全セッションが同時に止まりうる。きれいな経路では見えない。損失のある経路では、対症療法が症状より悪い。

代替が接続不能である場合に限り、この交換は受け入れられる。当然のものとして吸収するのではなく、責任者を添えた例外として記録すべきだ。

トランスポート、ポート、サンプルのクエリ、測定した結果、そして日付を記録する。その記録がなければ次の技術者が同じ実験を繰り返し、例外は静かにアーキテクチャになる。

判断を見直せる状態に保つ

経路の診断は早く古びる。中間装置は交換され、ブレードの設定は変わり、リンクは更新され、443 の TCP の理由は消えるのに設定は残る。例外に見直しの日付を入れ、UDP に戻せる条件を名指しする。

小さなクエリと大きな結果セットの両方で、二つのトランスポートを試す。並べ替えはサイズ依存の停止として現れ、リスナーの障害はどちらのサイズも等しく止める。

関連記事