caffeine-library / system-design-interview

🌱 가상 면접 사례로 배우는 대규모 시스템 설계 기초를 읽는 스터디
4 stars 0 forks source link

[additional] DNS #29

Closed ngwoon closed 2 years ago

ngwoon commented 2 years ago

연관 챕터

26

조사 내용

“책 158pg의 2. 도메인 이름 변환 캐시” 항목에서 “DNS요청의 결과를 받기 전까지는 다음 작업을 진행할 수 없는 것이다” 라는 글귀를 보고, 잘 이해가 되지 않아서 조사하게 되었습니다.

DNS란?

Domain Name System의 약자.

사람이 읽기 쉬운 텍스트 기반 도메인 주소(www.google.com)를 기계가 인식할 수 있는 숫자 기반 주소(172.217.25.4)로 변환해주는 시스템을 의미한다.

DNS Translation Flow

https://media.geeksforgeeks.org/wp-content/uploads/20200822065029/UntitledDiagram.png

우리가 알고 있는 DNS 흐름은 아래와 같다.

면밀히 살펴보는 DNS

1. DNS Translation Flow

브라우저에 www.net.compsci.googleplex.edu 라는 주소를 입력한 상황.

http://www.tcpipguide.com/free/diagrams/dnsresolution.png

Resolver

DNS 와 클라이언트 사이에서 주소 변환 역할을 맡는 컴포넌트.

DNS 클라이언트로부터 DNS 쿼리를 받아서, Name Server에 Recursive Query를 전달하고, 그 응답을 받아 DNS 클라이언트에게 숫자 주소를 반환하는 역할을 한다.

별도의 캐시를 운영할 수 있다.

일반적으로 애플리케이션 레벨에서 구현된다.

Local Name Server

여러 Name Server들 중 Resolver와 직접 통신하는 Name Server.

이 Name Server에서 질의받은 FQDN을 해석할 수 없다면, Root Name Server부터 시작하는 Recursive Query를 수행한다.

별도의 캐시를 운영할 수 있다.

DNS Cache

질의에 대한 응답을 일정 기간 동안 재활용할 수 있도록 저장해두는 공간.

Positive Cache와 Negative Cache가 존재한다.

Positive Cache는 성공한 질의를 보관하고, Negative Cache는 실패한 쿼리를 보관한다.

2. DNS는 항상 UDP?

DNS 질의는 기본적으로 UDP + port 53으로 수행된다.

단, 조금 더 안정성 있는 DNS 운영을 위해 TCP가 사용된다.

3. 그렇다면, 자바에서는 어떻게?

Jsoup이나, RestTemplate 등을 사용하여 Java 애플리케이션에서 다른 서버에 리소스를 요청하는 경우는 흔하다.

이럴 때 DNS resolution이 어떻게 진행될까?

→ JVM의 JNI가 활용된다.

https://blog.kakaocdn.net/dn/P4TIE/btq0Y3DDeQk/y3Mm5hrVWEilFtOjVLX3e1/img.png

JNI Java Native Interface의 약자로 운영체제에 특화되어 있는 기능이나 고성능의 실행을 필요로 하는 모듈을 c/c++과 같은 컴파일 언어로 구현해두고, 이를 자바 애플리케이션에서 호출해 사용하는 방법.

즉, DNS resolution을 수행하는 자바 애플리케이션의 흐름은 다음과 같다.

java.net 패키지의 InetAddress.class를 확인해보면, 아래와 같은 코드를 볼 수 있다.

static {
    String str = java.security.AccessController.doPrivileged(
            new GetPropertyAction("java.net.preferIPv6Addresses"));
    if (str == null) {
        preferIPv6Address = PREFER_IPV4_VALUE;
    } else if (str.equalsIgnoreCase("true")) {
        preferIPv6Address = PREFER_IPV6_VALUE;
    } else if (str.equalsIgnoreCase("false")) {
        preferIPv6Address = PREFER_IPV4_VALUE;
    } else if (str.equalsIgnoreCase("system")) {
        preferIPv6Address = PREFER_SYSTEM_VALUE;
    } else {
        preferIPv6Address = PREFER_IPV4_VALUE;
    }
    AccessController.doPrivileged(
        new java.security.PrivilegedAction<>() {
            public Void run() {
                System.loadLibrary("net"); // 여기!!!!
                return null;
            }
        });

        ...
}

jdk/bin 폴더 내부에 net.dll 파일이 있고, 이 파일 내부에 있는 getAddrInfo(3)함수가 호출됨을 알 수 있다.

이어서 InetAddress.get() 메서드를 살펴보면, 다음과 같은 코드를 볼 수 있다.

@Override
public InetAddress[] get() throws UnknownHostException {
    Addresses addresses;
    // only one thread is doing lookup to name service
    // for particular host at any time.
    synchronized (this) { // 여기!!!!
        // re-check that we are still us + re-install us if slot empty
        addresses = cache.putIfAbsent(host, this);
        if (addresses == null) {
            // this can happen when we were replaced by CachedAddresses in
            // some other thread, then CachedAddresses expired and were
            // removed from cache while we were waiting for lock...
            addresses = this;
        }
        // still us ?
        if (addresses == this) {
            // lookup name services
            InetAddress[] inetAddresses;
            UnknownHostException ex;

                ...
        }
}

주석으로도 친절히 적혀 있듯이, 오직 하나의 쓰레드만 name service lookup 작업을 수행할 수 있다는 것을 알 수 있다.

참고

dns resolver란?

https://jameshfisher.com/2018/02/03/what-does-getaddrinfo-do/

http://www.tcpipguide.com/free/t_DNSNameResolutionProcess-2.htm

https://jameshfisher.com/2018/02/03/what-does-getaddrinfo-do/

c library - getaddrinfo()

https://maheshsenniappan.medium.com/host-name-resolution-in-java-80301fea465a

자바에서의 dns resolution

https://maheshsenniappan.medium.com/host-name-resolution-in-java-80301fea465a

@caffeine-library/readers-system-design-interview

binchoo commented 2 years ago

DNS 서비스

네임서버가 제공하는 도메인 이름 쿼리 서비스입니다. 도메인을 구매할 경우 DNS 레코드를 정의하여 네임서버 동작을 정의할 수 있습니다.

Authoritative DNS 서비스

도메인 구매자가 DNS 레코드를 작성할 수 있는 DNS 서비스.

DNS 레코드

어떤 도메인 네임 질의에 대하여 네임 서버가 반환할 값을 정의하는 자료입니다. 이 값들은 DNS 레코드라고하며, 네임서버 Zone File 내부에 저장됩니다.

반환 값의 특성에 따라 타입이 나뉩니다. 알아둘 몇 가지 레코드 타입은 아래에 적습니다.

DNS 레코드 타입

A 레코드 (address)‍ 해당 도메인 네임에 대해 IPv4 주소로 반환합니다. 다수의 Value를 반환할 경우 클라이언트가 임의 선택하여 사용합니다. Record Name Record Type Value TTL
site.myexample.com A 11.22.33.44 300s

(Domain Registrar에 따라 설정 가능한 요소가 더욱 많을 수 있습니다)

AAAA 레코드 (quad A)
A 타입과 동일하나, IPv6 주소를 반환해야 합니다.

CNAME Record (Canonical Name) FQDN에 대하여 다른 FQDN을 반환합니다. Top Level Domain이 아니어야 합니다. Record Name Record Type Value TTL
www.myexample.com CNAME cname.myexample.com 300s

NS 레코드 (name server) 주어진 도메인이나 서브도메인에 대하여 응답할 책임이 있는 네임 서버들을 반환합니다. Domain Registrar가 관리하는 Second Level Domain 네임서버로 기본 설정이 되었을 것입니다.

Record Name Record Type Value TTL
myexample.com NS ns-252.awsdns-31.com.
ns-1468.awsdns-55.org.
ns-633.awsdns-15.net.
ns-1800.awsdns-33.co.uk.
300s

dig 명령어

도메인 쿼리 후 반환되는 DNS 레코드를 확인해 볼 수 있습니다.

아래 예시는 test.stephanetheteacher.com에 대해 설정된 A 레코드가 내려오는 것을 관찰합니다.

[ec2-user@ip-172-31-1-240 ~]$ dig test.stephanetheteacher.com

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> test.stephanetheteacher.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 42489
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;test.stephanetheteacher.com.INA

;; ANSWER SECTION:
test.stephanetheteacher.com. 104 INA11.22.33.44

;; Query time: 0 msec
;; SERVER: 172.31.0.2#53(172.31.0.2)
;; WHEN: Sun Feb 06 01:19:47 UTC 2022
;; MSG SIZE  rcvd: 72

아래 예시는 myapp.stephanetheteacher.com 에 대해 설정된 CNAME 레코드가 내려오는 것을 관찰합니다.

[ec2-user@ip-172-31-1-240 ~]$ dig myapp.stephanetheteacher.com

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.amzn2.5.2 <<>> myapp.stephanetheteacher.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 7494
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;myapp.stephanetheteacher.com.INA

;; ANSWER SECTION:
myapp.stephanetheteacher.com. 300 INCNAMEdemo-alb-route-53-1648128207.eu-central-1.elb.amazonaws.com.

;; AUTHORITY SECTION:
eu-central-1.elb.amazonaws.com.42 INSOAns-1689.awsdns-19.co.uk. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 60

;; Query time: 11 msec
;; SERVER: 172.31.0.2#53(172.31.0.2)
;; WHEN: Sun Feb 06 01:17:04 UTC 2022
;; MSG SIZE  rcvd: 211

Domain Registrar != DNS 서비스

[참고자료]