java DNS TTL 설정 - 코드로 동작 확인하기

    배경 - DNS 기반 redundancy layer

    DNS에 여러 A 레코드를 두고, DNS lookup을 하면 그 중 하나의 A 레코드를 반환하도록 한다. 이렇게 하여 서비스의 부하 분산, 지역 분산 및 혹시 모를 장애 대비도 할 수 있다. 그런데, DNS에 기반한 위 가정에 맞추려면, java 애플리케이션의 경우 꼭 챙겨야 하는 설정이 있다.


    DNS Client Cache 설정

    어떤 URL이 주어지면, DNS에 대한 질의를 하고자 하는 클라이언트와 그에 대한 답을 하는 서버로 역할이 나눠진다. 실행하는 자바 애플리케이션이 어떤 주소를 확인하기 위해 매번 DNS 질의를 해야 한다면 (아무리 패킷이 작더라도) 그만큼 네트워크 비용이 발생하기 때문에, 주소가 자주 바뀌지 않는다면 호출하는 빈도를 줄이는 것이 더 효과적일 것이다. 따라서, 이 빈도를 줄이기 위해 캐시를 하게 된다. 그러나, 캐시 갱신의 주기가 도래하지 않으면 유효성 확인을 하지 않기 때문에, 그 주기내에 원본 주소에 문제가 생긴다면 그만큼 인지하는데 오래 걸릴 수 밖에 없다.


    JVM 설정 확인

    JVM에서의 환경 설정은 $JAVA_HOME/jre/lib/security/java.security를 확인해 보자.

    networkaddress.cache.ttl=60

    와 같은 설정을 볼 수 있을 것이다. 즉 위와 같이 기록이 되어 있다면 TTL은 60초이고, 한번 DNS 질의를 하면 60초간은 믿고 쓴다는 뜻이다.


    테스트

    다음의 java 코드로 확인할 수 있다. 코드의 기본 골격은 제외하고 주요 부분만 인용하면 다음과 같다.

    java 코드

    Logger logger = Logger.getGlobal();
    while (true) {
        try {
            InetAddress inetHost = InetAddress.getByName("test.luran.me");
            logger.info("IP address: " + inetHost.getHostAddress());
            Thread.sleep(1000);
    
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    위의 코드는 test.luran.me의 주소를 1초마다 질의를 하고, 그 DNS 레코드에 매핑되는 IP 주소를 리턴하도록 하였다.

    환경 설정 - DNS record 변경 상황 가정

    $ cat /etc/hosts
    
    127.0.0.1    test.luran.me
    # 127.0.0.5   test.luran.me

    DNS 서버를 쓰는 대신, 간편하게 /etc/hosts에 설정을 변경하여 테스트 해본다. 두 개의 레코드를 선언해 놓고, test.luran.me가 처음에는 127.0.0.1을 가리키게 했다가, 127.0.0.5로 변경되는 방식으로 테스트 하고자 한다.

    파일편집을 위해 다음의 커맨드를 활용한다.

    sudo vi /etc/hosts

    vi로 편집했으므로, 저장할 때는 esc를 누른 후, :wq!를 입력하면 된다.


    테스트 방법

    위의 java코드를 실행하면, while loop이 계속 돌게 되는데, 일정 시간이 경과한 후 /etc/hosts에 선언된 내용 즉, test.luran.me에 매핑된 IP를 변경 저장하고 java 프로그램이 변경된 주소를 인지하게 되는지를 확인하면 된다.


    TTL 변경 방법

    JVM의 TTL을 변경하려면 다음 세 가지 방법 중 하나를 적용하면 된다. 그 중, JVM option 사용 방법을 추천한다.

    외부 설정

    앞서 언급한 $JAVA_HOME/jre/lib/security/java.security 파일내 설정값을 변경한다. 단, 이 값을 변경하면 JVM을 사용하는 애플리케이션이 모두 영향을 받게 된다.

    networkaddress.cache.ttl=5

    프로그램내 선언

    대안으로, 이 값을 애플리케이션에 선언할 수 있다. 자바 프로그램 내부에 다음의 코드를 기록하자.

    Security.setProperty("networkaddress.cache.ttl", "5");

    이렇게 되면, 해당 애플리케이션 내에서는 TTL이 5초로 동작한다. 대신, 선언을 누락하거나 놓칠 가능성이 있다. 그리고, 변경하기 어렵다. (빠뜨리거나, 어디에 있는지 기억하거나 찾기 어려움)

    JVM option으로 설정

    자바 애플리케이션을 실행할 때, JVM Option으로 지정하는 방법이다. 이 방식을 사용하면 관리하거나 변경하기 보다 용이하다.

    -Dsun.net.inetaddr.ttl=5

    자바 애플리케이션을 실행할 때, 이 옵션을 부여하면 위의 설정값을 override 하여, 동일한 효과가 발효된다.


    결과 비교

    테스트의 용이성을 위해, 두 번째 방법 혹은 세 번째 방법으로 테스트를 하면 되겠다. 만약, 두 번째 방법(프로그램내 선언)을 사용한다면,

    Logger logger = Logger.getGlobal();
    Security.setProperty("networkaddress.cache.ttl", "5");
    
    while (true) {
        try {
            InetAddress inetHost = InetAddress.getByName("test.luran.me");
            logger.info("IP address: " + inetHost.getHostAddress());
            Thread.sleep(1000);
    
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    와 같이 변경하면 된다. 세 번째 방법(JVM option)을 사용한다면, 코드는 그대로 유지하되 Runtime 옵션에 다음과 같이 설정하면 된다.

    적용 전 (11:56:40에 주소 변경)

    3월 19, 2021 11:56:40 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:41 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:42 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:43 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:44 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:45 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:46 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:47 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:48 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:49 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:50 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:51 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:52 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:53 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:56:54 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.5
    3월 19, 2021 11:56:55 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.5
    3월 19, 2021 11:56:56 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.5
    3월 1

    적용 후 (11:53:10에 주소 변경)

    3월 19, 2021 11:53:10 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.5
    3월 19, 2021 11:53:11 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.5
    3월 19, 2021 11:53:12 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.5
    3월 19, 2021 11:53:13 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.5
    3월 19, 2021 11:53:14 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.5
    3월 19, 2021 11:53:15 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:53:16 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:53:17 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:53:18 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:53:19 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:53:20 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:53:21 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1
    3월 19, 2021 11:53:22 오후 com.luran.spocksetupexample.DnsLookupTest main
    정보: IP address: 127.0.0.1

    맺음말

    위의 결과에서 보았듯이, 해당 옵션을 지정해야 DNS 주소 변경시 인지를 빨리한다. DB의 엔드포인트가 AWS RDS/Aurora와 같이 DNS로 제어되는 경우라면, 위의 옵션 적용을 꼭 검토하자. DB Failover시 필수 옵션이다. 최악의 경우, JVM의 DNS Cache TTL이 무한대로 설정되어 있는 상황에서, 마스터 서버 주소가 바뀌었는데 DNS Cache가 갱신이 되지 않으면 JVM을 재시작하기 전까지 옛주소에 접속하려 할 것이기 때문이다.

    댓글(0)

    Designed by JB FACTORY