aws memo

AWS関連の備忘録 (※本ブログの内容は個人的見解であり、所属組織及び企業の意見を代弁するものではありません。1年以上古いエントリは疑ってかかってください)

AWS: JavaのDNSキャッシュ ( TTL )について

AWSのサービスではDNSを用いて可用性を向上する仕組みを用いている。

  • 各種APIのエンドポイント
  • RDSのエンドポイント
  • ELBのエンドポイント
  • ElastiCacheのエンドポイント
  • CloudSearchのエンドポイント
  • Redshiftのエンドポイント

などなど。AWSが提供するエンドポイントのFQDNを、自分のアプリケーションから参照するように設定したり、一旦DNSでCNAME設定することも多い。

ただし、これらのエンドポイントFQDNで設定されているIPアドレスは、運用中に変更される可能性がある(ノード障害、フェイルオーバー等によるIPアドレス変更、スケーリングによるIPアドレス増減、等)。そのため、アプリケーション側はエンドポイントのIPアドレス変更に追随する必要がある。(追随しないと、古いIPアドレスにアクセス試行しつづけて、結果としてシステム障害になってしまう)

ここで問題になるのがJava (というかJVM)の1.5以前。デフォルトで、一度名前解決したIPアドレスは、JVMが終了するまでキャッシュし、再度名前解決することがないようになっている(キャッシュのttlが-1 となっている)。AWSにアクセスするJavaアプリケーションではこちらが問題になる。

ということで、以下のいずれかを設定しておくことになる。(例としてTTL=60秒)

java.security ファイルに追記。

networkaddress.cache.ttl=60
networkaddress.cache.negative.ttl=1

コードの中に以下を書く

// Set DNS results to be cached for only 1 minute
java.security.Security.setProperty("networkaddress.cache.ttl" , "60");
// Do not cache un-successful name lookups from the DNS
java.security.Security.setProperty("networkaddress.cache.negative.ttl", "1");

JVM起動オプションに追加する

java -Dsun.net.inetaddr.ttl=0 -Dsun.net.inetaddr.negative.ttl=1 -Dxxx=yyy .... com.example.Main

Tomcatの場合

<env>
   <variable name="JAVA_OPTS" value="-Dsun.net.inetaddr.ttl=60 -Dsun.net.inetaddr.negative.ttl=1 -server -Xms512m -Xmx2048m"></variable>
</env>

ちなみに、Java1.6のあるバージョン以降は若干挙動が異なる。以下で確認可能。

sun.net.InetAddressCachePolicy.get()

参考

Setting the JVM TTL for DNS Name Lookups - AWS SDK for Java

Honoring DNS TTLs : Articles & Tutorials : Amazon Web Services

 Networking Properties

InetAddress (Java Platform SE 6)