Globale DNS-Auflösung durch Verzicht auf CNAMES beschleunigen
Wie beispielsweise in meinem Artikel “Ein eigenes kleines CDN für meine Mastodon Instanz metalhead.club” gezeigt, nutze ich gerne CNAMEs, um meine DNS-Einträge zu organisieren. Üblicherweise lege ich für jeden Host einen DNS-Record an, der seinen Hostnamen auf die IP mappt. Dann verwende ich einen oder mehrere CNAME-Einträge, um gewisse (Sub-) Domains je nach Dienst und Verwendungszweck auf diese CNAMES zu verlinken. Das hilft bei der Übersicht und kann die Organisation erleichtern - vor allem, wenn einmal IP-Adressen für Hosts ausgetauscht werden müssen. Dank der Verkettung der Einträge muss nur das letzte Mapping von Server-Hostname zu IP angepasst werden, wenn die IP-Adresse des Zielhosts sich einmal ändern sollte.
Anhand des Beispiels aus dem vorher erwähnten Artikel kann eine CNAME-Kette beispielsweise so aussehen:
[thomas@thomas-nb]~% dig media.metalhead.club
;; ANSWER SECTION:
media.metalhead.club. 1800 IN CNAME metalheadclub-media.cdn.650thz.de.
metalheadclub-media.cdn.650thz.de. 21600 IN CNAME s3.650thz.de.
s3.650thz.de. 3600 IN A 5.1.72.141
Es wird also zunächst media.metalhead.club aufgelöst, dann metalheadclub-media.cdn.650thz.de und schließlich s3.650thz.de. Erst dann steht die IP-Adresse für den Zielhost fest. Das gefällt mir im Sinne der Ordnung, weil die Gliederung für mich im Kopf Sinn ergibt. Wie ich allerdings bei der Analyse meines kleinen CDNs für metalhead.club feststellen müsste, ist das für die Performance nicht besonders förderlich. Denn der Gebrauch von CNAMES hat aber auch einen bedeutenden Nachteil: Die Zeit für eine DNS-Auflösung verlängert sich mit jedem CNAME in der Kette bis zur IP-Adresse.
Allein die Auflösung der zweiten Zeile aus der “Answer Section” bedeutet beispielsweise: Erst .de auflösen (DNS-Rootserver befragen), dann .de Nameserver nach 650thz.de befragen, dann 650thz.de Nameserver nach cdn befragen, schließlich die cdn-Nameserver nach metalhead.club-media befragen. Erst dann steht fest: Es muss s3.650thz.de aufgelöst werden. Das Spiel beginnt erneut, bis am Ende schließlich die IP-Adresse feststeht.
Es dürfte klar sein, dass diese Kette aus zwei CNAME-Einträgen durchaus Zeit braucht, bis sie vom DNS-Resolver des Nutzers aufgelöst ist. Für regionale Nutzer, die sich in Reichweite dieser Nameserver befinden, fällt der Aufwand nicht so sehr ins Gewicht, da das Auflösen jedes Kettenglieds in der Regel nur einige zehntel Millisekunden braucht.
Anders sieht es aber für Nutzer aus, die (wie im Fall des metalhead.club) beispielsweise aus den USA oder aus Australien auf Nameserver in Europa zugreifen müssen. Denn:
- Rootserver: Global
- .de-Nameserver: Global
- 650thz.de: Regional, EU
- cdn.650thz.de: Regional, EU
In meiner Kette sind 4 Zonen auf 4 (virtuellen) Nameservern involviert. Jeder muss einzeln befragt werden und nur zwei davon sind global aufgestellt, d.h. sie sind weltweit mit minimalen Latenzzeiten erreichbar. Alle regionalen Server sind für alle, die sich nicht in der EU aufhalten, nur mit deutlich erhöhten Laufzeiten erreichbar. Dass gleich 2x (aus ihrer Sicht “langsame”) regionale DNS-Nameserver im Fall eines US-Nutzers abgefragt werden müssen, sorgt dann dafür, dass sich die erhöhten Latenzen sehr schnell aufaddieren.
Aus Sicht eines US-Nutzers oder eines Nutzers aus Asien ist es also besonders wichtig, dass Auflösungsketten möglichst kurz gehalten werden. Besonders deutlich wird das Bild, wenn man ein Tool wie z.B. globalping.io nutzt und sich die globalen Auflösungszeiten im DNS-Modus einmal ansieht:
Während EU-Nutzer media.metalhead.club (im Screenshot media-old.metalhead.club) nach etwa 0,004 - 0,070 Sekunden aufgelöst bekommen, muss sich ein Japaner deutlich länger gedulden: Nämlich ca 1,5 Sekunden! Erst dann kann sein Browser anfangen, Kontakt zum endgültigen Zielserver aufzunehmen.
Das gilt selbstverständlich nur für die erste DNS-Anfrage nach Ablauf der TTL. Kurz darauf folgende Anfragen werden vom DNS-Resolver üblicherweise aus dem Cache beantwortet, sodass diese um Größenordnungen schneller beantwortet werden. Nach Ablauf der TTL dauert der erste Request allerdings wieder 1,5 Sekunden! Allerdings kann bei den wenigen Nutzern in einigen Regionen nicht angenommen werden, dass diese einen gemeinsamen DNS-Resolver nutzen. Daher ist es mir wichtig, dass auch ungecachte Requests zügig beantwortet werden.
Also habe ich mich entschieden, Auf CNAME-Ketten ganz zu verzichten. Und das ging so:
- In der metalhead.club Zone habe ich die Subdomain media.metalhead.club direkt an den GeoIP-Nameserver von Scaleway delegiert
- Der Scaleway-Nameserver löst dann direkt zu einer IP-Adresse auf, die zur Region des Nutzers passt
Es sind also keine CNAMEs mehr an der Auflösung beteiligt: Die gesamte Auflösung basiert nur noch auf Zonendelegation.
Das Ganze ließe sich durch folgende Maßnahmen nochmal verbessern:
- Keine Trennung von “normalem” DNS-Nameserver (Core-Networks.de) und GeoIP Nameserver (Scaleway): Dann könnte auf die “media”-Zonendelegation verzichtet werden
- Globale Erreichbarkeit aller Nameserver (ist allerdings ein nicht unbedeutender Kostenfaktor, außerdem neuer DNS-Anbieter erforderlich)
Aber auch ohne diese beiden Verbesserungen konnte ich alleine durch den Verzicht auf CNAMES auf Auflösungszeit deutlich verkürzen, wie dieser Screenshot zeigt:
Das ist doch schon viel besser: Nach der Optimierung durch Verzicht auf CNAMES dauert die Auflösung von media.metalhead.club in diesem Fall nur noch rund 0,7 Sekunden statt 1,9 Sekunden!
Übrigens: Die Hauptdomain metalhead.club löst technisch bedingt sowieso gleich auf IP-Adressen auf. Hier ist keine Optimierung nötig gewesen.