#はじめに
こんにちは、黒糖と申します。
ブログ(https://kokutoh.com/?p=187)
に書いた内容と同じですが、同じ轍を踏まないようにQiitaにも書いて、供養したいと思います。
日々、システムエンジニアとして、とあるECサイトの保守・運用業務を担っております。
※環境としては、一般的な構成(FW、SSLアクセラレータ、LB、Web(AP)サーバ複数台、DBサーバ)で
アプリケーションのミドルウェアはWebshere Application Server 8系
Web(API)サーバのOSはRedhat7、Java1.7です。
先日、他社様とのWEB API 部分で、通信に失敗し、
試行錯誤した末に、復帰することができましたので、備忘の意味も込めて、残しておきます。
#原因?
結論から申しましょう。
原因としては、APIを受ける他社様サーバはAWS上に構築されており、IPアドレスが可変であったことです。
#でも、ちょっと待って・・・
ただ、そのAPIにリクエストを送信するWEB サーバから参照しているDNSサーバは、
他社様指定のもので、名前解決の結果、もちろん可変後(変更後)のIPアドレスをしっかりと返してくれておりました。
つまり、WEBサーバから、当該APIのFQDNで、nslookupコマンドを使用すると、何の問題もなく、現在のIPアドレスが返却されていたのです。
では、なぜJavaアプリケーションからだと急に通信に失敗するようになったか。
(ちなみにFWのポリシー設定では、FQDNで許可設定を入れているので、該当のNWには出れていました。)
#本当の原因!!
実はJava7では、デフォルトのDNSキャッシュ設定が、TTL=-1 つまり永続的にキャッシュするという設定が入っております。
これにより、APIを受けるサーバのIPが変わっても、以前に通信成功した時のIPアドレスに向けてリクエストを送信、
結果として該当のサーバは存在していない(もしかしたら存在するかもしれないが、該当のAPIはそのサーバには存在しない)ので、
通信に失敗したということです。
#改善するには
対策としては、上記のJVM側のDNSキャッシュをTTL=0(無効)に設定することで、
都度都度、DNSサーバで名前解決をするようになり改善されました。
#今後は・・・
教訓として、通信が不通になってしまった場合、FWの設定に目を向けがちですが、JVMの設定に目を向けるのも大切だということです。
(ひょっとするとTomcatやWebShereにもそのような設定が可能かもしれないので、そこも今後は調査対象とすべきです。)
#おわりに
AWS上で構築されているサーバとの通信が不通になった場合は、上記お試しいただけるとよろしいかと。
(JVMのDNSキャッシュ設定は、java.securityというファイルを書き換えることで可能です。
詳細な場所とかはググれば死ぬほど出てくるので割愛します。)
以上です。