7. Resolver Implementation (リゾルバ実装)
推奨されるリゾルバアルゴリズムの最上位レベルはRFC-1034で説明されています。このセクションでは、このメモのネームサーバー実装セクションで提案されているデータベース構造を前提とした実装の詳細について説明します。
7.1. Transforming a User Request into a Query (ユーザーリクエストのクエリへの変換)
リゾルバが最初に行うステップは、ローカルOSに適した形式で述べられたクライアントのリクエストを、特定のQTYPEおよびQCLASSに一致する特定の名前でのRRの検索仕様に変換することです。
クエリ仕様ガイドライン
単一タイプとクラスの優先: 可能な場合、QTYPEとQCLASSは単一のタイプと単一のクラスに対応すべきです (SHOULD)。これにより、キャッシュされたデータの使用がはるかに簡単になります。
理由: キャッシュ内の1つのタイプのデータの存在は、他のタイプのデータの存在または非存在を確認しません。したがって、確認する唯一の方法は、権威ソースに相談することです。
QCLASS=*の制限: QCLASS=*が使用される場合、権威的な回答は利用できません。
リクエスト状態情報
リゾルバは、その機能を効率的に実行するために複数のリクエストを多重化できなければならないため、各保留中のリクエストは通常、何らかの状態情報のブロックで表されます。
この状態ブロックには通常、次のものが含まれます:
1. タイムスタンプ (Timestamp)
目的: リクエストが開始された時刻を示します。
使用法:
- タイムスタンプは、データベース内のRRが使用できるか、または古いかを決定するために使用されます
- このタイムスタンプは、ゾーンとキャッシュでのRRストレージについて以前に説明した絶対時間形式を使用します
TTL解釈:
- RRのTTLが相対時間を示す場合、RRはタイムリーでなければなりません (MUST)。これはゾーンの一部であるためです
- RRが絶対時間を持つ場合、それはキャッシュの一部であり、RRのTTLはリクエスト開始のタイムスタンプと比較されます
タイムスタンプの利点: タイムスタンプを使用することは、現在時刻を使用するよりも優れています。これにより、TTLがゼロのRRを通常の方法でキャッシュに入力できますが、システム負荷、クエリ再送信タイムアウトなどによる多くの秒の間隔の後でも、現在のリクエストで使用できます。
2. 作業制限パラメータ (Work Limitation Parameters)
目的: このリクエストに対して実行される作業量を制限するための何らかのパラメータ。
理論的根拠: クライアントリクエストに応じてリゾルバが行う作業量は、次のものから保護するために制限されなければなりません (MUST):
- 循環CNAME参照などのデータベースのエラー
- リゾルバが必要とするネームサーバーへのアクセスを妨げるネットワーク分割などの運用上の問題
実装:
- リゾルバが特定のネームサーバーアドレスに特定のクエリを再送信する回数に関するローカル制限は不可欠ですが
- リゾルバは、単一のリクエストの作業を制限するためにグローバルなリクエストごとのカウンターを持つべきです (SHOULD)
- カウンターは初期値に設定され、リゾルバがアクション (再送信タイムアウト、再送信など) を実行するたびに減分されるべきです (SHOULD)
- カウンターがゼロを超えた場合、リクエストは一時的なエラーで終了します
並列リクエスト: リゾルバ構造が、1つのリクエストがネームサーバーにアクセスする必要があるときにネームサーバーのアドレスの並列解決を引き起こすなど、1つのリクエストが並列で他のリクエストを開始できる場合、生成されたリクエストはより低いカウンターで開始されるべきです (SHOULD)。これにより、データベース内の循環参照がリゾルバアクティビティの連鎖反応を開始することが防止されます。
3. SLISTデータ構造 (SLIST Data Structure)
RFC-1034で説明されているSLISTデータ構造。
目的: この構造は、外部ネームサーバーからの回答を待つ必要がある場合に、リクエストの状態を追跡します。
7.2. Sending the Queries (クエリの送信)
RFC-1034で説明されているように、リゾルバの基本的なタスクは、クライアントのリクエストに答えるクエリを定式化し、そのクエリを情報を提供できるネームサーバーに向けることです。
クエリ定式化の課題
リゾルバは通常、NS RRの形式で、どのサーバーに尋ねるべきかについて非常に強いヒントしか持っておらず、次のことをする必要がある場合があります:
- CNAMEに応じてクエリを修正する
- リゾルバが求めているネームサーバーのセットを修正する。これは、リゾルバを望ましい情報に近いネームサーバーに向ける委任応答に応じて行われます
クライアントが要求した情報に加えて、リゾルバは、接続したいネームサーバーのアドレスを決定するために、独自のサービスを呼び出す必要がある場合があります。
リゾルバモデル
このメモで使用されているモデルは次のことを前提としています:
- リゾルバは、クライアントからのものと内部生成されたものの両方を含む、複数のリクエスト間で注意を多重化しています
- 各リクエストは何らかの状態情報で表されます
- 望ましい動作は、リゾルバが次の方法でネームサーバーにクエリを送信することです:
- リクエストが回答される確率を最大化する
- リクエストにかかる時間を最小化する
- 過度の送信を回避する
主要アルゴリズム
主要アルゴリズムは、リクエストの状態情報を使用して次のことを行います:
- クエリする次のネームサーバーアドレスを選択する
- 応答が到着しない場合に次のアクションを引き起こすタイムアウトを計算する
次のアクションは通常、他のサーバーへの送信ですが、クライアントへの一時的なエラーである場合があります。
SLIST初期化
開始点: リゾルバは常に、クエリするサーバー名のリスト (SLIST) から始めます。
初期内容:
- このリストは、リゾルバが知っている最も近い先祖ゾーンに対応するすべてのNS RRになります
- 起動の問題を回避するために、リゾルバは、適切な現在のNS RRがない場合に尋ねるデフォルトサーバーのセットを持つべきです (SHOULD)
アドレスの追加: 次に、リゾルバはネームサーバーの既知のすべてのアドレスをSLISTに追加し、リゾルバがネームサーバーの名前を持っているがアドレスを持っていない場合、サーバーのアドレスを取得するための並列リクエストを開始する場合があります (MAY)。
履歴情報
SLIST の初期化を完了するために、リゾルバはSLIST内の各アドレスに持っている履歴情報を添付します。
典型的な履歴データ:
- アドレスの応答時間の何らかの加重平均 (Weighted Averages)
- アドレスの打率 (Batting Average) (つまり、アドレスがリクエストにどのくらいの頻度で応答したか)
重要な注意事項:
- この情報は、ネームサーバーベースではなく、アドレスベースで保持されるべきです (SHOULD)。特定のサーバーの応答時間と打率は、アドレスによって大幅に異なる可能性があるためです
- この情報は実際にはリゾルバアドレス/サーバーアドレスペアに固有であるため、複数のアドレスを持つリゾルバは、各アドレスの個別の履歴を保持したい場合があります (MAY)
- そのような履歴を持たないアドレスの場合: 予想される往復時間は5〜10秒が最悪のケースであるべきです (SHOULD)。同じローカルネットワークなどのより低い推定値を使用します
委任処理: 委任が続く場合、リゾルバアルゴリズムはSLISTを再初期化することに注意してください。
サーバー選択とタイムアウト
ランク付け: この情報は、利用可能なネームサーバーアドレスの部分的なランク付けを確立します。
選択戦略: アドレスが選択されるたびに、他のすべてのアドレスが試されるまで、その選択を再度防ぐように状態を変更すべきです (SHOULD)。
タイムアウト計算: 各送信のタイムアウトは、応答の分散を考慮するために、平均予測値よりも50〜100%大きくすべきです (SHOULD)。
特殊なケース
ブートストラップの問題:
- リゾルバは、SLISTに指定されたネームサーバーのいずれに対してもアドレスが利用できず、リスト内のサーバーが通常自身のアドレスを検索するために使用されるサーバーである状況に遭遇する場合があります
- この状況は通常、グルーアドレスRRが委任をマークするNS RRよりも小さいTTLを持っている場合、またはリゾルバがNS検索の結果をキャッシュする場合に発生します
- リゾルバはこの状態を検出し、次の先祖ゾーンで、または代替としてルートで検索を再開すべきです (SHOULD)
サーバーエラー:
- リゾルバがネームサーバーからサーバーエラーまたは他の奇妙な応答を受け取った場合、それをSLISTから削除すべきです (SHOULD)
- リゾルバは、次の候補サーバーアドレスへの即時送信をスケジュールしたい場合があります (MAY)
7.3. Processing Responses (応答の処理)
到着する応答データグラムを処理する最初のステップは、応答を解析することです。
応答解析手順
この手順には次のものを含むべきです (SHOULD):
1. ヘッダーチェック:
- ヘッダーの妥当性をチェックする
- 応答が期待されているときにクエリであるデータグラムを破棄する
2. セクション解析:
- メッセージのセクションを解析する
- すべてのRRが正しくフォーマットされていることを確認する
3. TTLチェック (オプション):
- オプションのステップとして、到着するデータのTTLをチェックし、過度に長いTTLを持つRRを探します
- RRが過度に長いTTL、たとえば1週間以上を持つ場合:
- 応答全体を破棄する
- または応答内のすべてのTTLを1週間に制限する
応答マッチング
次のステップは、応答を現在のリゾルバリクエストに一致させることです。
推奨戦略:
- ドメインヘッダーのIDフィールドを使用して予備的なマッチングを行う
- 次に、質問セクションが現在望まれている情報に対応することを確認する
実装要件: これには、送信アルゴリズムがドメインIDフィールドの数ビットを何らかのリクエスト識別子に割り当てる必要があります。
特別な考慮事項
ソースアドレスの変動:
- 一部のネームサーバーは、クエリの受信に使用されたアドレスとは異なるアドレスから応答を送信します
- つまり、リゾルバは、対応するクエリを送信したのと同じアドレスから応答が来ることを信頼できません (CANNOT)
- このネームサーバーのバグは通常、UNIXシステムで発生します
再送信処理:
- リゾルバが特定のリクエストをネームサーバーに再送信する場合、いずれかの送信からの応答を使用できるべきです (SHOULD)
- ただし、応答を使用してネームサーバーにアクセスするための往復時間をサンプリングする場合:
- どの送信が応答と一致するかを決定できなければなりません (MUST) (および各送信メッセージの送信時間を保持する)
- または最初の送信のみに基づいて往復時間を計算する
欠落しているゾーンデータ:
- ネームサーバーは、一部のNS RRに従って持つべきゾーンの現在のコピーを時折持っていない場合があります
- リゾルバは単に現在のSLISTからネームサーバーを削除し、続行すべきです (SHOULD)
7.4. Using the Cache (キャッシュの使用)
一般的に、リゾルバは、将来のクライアントリクエストに答えるのに役立つ可能性があるため、応答で受信するすべてのデータをキャッシュすることが期待されます。
ただし、キャッシュすべきではない (SHOULD NOT) いくつかのタイプのデータがあります:
キャッシュすべきではないデータ
1. 不完全なセット:
- 特定の所有者名に対して同じタイプの複数のRRが利用可能な場合、リゾルバはすべてをキャッシュするか、まったくキャッシュしないかのどちらかにすべきです (SHOULD)
- 応答が切り詰められ、リゾルバが完全なセットを持っているかどうかわからない場合、部分的な可能性のあるRRのセットをキャッシュすべきではありません (SHOULD NOT)
2. 権威データよりも非権威データ:
- キャッシュされたデータは、権威データよりも優先して使用されるべきではありません (SHOULD NEVER)
- キャッシュがこれを引き起こす場合、データをキャッシュすべきではありません (SHOULD NOT)
3. 逆引きクエリの結果:
- 逆引きクエリの結果はキャッシュすべきではありません (SHOULD NOT)
4. ワイルドカードクエリの結果:
- データがワイルドカードを構築するために使用される可能性がある場合、QNAMEに
*ラベルが含まれる標準クエリの結果 - 理由: キャッシュには、ワイルドカードRRのアプリケーションを制限するために必要な既存のRRまたはゾーン境界情報が必ずしも含まれていません
5. 疑わしい信頼性のデータ:
- 疑わしい信頼性の応答内のRRデータ
- リゾルバが要求されていない応答またはRRデータを受信した場合、キャッシュせずに破棄すべきです (SHOULD)
- 基本的な意味: パケットのすべての健全性チェックは、それがキャッシュされる前に実行されるべきです (SHOULD)
キャッシュ更新戦略
リゾルバが応答内のある名前のRRのセットを持ち、RRをキャッシュしたい場合:
- すでに存在するRRについてキャッシュをチェックすべきです (SHOULD)
- 状況に応じて、応答内のデータまたはキャッシュのいずれかが優先されます
- 2つを組み合わせるべきではありません (SHOULD NEVER)
- 応答内のデータが回答セクションの権威データからのものである場合、それは常に優先されます (ALWAYS)
ベストプラクティスの概要
効率的なリゾルバ実装のために
-
可能な場合は単一タイプとクラスのクエリを使用する - より良いキャッシュ利用のため
-
リクエストごとの状態を維持する - タイムスタンプと作業カウンターを含む
-
アドレスごとの履歴を保持する - スマートなサーバー選択のため
-
適切なタイムアウト戦略を実装する (予測時間の50〜100%上)
-
特殊なケースを処理する - ブートストラップの問題とサーバーエラーなど
-
応答を慎重に解析する - ヘッダーチェックと形式検証を含む
-
選択的にキャッシュする - すべてのデータをキャッシュすべきではありません
-
権威データを優先する - 両方が利用可能な場合、キャッシュされたデータよりも
関連: サーバー側の詳細については、6. Name Server Implementation (ネームサーバー実装)を参照してください