VOLUME 05 / CHAPTER 03
つながったのに、画面が使えない
名前解決、通信、TLS、HTTP、業務の成功を層ごとに分ける。通信回数とキャッシュの利点を、再試行・更新・移行の条件から読み解く。
出典照合日: · 独自解説
架空事例:青葉機材が倉庫向けWeb画面を新しい公開経路へ移す。URL、通信時間、障害は独自の作例である。通信の説明では、TCP上のTLSでHTTPを運ぶ構成を対象とする。すべてのHTTPS通信がTCPを使うとする説明ではない。
接続試験は成功していた
新しいサーバへの接続は成功した。トップページも返った。それなのに、倉庫担当者の画面には文字だけが並び、予約を検索できなかった。
調べると、HTMLが参照するCSSとJavaScriptのURLが誤っていた。画面を置いた場所は /library/ なのに、必要なファイルをサイトのルートから取得しようとしていたのである。
これは、すべての通信が切れた障害ではない。HTMLを取得する要求は成功し、そのHTMLが必要とする別の要求が失敗していた。一つの接続や一つの応答から、画面全体の成功へ結論を広げたところに見落としがあった。
システム間連携を設計するときも、同じ区別が必要になる。宛先に届くこと、相手が要求を解釈すること、業務で必要な結果が得られることは、別の段階である。原教材第19章の層の区別を、動かない画面から逆にたどる。1
名前を変更したのに、古い相手へ届く
青葉機材は、公開名が示すアドレスを新しいサーバへ変更した。しかし、しばらく旧サーバへの要求も続いた。管理画面に新しいアドレスが表示されることと、各利用者がその値を使っていることは一致しない。
DNSでは、権威を持つ側の情報と、リゾルバなどが持つキャッシュを区別する。RFC 1034は、TTLをレコードのキャッシュ保持に関わる秒単位の値として説明している。2 キャッシュが有効な間、過去の応答を再利用する経路があり得る。
本事例で切替直前にTTLを短くしても、既に古いTTLで保存された応答の残り時間を、遠隔から一斉に書き換えたことにはならない。また、既に確立した接続を、DNSの変更だけで新しい相手へ付け替えたことにもならない。
そのため、旧サーバを停止する時刻は、DNSの編集を保存した時刻だけでは決めない。実際の参照・接続の状態と、切替期間中に新旧どちらが更新を受け付けるかを確認する。ここで必要なのは、TTLを短くするという設定だけでなく、移行中の業務を矛盾なく扱う方針である。
同じ経路でも、機器が見ている情報は違う
同一リンクのフレームをMACアドレスに従って転送する働きと、IPパケットをネットワーク間で配送する働きは異なる。L2スイッチとルータを、どちらも「通信を中継する箱」としてだけ覚えると、どこで判断が行われているかを見失う。1
青葉機材の端末は、社内の宛先には届くが、新しい公開先には届かなかったとする。同じLAN内の到達だけを確認しても、外向きの経路や通信制御まで確認したことにはならない。さらに、公開先のIPアドレスへ届いても、目的のアプリケーションがそのポートで受け付けているかは別に調べる。
NATやNAPTによるアドレス・ポートの変換も、利用者がその予約を閲覧してよいかという認可ではない。ネットワーク上の到達範囲と、アプリケーションの操作範囲を、それぞれの層で定める。
TCPが運ぶのは、一回分の予約ではない
独自の通信方式で、予約情報を一回の送信操作で渡したとする。受信側が一回の読取りで、必ずちょうど一予約分を受け取れるとは限らない。
TCPは、信頼性のある順序付きのバイトストリームを提供する。アプリケーションの書込み・読取りの区切りと、TCPセグメントの区切りが一致する保証はない。3 二回に分けた送信がまとめて見える場合も、一回の送信を複数回に分けて読む場合も想定する必要がある。
本事例で独自形式を作るなら、どこまでが一件かを、長さなどの規則で識別する。長さが不正な場合や途中で切れた場合も、その通信方式の契約として扱う。HTTPを使うなら、その版のメッセージ処理を担う実装の契約へ従う。TCPの再送があることを、業務メッセージの解釈まで任せられる根拠にしない。
また、通信上の確認応答と、予約DBへのコミットは同じ出来事ではない。バイト列を受け取った後に業務処理が失敗する場合もある。第3巻で扱った「結果が分からない状態」は、通信路に信頼性があっても残る。
暗号化が終わる場所を確認する
ブラウザと公開ゲートウェイの間でTLSを使っていた。では、ゲートウェイから予約サーバまでの通信も、同じ接続によって保護されているだろうか。
TLSをそこで終端し、別の接続で予約サーバへ転送する構成なら、後半は別に設計する必要がある。TLS 1.3の仕様が扱うのは、通信相手の認証、機密性、完全性などを備える通信路である。4 保護する区間がどこまでかを確認せず、「HTTPSだから全経路で安全」とまとめない。
青葉機材では、ゲートウェイが確認した利用者を、予約サーバへどのように伝えるかも検討する。単に利用者番号という文字列が届くことと、その値を信頼してよいことは違う。直接予約サーバへ到達できる経路があるなら、ゲートウェイだけの確認を迂回しないかも見る。
さらに、正しいサービスへ暗号化して接続できても、他人の予約を閲覧してよいことにはならない。通信相手の確認と、業務上の認可の境界は、次巻のセキュリティ設計にもつながる。
帯域を増やしても、往復は消えない
一回の照会に50ミリ秒の通信往復が必要で、前の応答を待ってから次を送る照会が六回あるとする。接続開始、処理、データ転送の追加時間を無視しても、この直列の往復だけで300ミリ秒になる。
小さな照会を六回行う処理で、帯域だけを増やしても、往復の待ちが同じならその部分は消えない。必要な項目をまとめて取得する案や、互いに依存しない照会を並行する案を検討できる。ただし、一つの要求へ全件を詰め込めば、不要な取得や応答サイズの増大につながる場合もある。
本事例では、予約一覧の各行に必要な機材名を、一行ずつ別の要求で取得していた。どの機材番号が必要かは一覧を作る段階で分かっている。その番号の集合に絞った取得へ変えることを検討する。各機材へのアクセス権限を確認する責任は、要求をまとめても残る。
速い通信設備を選ぶことと、往復を必要以上に作らないインタフェースを選ぶことは、別の改善である。
再送してよいかは、返事の内容だけでは決まらない
予約確定を依頼したが、応答が届かなかった。この状態を失敗と断定して、同じ確定操作を新しい操作として繰り返すと、二重処理を生む可能性がある。原教材第7章の再試行と冪等性は、通信障害への応答を決めるために必要になる。1
HTTPの冪等性は、同じ要求を繰り返したときの意図した効果に関する性質であり、応答本文や状態コードが毎回同一という意味ではない。RFC 9110は、通信が切れた場合の再試行をこの性質と結び付けている。5
青葉機材の確定APIがPOSTを使うなら、POSTだから絶対に再試行できないと決めるのでも、TCPに再送があるから無条件に繰り返すのでもない。同じ業務操作を識別できる契約、確定済み結果の照会、途中状態の扱いを設計する。メソッド名を変えるだけで、内部の重複処理が直るわけではない。
GETなどの安全なメソッドを、予約削除のような操作へ流用するのも適切ではない。安全という語は、主に要求された意味が読取り中心であることを指す。アクセスログまで一切変化しないという意味ではない。5
別の場所を読むのか、同じ要求を送るのか
受付完了後、結果を確認する別URLへ案内する場合と、同じ送信内容を別の宛先へ送らせる場合では、適した応答が違う。
303は、別のリソースをGETやHEADによって参照する方向へ案内する。307は、一時的な移動先へ自動的に要求を送り直す際にメソッドを変えない。どちらも3xxだという理由で入れ替えない。1 細部はRFC 9110の15.4.4と15.4.8へ対応する。5
例えば、受付処理の後に結果ページを表示させたい設計で、再度POST本文を処理させる経路へ誘導すると、意図が変わってしまう。画面が遷移したという観測だけでなく、次にどのメソッドで、何のために通信したかを見る。
保存しないことと、確かめてから使うこと
新しいCSSを配置したのに、ある端末では古い表示が続いた。別の担当者は、すべてに no-cache を付ければ、保存自体を防げると考えた。
HTTPキャッシュで、フィールド名を指定しない no-cache は、再利用前に検証することを要求する。保存そのものを禁じる no-store とは異なる。また、修飾のない private は、共有キャッシュと個人用キャッシュの扱いを分ける指示である。6
検証の結果として304が返る場合、保存済みの応答を条件に従って更新・再利用できる。必ず全文を再転送したわけではない。保存の可否、有効期間、再利用前の検証を別々に考えると、キャッシュを使うか使わないかの二択から抜け出せる。6
青葉機材では、全利用者に共通の静的な部品と、顧客ごとに異なる予約情報を同じ規則で配信しない。表示が速くなっても、別の顧客の情報を再利用したなら設計は失敗である。なお、no-store を付けたことだけで、悪意ある相手を含めたあらゆる保存を防ぐ保証にもならない。
どの成功を確認したかを残す
名前が引けない。接続できない。TLSの相手を確認できない。必要なURLから期待する応答が得られない。画面は表示できるが予約を完了できない。それぞれに必要な観測がある。
最初の「トップページが返る」という試験は残してよい。しかし、公開先のパスでCSSやJavaScriptを取得できるか、代表的な操作が完了するかも確認する。成功を確認する層を増やすのであって、同じ接続試験を何度も繰り返して保証を広げるのではない。
障害調査でも、どの要求が、どの段階まで成功したかを区別して記録する。すべてを「ネットワークエラー」と呼ぶより、直すべき責務の境界が見える。
知識を答案へ戻す
午前Ⅱ。 L2とL3、ポートと業務権限、TCPのバイト列とメッセージ、TLSと認可を区別する。HTTPでは、再試行の効果、リダイレクト後のメソッド、キャッシュの保存と検証を別々に読む。
午後Ⅰ。 誰から誰への、どの層の通信が失敗したかを与件から特定する。DNS変更を即時の接続切替え、応答の到着を業務上の成功と読み替えない。
午後Ⅱ。 性能や移行の要求から通信方式を選び、平常時だけでなく、古い情報・途中失敗・再送・経路変更の扱いを説明する。暗号化やキャッシュという名称だけで効果を断定しない。
立ち止まって考える:HTMLの取得に成功し、通信も暗号化されていた。画面を公開してよいか
その確認だけでは、HTMLが参照する部品、業務API、利用者ごとのアクセス制御、必要な操作の完了まで分からない。公開経路で実際に利用する要求と操作へ、確認範囲を合わせる必要がある。
出典と照合範囲
[1] コンプリートテキスト第7・16・19・20・22章、IPA「SAシラバス Ver.5.2」4-9、5-5、10-2、12-2、18-1:通信の層、再試行、暗号、キャッシュ、連携を出発点とした。架空の公開障害と判断は独自の説明である。直列6往復の算術とルート相対・文書相対URLの例はPythonで確認した。実通信の測定ではない。公式シラバス
[2] RFC 1034, Domain Names — Concepts and Facilities, 3.6:TTLと権威情報・キャッシュの区別を参照した。1987年の推奨TTL値を現在の運用推奨へ転用していない。すべてのリゾルバの障害時動作やキャッシュ実装を扱う章ではない。RFC本文
[3] RFC 9293, TCP, 2.2・3.7:順序付きバイトストリームと、セグメント・アプリケーションの区切りの関係を参照した。予約の確定との区別は、本事例への独自の適用である。RFC本文
[4] RFC 8446, TLS 1.3, 1:通信路の認証・機密性・完全性の位置付けを参照した。ゲートウェイ構成は独自の例であり、TLSの全機能やすべての認証方式を説明していない。RFC本文
[5] RFC 9110, HTTP Semantics, 9.2・15.4.4・15.4.8:安全性と冪等性の意味、303と307の区別を照合した。予約APIの再試行契約は本事例の設計上の検討である。RFC本文
[6] RFC 9111, HTTP Caching, 4.3・5.2.2:304による検証、no-cache・no-store・privateの違いを参照した。フィールド名付きの修飾や拡張指示を含む、全組合せの解説ではない。HTTP Working Group公開本文