android/java DNSキャッシュの設定
DNSでドメイン名を検索する場合、指定したドメイン名を見つけるには複数の中間DNSサーバを経由する場合があります.そのため、DNSサーバ上でドメイン名を検索するのは非常に高価な操作です.Javaではこの問題を緩和するためにDNSキャッシュが提供されている.InetAddressクラスが初めてドメイン名(www.google.comなど)を使用してInetAddressオブジェクトを作成すると、JVMはこのドメイン名とDNSから取得した情報(IPアドレスなど)をDNSキャッシュに保存します.次にInetAddressクラスがこのドメイン名を再使用すると、DNSサーバにアクセスすることなく、DNSキャッシュから必要な情報を直接取得できます.DNSキャッシュは、デフォルトではアクセスしたドメイン名情報を永遠に保持しますが、このデフォルト値を変更できます.このデフォルト値を変更するには、一般的に2つの方法があります.1.プログラムでjava.security.Security.setPropertyメソッドを使用して、セキュリティ属性networkaddress.cache.ttlの値(単位:秒)を設定します.次のコードでキャッシュタイムアウトを10秒に設定します.
java.security.Security.setProperty("networkaddress.cache.ttl", 10);
2.java.securityファイルのnetworkaddress.cache.negative.ttlプロパティを設定します.JDKのインストールディレクトリがC:jdk 1.6であると仮定すると、java.securityファイルはc:jdk 1.6jrelibsecurityディレクトリにあります.このファイルを開き、networkaddress.cache.ttlプロパティを見つけ、このプロパティ値を対応するキャッシュタイムアウト(秒単位)に設定します.networkaddress.cache.ttlプロパティ値を-1に設定すると、DNSキャッシュデータは解放されません.次のコードでは、DNSキャッシュを使用するか使用しないかの効果を示します.
上記のコードにはDNSキャッシュタイムアウト(args[1]パラメータを介して)が設定されており、ユーザはコマンドラインパラメータを介してこの値をMyDNSに転送することができる.このプログラムはまずgetAllByNameを使用してInetAddress配列を作成し、System.in.readを使用してプログラムを一時停止します.ユーザがしばらく待つと、任意のキーを押して続行し、同じドメイン名(args[0])を使用してInetAddress配列を再構築できます.DNSキャッシュのタイムアウトよりもユーザが待機している時間が小さい場合、addresses 2とaddresses 1配列の要素は同じであり、addresses 2配列を作成するのにかかる時間は一般的に0ミリ秒(1ミリ秒未満ではJavaはより正確な時間を得ることができない)である.テスト1:DNSキャッシュタイムアウトを5秒に設定するコマンドを実行します:java mynet.MyDNS www.126.com 5実行結果1(5秒以内に任意のキーを押す):addresses 1: 344 ms www.126.com/202.108.9.77任意のキーを押してaddresses 2を続行 0 ms www.126.com/202.108.9.77実行結果2(5秒後に任意のキーを押す):addresses 1: 344 ms www.126.com/202.108.9.77任意のキーを押してaddresses 2を続行 484ミリ秒www.126.com/202.108.9.77は、上記のテストで2つの実行結果が表示される可能性があります.「任意のキーを押して続行...」が表示された後、5秒以内に任意のキーを押して続行すると、実行結果1が得られます.この結果から、addresses 2が使用する時間は0ミリ秒です.つまり、addresses 2はDNSサーバに実際にアクセスするのではなく、メモリ内のDNSから直接キャッシュされたデータです.5秒後に任意のキーを押して続行すると、実行結果2が得られ、メモリ内のDNSキャッシュのデータが解放されるので、addresses 2はDNSサーバに再アクセスする必要があるため、addresses 2の時間は484ミリ秒である(addresses 1とaddresses 2の後のミリ秒数は異なる環境で異なる場合がありますが、一般的には、実行結果1のaddresses 2の値は0または5のような0に近い数です.実行結果2のaddresses 2の値は、一般的にaddresses 1の値に近いか、1200のような0よりはるかに大きい数です).テスト2:次のコマンドを実行します.(ComputerNameはネイティブのコンピュータ名、DNSキャッシュタイムアウトは期限切れに設定されています[-1]):java mynet.MyDNS ComputerName-1実行結果(任意のキーで続行する前に192.168.18.20を削除):addresses 1: 31 ms myuniverse/192.168.18.10 myuniverse/192.168.18.20任意のキーを押してaddresses 2を続行 0ミリ秒myuniverse/192.168.18.10 myuniverse/192.168.18.20 上記のテストから、DNSキャッシュを無期限に設定した後、どのくらいの時間が経過しても、任意のキーを押した後、addresses 2は任意に2つのIPアドレス(192.168.18.10と192.168.18.20)を得たことがわかります.あ、しかもaddresses 2の時間は0ミリ秒であるが、このとき192.168.18.20は既に削除されている.従って、addresses 2はDNSキャッシュから得られたデータであると判断できる.以下のコマンドを実行し、5秒後に任意のキーを押して続行すると、addresses 2はIPアドレスが1つしか残っていない(192.168.18.10).java mynet.MyDNS ComputerName 5ドメイン名がDNSサーバ上に存在しない場合、クライアントは一定時間の試行後(平均5秒)を選択すると、UnknownHostException例外が放出されます.DNSキャッシュは、次のドメイン名へのアクセス時に待機しないように、このエラーメッセージも保存します.つまり、エラードメイン名へのアクセスは、最初のアクセス時のみ5回程度の試行を行い、後でこのドメイン名へのアクセス時には、5秒も待たずにUnknownHostException例外を直接放出します名前が失敗した原因は、このドメイン名が本当に存在しないか、DNSサーバまたは他のハードウェアまたはソフトウェアの一時的な障害のためである可能性があるため、一般的にこのドメイン名エラー情報を常に保持することはできません.Javaではnetworkaddress.cache.negative.ttlプロパティでこれらの情報を保持する時間を設定できます.このプロパティのデフォルト値は10秒です.jAVa.security.Security.setPropertyメソッドまたはjava.securityファイルで設定します.次のコードでは、networkaddress.cache.negative.ttlプロパティの使用方法を示します.
上のコードでnetworkaddress.cache.negative.ttl属性値を5秒に設定します.このプログラムでは、address 1とaddress 2がwww.ppp 123.com(存在しないドメイン名です.読者は存在しないドメイン名に変更できます)にアクセスした後、UnknownHostException異常をどのくらい投げ出したかをテストしました.実行結果:www.ppp 123.comは存在しません!address 1: 4688ミリ秒www.ppp 123.comは存在しません!address 2: 0ミリ秒 以上の実行結果から、address 2は0ミリ秒を使用して異常を放出していることが分かるので、address 2はDNSキャッシュからドメイン名www.ppp 123.comがアクセスできない情報を得ていると判断し、そのままUnknowHostException異常を放出している.上面コードの遅延コードの注釈を外すと、www.ppp123.comは存在しません!address 1: 4688ミリ秒www.ppp 123.comは存在しません!address 1: 4420 ms上記の実行結果から分かるように、6秒目にDNSキャッシュ内のデータが解放されたため、address 2はDNSサーバにアクセスする必要があり、www.ppp 123.comがアクセスできないドメイン名であることを知ることができる.DNSキャッシュを使用する場合、2つの点に注意する必要がある:1.実際の状況に応じてnetworkaddress.cache.ttl属性の値を設定することができる.一般的にこの属性はの値を-1に設定します.ただし、動的にマッピングされたドメイン名にアクセスしている場合(動的ドメイン名サービスを使用してドメイン名をADSLの動的IPにマッピングするなど)2.networkaddress.cache.negative.ttl属性値を設定するときは-1にしないほうがいい.そうしないと、一時的な障害でドメイン名にアクセスできない場合、プログラムがこのドメイン名に再アクセスするとき、このドメイン名が正常に戻っても、プログラムはこのドメインにアクセスできない名前です.プログラムを再実行しない限り.
java.security.Security.setProperty("networkaddress.cache.ttl", 10);
2.java.securityファイルのnetworkaddress.cache.negative.ttlプロパティを設定します.JDKのインストールディレクトリがC:jdk 1.6であると仮定すると、java.securityファイルはc:jdk 1.6jrelibsecurityディレクトリにあります.このファイルを開き、networkaddress.cache.ttlプロパティを見つけ、このプロパティ値を対応するキャッシュタイムアウト(秒単位)に設定します.networkaddress.cache.ttlプロパティ値を-1に設定すると、DNSキャッシュデータは解放されません.次のコードでは、DNSキャッシュを使用するか使用しないかの効果を示します.
package mynet;
import java.net.*;
public
class MyDNS
{
public
static
void main(String[] args) throws Exception
{
// args[0]: args[1]:
if (args.length <
2)
return;
java.security.Security.setProperty("networkaddress.cache.ttl", args[1]);
long time = System.currentTimeMillis();
InetAddress addresses1[] = InetAddress.getAllByName(args[0]);
System.out.println("addresses1: "
+ String.valueOf(System.currentTimeMillis() - time)
+
" ");
for (InetAddress address : addresses1)
System.out.println(address);
System.out.print(" ");
System.in.read();
time = System.currentTimeMillis();
InetAddress addresses2[] = InetAddress.getAllByName(args[0]);
System.out.println("addresses2: "
+ String.valueOf(System.currentTimeMillis() - time)
+
" ");
for (InetAddress address : addresses2)
System.out.println(address);
}
}
上記のコードにはDNSキャッシュタイムアウト(args[1]パラメータを介して)が設定されており、ユーザはコマンドラインパラメータを介してこの値をMyDNSに転送することができる.このプログラムはまずgetAllByNameを使用してInetAddress配列を作成し、System.in.readを使用してプログラムを一時停止します.ユーザがしばらく待つと、任意のキーを押して続行し、同じドメイン名(args[0])を使用してInetAddress配列を再構築できます.DNSキャッシュのタイムアウトよりもユーザが待機している時間が小さい場合、addresses 2とaddresses 1配列の要素は同じであり、addresses 2配列を作成するのにかかる時間は一般的に0ミリ秒(1ミリ秒未満ではJavaはより正確な時間を得ることができない)である.テスト1:DNSキャッシュタイムアウトを5秒に設定するコマンドを実行します:java mynet.MyDNS www.126.com 5実行結果1(5秒以内に任意のキーを押す):addresses 1: 344 ms www.126.com/202.108.9.77任意のキーを押してaddresses 2を続行 0 ms www.126.com/202.108.9.77実行結果2(5秒後に任意のキーを押す):addresses 1: 344 ms www.126.com/202.108.9.77任意のキーを押してaddresses 2を続行 484ミリ秒www.126.com/202.108.9.77は、上記のテストで2つの実行結果が表示される可能性があります.「任意のキーを押して続行...」が表示された後、5秒以内に任意のキーを押して続行すると、実行結果1が得られます.この結果から、addresses 2が使用する時間は0ミリ秒です.つまり、addresses 2はDNSサーバに実際にアクセスするのではなく、メモリ内のDNSから直接キャッシュされたデータです.5秒後に任意のキーを押して続行すると、実行結果2が得られ、メモリ内のDNSキャッシュのデータが解放されるので、addresses 2はDNSサーバに再アクセスする必要があるため、addresses 2の時間は484ミリ秒である(addresses 1とaddresses 2の後のミリ秒数は異なる環境で異なる場合がありますが、一般的には、実行結果1のaddresses 2の値は0または5のような0に近い数です.実行結果2のaddresses 2の値は、一般的にaddresses 1の値に近いか、1200のような0よりはるかに大きい数です).テスト2:次のコマンドを実行します.(ComputerNameはネイティブのコンピュータ名、DNSキャッシュタイムアウトは期限切れに設定されています[-1]):java mynet.MyDNS ComputerName-1実行結果(任意のキーで続行する前に192.168.18.20を削除):addresses 1: 31 ms myuniverse/192.168.18.10 myuniverse/192.168.18.20任意のキーを押してaddresses 2を続行 0ミリ秒myuniverse/192.168.18.10 myuniverse/192.168.18.20 上記のテストから、DNSキャッシュを無期限に設定した後、どのくらいの時間が経過しても、任意のキーを押した後、addresses 2は任意に2つのIPアドレス(192.168.18.10と192.168.18.20)を得たことがわかります.あ、しかもaddresses 2の時間は0ミリ秒であるが、このとき192.168.18.20は既に削除されている.従って、addresses 2はDNSキャッシュから得られたデータであると判断できる.以下のコマンドを実行し、5秒後に任意のキーを押して続行すると、addresses 2はIPアドレスが1つしか残っていない(192.168.18.10).java mynet.MyDNS ComputerName 5ドメイン名がDNSサーバ上に存在しない場合、クライアントは一定時間の試行後(平均5秒)を選択すると、UnknownHostException例外が放出されます.DNSキャッシュは、次のドメイン名へのアクセス時に待機しないように、このエラーメッセージも保存します.つまり、エラードメイン名へのアクセスは、最初のアクセス時のみ5回程度の試行を行い、後でこのドメイン名へのアクセス時には、5秒も待たずにUnknownHostException例外を直接放出します名前が失敗した原因は、このドメイン名が本当に存在しないか、DNSサーバまたは他のハードウェアまたはソフトウェアの一時的な障害のためである可能性があるため、一般的にこのドメイン名エラー情報を常に保持することはできません.Javaではnetworkaddress.cache.negative.ttlプロパティでこれらの情報を保持する時間を設定できます.このプロパティのデフォルト値は10秒です.jAVa.security.Security.setPropertyメソッドまたはjava.securityファイルで設定します.次のコードでは、networkaddress.cache.negative.ttlプロパティの使用方法を示します.
package mynet;
import java.net.*;
public
class MyDNS1
{
public
static
void main(String[] args) throws Exception
{
java.security.Security.setProperty("networkaddress.cache.negative.ttl",
"5");
long time =
0;
try
{
time = System.currentTimeMillis();
InetAddress.getByName("www.ppp123.com");
}
catch (Exception e)
{
System.out.println("www.ppp123.com ! address1: "
+ String.valueOf(System.currentTimeMillis() - time)
+
" ");
}
//Thread.sleep(6000); // 6
try
{
time = System.currentTimeMillis();
InetAddress.getByName("www.ppp123.com");
}
catch (Exception e)
{
System.out.println("www.ppp123.com ! address2: "
+ String.valueOf(System.currentTimeMillis() - time)
+
" ");
}
}
}
上のコードでnetworkaddress.cache.negative.ttl属性値を5秒に設定します.このプログラムでは、address 1とaddress 2がwww.ppp 123.com(存在しないドメイン名です.読者は存在しないドメイン名に変更できます)にアクセスした後、UnknownHostException異常をどのくらい投げ出したかをテストしました.実行結果:www.ppp 123.comは存在しません!address 1: 4688ミリ秒www.ppp 123.comは存在しません!address 2: 0ミリ秒 以上の実行結果から、address 2は0ミリ秒を使用して異常を放出していることが分かるので、address 2はDNSキャッシュからドメイン名www.ppp 123.comがアクセスできない情報を得ていると判断し、そのままUnknowHostException異常を放出している.上面コードの遅延コードの注釈を外すと、www.ppp123.comは存在しません!address 1: 4688ミリ秒www.ppp 123.comは存在しません!address 1: 4420 ms上記の実行結果から分かるように、6秒目にDNSキャッシュ内のデータが解放されたため、address 2はDNSサーバにアクセスする必要があり、www.ppp 123.comがアクセスできないドメイン名であることを知ることができる.DNSキャッシュを使用する場合、2つの点に注意する必要がある:1.実際の状況に応じてnetworkaddress.cache.ttl属性の値を設定することができる.一般的にこの属性はの値を-1に設定します.ただし、動的にマッピングされたドメイン名にアクセスしている場合(動的ドメイン名サービスを使用してドメイン名をADSLの動的IPにマッピングするなど)2.networkaddress.cache.negative.ttl属性値を設定するときは-1にしないほうがいい.そうしないと、一時的な障害でドメイン名にアクセスできない場合、プログラムがこのドメイン名に再アクセスするとき、このドメイン名が正常に戻っても、プログラムはこのドメインにアクセスできない名前です.プログラムを再実行しない限り.