Hallo!
Hallo zusammen, ich bin Nikita – Systemingenieur bei SEMrush. Mit diesem Artikel setze ich die Geschichte fort, wie wir eine Lösung für die Chinesische Firewall für unseren Dienst semrush.com entwickelt haben.
In Ich habe erzählt:
- welche Probleme auftreten, nachdem die Entscheidung getroffen wurde, "Unser Service muss in China funktionieren"
- welche Herausforderungen es im chinesischen Internet gibt
- warum eine ICP-Lizenz notwendig ist
- wie und warum wir beschlossen haben, unsere Testumgebungen mit Catchpoint zu testen
- welches Ergebnis unsere erste Lösung brachte, die auf dem Cloudflare China Network basiert
- wie wir einen Fehler im DNS von Cloudflare gefunden haben.
Dieser Teil ist meiner Meinung nach der interessanteste, da er sich auf spezifische technische Implementierungen der Staging-Umgebungen konzentriert. Lassen Sie uns beginnen, oder besser gesagt, fortfahren mit Alibaba Cloud.
Alibaba Cloud
Alibaba Cloud — ein ziemlich großer Cloud-Anbieter, der alle Dienste bietet, um sich ehrlich als Cloud-Anbieter zu bezeichnen. Es ist gut, dass ausländische Benutzer die Möglichkeit haben, sich anzumelden, und dass der Großteil der Website ins Englische übersetzt ist (was für China eine Seltenheit ist). In dieser Cloud kann man in zahlreichen Regionen der Welt, im Festland-China sowie im asiatisch-pazifischen Raum (Hongkong, Taiwan usw.) arbeiten.
IPSEC
Wir begannen mit der Geografie. Da unsere Testwebsite auf Google Cloud gehostet wurde, mussten wir Alibaba Cloud mit GCP "verbinden". Daher öffneten wir die Liste der Standorte, in denen Google präsent ist. Zu diesem Zeitpunkt hatte Google noch kein eigenes Rechenzentrum in Hongkong.
Die nächstgelegene Region war asia-east1 (Taiwan). Für Alibaba war die am nächsten gelegene Region des Festlandes-China zu Taiwan cn-shenzhen (Shenzhen).
Mit terraform Wir haben die gesamte Infrastruktur in GCP und Ali eingerichtet. Der Tunnel mit 100 Mbit/s zwischen den Clouds wurde nahezu sofort hochgefahren. In Shenzhen und Taiwan wurden Proxy-VMs bereitgestellt. In Shenzhen wird der Benutzertraffic terminieren und über den Tunnel nach Taiwan proxiert, von wo er direkt auf die externe IP unseres Services in us-east (Ostküste der USA). Der Ping zwischen den VMs über den Tunnel 24ms, was nicht schlecht ist.
Gleichzeitig haben wir eine Testzone in Alibaba Cloud DNS. Nach der Delegation der Zone an die NS von Ali sank die Auflösungszeit von 470 ms auf 50 ms. Zuvor war die Zone ebenfalls bei Cloudflare.
Parallel zum Tunnel nach asia-east1 wurden noch ein Tunnel direkt von Shenzhen nach us-east4eingerrichtet. Dort wurden weitere Proxy-VMs erstellt und beide Lösungen getestet, indem wir den Testtraffic mithilfe von Cookies oder DNS routeten. Der schematische Teststand ist im nächsten Bild dargestellt:
Die Latenz für die Tunnel war wie folgt:
Ali cn-shenzhen <—> GCP asia-east1 — 24ms
Ali cn-shenzhen <—> GCP us-east4 — 200ms
Die Browser-Tests von Catchpoint berichteten von hervorragenden Verbesserungen der Kennzahlen.
Vergleichen Sie die Testergebnisse für die beiden Lösungen:
Lösung
Verfügbarkeit
Median
75. Perzentil
95. Perzentil
Cloudflare
86.6
18s
30s
60s
IPsec
99.79
18s
21s
30s
Dies sind die Daten der Lösung, die einen IPSEC-Tunnel über asia-east1. Über us-east4 waren die Ergebnisse schlechter und es gab mehr Fehler, daher werde ich die Ergebnisse nicht anführen.
Die Ergebnisse dieses Tests von zwei Tunnel, von denen einer in der Nähe von China endet und der andere am endgültigen Ziel, zeigen, dass es wichtig ist, so schnell wie möglich unter der chinesischen Firewall 'herauszukommen' und dann schnelle Netzwerke (CDN-Anbieter, Cloud-Anbieter usw.) zu nutzen. Man sollte nicht versuchen, die Firewall auf einmal zu durchdringen und direkt zum Ziel zu gelangen. Das ist nicht der schnellste Weg.
Insgesamt sind die Ergebnisse gut, jedoch beträgt die Medianzeit bei semrush.com 8,8 s und der 75. Perzentil 9,4 s (bei demselben Test).
Und bevor wir weitermachen, möchte ich einen kleinen Abschweifer machen.
Abschweifer
Nachdem der Benutzer die Website www.semrushchina.cn, die über 'schnelle' chinesische DNS-Server aufgelöst wird, aufruft, läuft die HTTP-Anfrage über unsere schnelle Lösung. Die Antwort wird auf demselben Weg zurückgegeben, aber in allen JS-Skripten, HTML-Seiten und anderen Elementen der Webseite ist die Domain semrush.com für zusätzliche Ressourcen, die beim Rendern der Seite geladen werden müssen. Das bedeutet, der Client löst den „hauptsächlichen“ A-Eintrag auf www.semrushchina.cund geht in einen schnellen Tunnel, erhält schnell die Antwort — die HTML-Seite, auf der steht:
- lade dieses spezielle js von sso.semrush.com,
- hole die CSS-Dateien von cdn.semrush.com,
- und nimm auch Bilder von dab.semrush.com
- usw.
Der Browser beginnt, ins „externe“ Internet nach diesen Ressourcen zu gehen, wobei er jedes Mal durch die zeitaufwendige Antwort des Firewalls navigiert.
Im vorherigen Test wurden jedoch Ergebnisse präsentiert, bei denen auf der Seite keine Ressourcen vorhanden sind. semrush.com, nur semrushchina.cn, während *.semrushchina.cn in die Adresse einer virtuellen Maschine in Shenzhen aufgelöst wird, um dann in den Tunnel zu gelangen.
Nur so, indem man maximal den gesamten möglichen Traffic durch seine Lösung zum schnellen Durchgang des chinesischen Firewalls leitet, kann man akzeptable Geschwindigkeiten und Verfügbarkeitskennzahlen der Website sowie ehrliche Testergebnisse der Lösungen erhalten.
Wir haben dies ohne eine einzige Codeänderung auf der Seite der Produktteams geschafft.
Subfilter
Die Lösung entstand praktisch sofort nach dem Auftreten dieses Problems. Wir benötigten PoC (Proof of Concept), dass unsere Firewall-Lösungen tatsächlich effektiv arbeiten. Dafür muss der gesamte Traffic der Website in diese Lösung eingebunden werden. Und wir haben in nginx angewendet.
Subfilter — das ist ein recht einfaches Modul in nginx, das eine Zeile im Antworttext gegen eine andere umtauschen kann. Hier haben wir also alle Vorkommen semrush.com findet man semrushchina.cn in allen Antworten geändert.
Und… das hat nicht funktioniert, da wir von den Backends komprimierte Inhalte erhalten haben, sodass der subfilter die benötigte Zeile nicht fand. Wir mussten einen weiteren lokalen Server in nginx hinzufügen, der die Antwort dekomprimierte und sie an den nächsten lokalen Server weitergab, der dann für den Austausch der Zeile, die Komprimierung und die Übergabe an den nächsten Proxy-Server in der Kette zuständig war.
Letztendlich hätte der Kunde erhalten .semrush.com, aber er erhielt .semrushchina.cn und wurde ordnungsgemäß durch unsere Lösung geleitet.
Es reicht jedoch nicht aus, die Domain nur in eine Richtung zu ändern, denn die Backends erwarten weiterhin semrush.com in den folgenden Anfragen des Kunden. Folglich erhalten wir auf demselben Server, auf dem die Umstellung in eine Richtung erfolgt, mithilfe eines einfachen regulären Ausdrucks den Subdomain aus der Anfrage und führen dann proxy_pass mit der Variablen $host, die eingestellt ist auf $subdomain.semrush.com. Es mag kompliziert erscheinen, aber es funktioniert. Und es funktioniert gut. Für einzelne Domains, die eine andere Logik erfordern, werden einfach eigene Server-Blöcke erstellt und eine separate Konfiguration vorgenommen. Nachfolgend sind verkürzte Nginx-Konfigurationen zur Veranschaulichung und Demonstration dieses Schemas aufgeführt.
Die folgende Konfiguration verarbeitet alle Anfragen aus China an .semrushchina.cn:
listen 80;
server_name ~^(?<subdomain>[w-]+).semrushchina.cn$;
sub_filter '.semrush.com' '.semrushchina.cn';
sub_filter_last_modified on;
sub_filter_once off;
sub_filter_types *;
gzip on;
gzip_proxied any;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;
location / {
proxy_pass http://127.0.0.1:8083;
proxy_set_header Accept-Encoding "";
proxy_set_header Host $subdomain.semrush.com;
proxy_set_header X-Accept-Encoding $http_accept_encoding;
}
}Diese Konfiguration proxy passt auf localhost auf Port 83, und dort wartet die nächste Konfiguration:
listen 127.0.0.1:8083;
server_name *.semrush.com;
location / {
resolver 8.8.8.8 ipv6=off;
gunzip on;
proxy_pass https://$host;
proxy_set_header Accept-Encoding gzip;
}
}Ich wiederhole, das sind gekürzte Konfigurationen.
So könnte es ungefähr aussehen. Es mag kompliziert erscheinen, aber das ist nur eine Wortfrage. In der Praxis ist alles einfacher als es klingt 🙂
Ende des lyrischen Einschubs
Eine Zeit lang waren wir glücklich, weil sich das Gerücht über ausfallende IPSEC-Tunnel nicht bestätigte. Doch dann begannen die Tunnel zu fallen. Mehrmals am Tag für ein paar Minuten. Nicht viel, aber das war für uns nicht akzeptabel. Da beide Tunnel an einer Router-Seite von Ali terminiert waren, dachten wir, dass es vielleicht ein regionales Problem war und wir ein Backup-Region benötigen.
Wir haben es hochgezogen. Die Tunnel fingen an, zu unterschiedlichen Zeiten auszusetzen, aber unser Failover auf der Upstream-Ebene in Nginx funktionierte hervorragend. Doch dann begannen die Tunnel wieder ungefähr gleichzeitig auszufallen 🙂 Und erneut kamen 502 und 504 Fehler. Die Uptime begann sich zu verschlechtern, also haben wir die Option mit Alibaba CEN (Cloud Enterprise Network) durchdacht.
CEN
CEN stellt die Verbindung zwischen zwei VPCs aus verschiedenen Regionen innerhalb von Alibaba Cloud dar, was bedeutet, dass man private Netzwerke beliebiger Regionen innerhalb der Cloud miteinander verbinden kann. Und das Wichtigste: dieser Kanal hat eine ziemlich strenge SLA. Er ist sowohl in Bezug auf Geschwindigkeit als auch Uptime sehr stabil. Doch es gibt immer einen Haken:
- es ist SEHR schwierig, ihn zu bekommen, wenn Sie kein chinesischer Staatsbürger oder Unternehmen sind,
- man muss für jedes Megabit der Bandbreite des Kanals bezahlen.
Nachdem wir die Möglichkeit bekommen hatten, zu verbinden Festlandchina und Übersee, haben wir ein CEN zwischen zwei Regionen Ali eingerichtet: cn-shenzhen und us-east-1 (der nächstgelegenen Punkt zu us-east4). In Ali us-east-1 haben wir eine weitere Virtuelle Maschine gestartet, um einen weiteren Hop.
Entstanden ist folgendes:
Die Ergebnisse der Browser-Tests sind unten:
Lösung
Verfügbarkeit
Median
75. Perzentil
95. Perzentil
Cloudflare
86.6
18s
30s
60s
IPsec
99.79
18s
21s
30s
CEN
99.75
16s
21s
27s
Die Ergebnisse sind etwas besser als bei IPSEC. Aber über IPSEC kann man potenziell mit 100 Mbit/s laden, während es über CEN nur mit 5 Mbit/s geht und teurer ist.
Ein Hybrid drängt sich auf, nicht wahr? Die Geschwindigkeit von IPSEC mit der Stabilität von CEN zu verbinden.
So haben wir es gemacht, den Verkehr sowohl über IPSEC als auch über CEN im Falle eines Ausfalls des IPSEC-Tunnels laufen zu lassen. Die Verfügbarkeit ist deutlich gestiegen, aber die Ladegeschwindigkeit der Website ließ bisher zu wünschen übrig. Daher habe ich alle Schemas, die wir bereits verwendet und getestet haben, skizziert und beschlossen, ein wenig GCP hinzuzufügen, nämlich GLB.
GLB
GLB — ist (oder Google Cloud Load Balancer). Er bietet uns einen wichtigen Vorteil: Im Kontext des CDN hat er Anycast-IP, was es ermöglicht, den Verkehr ins nächstgelegene Rechenzentrum des Kunden zu routen, wodurch der Verkehr schneller in das schnelle Google-Netzwerk gelangt und weniger über das „gewöhnliche“ Internet läuft.
Ohne lange zu zögern, haben wir HTTP/HTTPS LB in GCP eingerichtet und unsere virtuellen Maschinen mit Subfilter als Backend verwendet.
Es gab mehrere Schema:
- Verwenden Cloudflare China Netzwerk, diesmal aber mit Origin und globalem IP GLB.
- Kunden in cn-shenzhen, und von dort den Verkehr direkt in GLB.
- direkt aus China nach GLB.
- Kunden in cn-shenzhen, von dort proxyieren in asia-east1 über IPSEC (in us-east4 über CEN), und dann zu GLB (keine Sorge, unten gibt es ein Bild und eine Erklärung)
Wir haben all diese Optionen sowie einige hybride Optionen getestet:
- Cloudflare + GLB
Dieses Setup hat uns aufgrund der Uptime und DNS-Fehler nicht überzeugt. Der Test wurde jedoch vor der Bugbehebung seitens CF durchgeführt; möglicherweise ist es jetzt besser (allerdings schließt dies keine HTTP-Timeouts aus).
- Ali + GLB
Dieses Setup hat uns ebenfalls nicht überzeugt, was die Uptime betrifft, da GLB häufig aus dem Upstream fiel, weil eine Verbindung in akzeptabler Zeit oder Timeout nicht möglich war. Für die Server innerhalb Chinas bleibt die GLB-Adresse außerhalb, und somit hinter der chinesischen Firewall. Es gab keine Wunder.
- Nur GLB
Eine Variante, die der vorherigen ähnelt, wobei keine Server in China verwendet wurden: Der Verkehr ging direkt zu GLB (DNS-Einträge wurden geändert). Dementsprechend waren die Ergebnisse unzureichend, da die Situation für normale chinesische Kunden, die Dienste von regulären Internetanbietern nutzen, bei der Überwindung der Firewall deutlich schlechter ist als bei Ali Cloud.
- Shenzhen -> (CEN/IPSEC) -> Proxy -> GLB
Hier haben wir uns entschieden, die besten Merkmale aller Lösungen zu kombinieren:
- Stabilität und garantierten SLA von CEN
- hohe Geschwindigkeit durch IPSEC
- das 'schnelle' Google-Netzwerk und sein Anycast.
Das Schema sieht ungefähr so aus: Der Datenverkehr der Benutzer wird auf einer virtuellen Maschine in ch-shenzhenterminiert. Dort sind Nginx-Upstreams konfiguriert, von denen einige auf private IP-Server verweisen, die sich am anderen Ende des IPSEC-Tunnels befinden, und einige Upstreams auf private Serveradressen auf der anderen Seite von CEN. IPSEC wurde bis zur Region asia-east1 in GCP eingerichtet (es war die nächstgelegene Region zu China zum Zeitpunkt der Erstellung der Lösung. Jetzt gibt es auch GCP-Präsenz in Hongkong). CEN — bis zur Region us-east1 in Ali Cloud.
Anschließend wurde der Datenverkehr von beiden Enden weitergeleitet zu dem Anycast IP GLB,also zum nächstgelegenen Google-Standort, und lief über dessen Netzwerke in die Region us-east4 in GCP, in der die substituierenden virtuellen Maschinen standen (mit Subfilter in Nginx).
Diese hybride Lösung, wie wir erwartet haben, ermöglicht es, die Vorteile jeder Technologie zu nutzen. Insgesamt fließt der Datenverkehr über das schnelle IPSEC, doch wenn Probleme auftreten, entfernen wir diese Server schnell für einige Minuten aus den Upstreams und leiten den Datenverkehr nur über CEN, bis der Tunnel stabilisiert ist.
Nachdem wir die vierte Lösung aus der obigen Liste implementiert haben, haben wir erreicht, was wir wollten und was das Geschäft zu diesem Zeitpunkt von uns verlangt hat.
Ergebnisse der Browser-Tests für die neue Lösung im Vergleich zu vorherigen:
Lösung
Verfügbarkeit
Median
75. Perzentil
95. Perzentil
Cloudflare
86.6
18s
30s
60s
IPsec
99.79
18s
21s
30s
CEN
99.75
16s
21s
27s
CEN/IPsec + GLB
99.79
13s
16s
25s
(CDN
In der von uns implementierten Lösung funktioniert alles gut, nur fehlt ein CDN, das den Traffic auf regionaler und sogar städtischer Ebene beschleunigen könnte. Theoretisch sollte dies die Leistung der Website für Endbenutzer durch die Nutzung schneller Kommunikationskanäle des CDN-Anbieters verbessern. Darüber haben wir die ganze Zeit nachgedacht. Jetzt ist die Zeit für die nächste Iteration des Projekts gekommen: die Suche und das Testen von CDN-Anbietern in China.
Und darüber werde ich euch im nächsten, letzten Teil berichten 🙂
Quelle: habr.com
