Hej!
Det er mig igen, Nikita — systemingeniøren fra virksomheden SEMrush. I denne artikel fortsætter jeg historien om, hvordan vi kom op med en løsning til at omgå den kinesiske brandmur for vores service semrush.com.
I Jeg har allerede fortalt:
- hvilke problemer der opstår, når man beslutter, at "Vi skal have vores service til at fungere i Kina"
- hvilke problemer der findes med det kinesiske internet
- hvorfor man har brug for en ICP-licens
- hvordan og hvorfor vi besluttede at teste vores teststande med Catchpoint
- hvilket resultat vores første løsning, baseret på Cloudflare China Network, gav
- hvordan vi fandt en fejl i DNS Cloudflare
Denne del er den mest interessante, efter min mening, fordi den fokuserer på specifikke tekniske implementeringer af stager. Og vi begynder, eller rettere sagt fortsætter, med Alibaba Cloud.
Alibaba Cloud
Alibaba Cloud — en ret stor cloud-udbyder, der tilbyder alle de tjenester, der gør, at den med rette kan kalde sig en cloud provider. Det er godt, at de giver udenlandske brugere mulighed for at registrere sig, og at en stor del af webstedet er oversat til engelsk (det er en luksus i Kina). I denne sky kan man arbejde med mange regioner i verden, det kontinentale Kina, samt Oceanien (Hongkong, Taiwan osv.).
IPSEC
Vi begyndte med geografi. Da vores testwebsted var placeret i Google Cloud, var vi nødt til at 'forbinde' Alibaba Cloud med GCP, så vi åbnede listen over steder, hvor Google er til stede. På det tidspunkt havde de stadig ikke deres eget datacenter i Hongkong.
Den nærmeste region viste sig at være asia-east1 (Taiwan). For Ali var den nærmeste region i det kontinentale Kina til Taiwan cn-shenzhen (Shenzhen).
Ved hjælp af terraform Vi beskrev og opsatte hele infrastrukturen i GCP og Ali. Tunnelen på 100 Mbit/s mellem skyerne blev oprettet næsten øjeblikkeligt. På Shenzhen- og Taiwan-siden oprettede vi proxypc'er. I Shenzhen termineres brugertrafikken, proxieres gennem tunnelen til Taiwan, og derfra går den direkte til den eksterne IP for vores service i us-east (Østkysten af USA). Ping mellem virtuel maskiner over tunnelen er 24 ms, hvilket ikke er så dårligt.
Samtidig placerede vi testzonen i Alibaba Cloud DNS. Efter delegationen af zonen til NS Ali faldt opløsningstiden fra 470 ms til 50 ms. Før dette var zonen også på Cloudflare.
Parallelt med tunnelen til asia-east1 oprettede vi endnu en tunnel fra Shenzhen direkte til us-east4. Der blev oprettet flere proxy-virtuelle maskiner, og man begyndte at måle begge løsninger ved at rute testtrafik ved hjælp af Cookies eller DNS. Det teststand er skematisk beskrevet i følgende billede:
Latency for tunnelerne viste sig at være følgende:
Ali cn-shenzhen GCP asia-east1 — 24ms
Ali cn-shenzhen <—> GCP us-east4 — 200ms
Browser-tests fra Catchpoint rapporterede om en fremragende forbedring af målinger.
Sammenlign testresultaterne for de to løsninger:
Løsning
Driftstid
Median
75 Percentil
95 Percentil
Cloudflare
86.6
18s
30s
60s
IPsec
99.79
18s
21s
30s
Dette er data fra løsningen, der bruger IPSEC-tunnel gennem asia-east1. Gennem us-east4 var resultaterne dårligere, og der var også flere fejl, så jeg vil ikke publicere resultaterne.
På baggrund af resultaterne fra denne test af de to tunneler, hvoraf den ene termineres i den nærmeste region til Kina, og den anden ved den endelige destination, blev det klart, at det er vigtigt at "komme hurtigt ud" fra den kinesiske firewall, og derefter anvende hurtige netværk (CDN-udbydere, cloud-udbydere osv.). Man bør ikke forsøge at passere firewallen i ét hug og komme til destinationen. Det er ikke den hurtigste vej.
Generelt er resultaterne okay, men for semrush.com er medianen 8.8s, og 75. percentilen 9.4s (i den samme test).
Og før jeg går videre, vil jeg gerne lave en lille lyrisk afstikker.
Lyrisk afstikker
Efter at brugeren har tilgået siden www.semrushchina.cn, som opløses gennem "hurtige" kinesiske DNS-servere, går HTTP-anmodningen gennem vores hurtige løsning. Svaret returneres ad samme vej, men i alle JS-scripts, HTML-sider og andre elementer på web-siden er domænet semrush.com angivet for yderligere ressourcer, der skal indlæses ved rendering af siden. Det vil sige, klienten opløser "hoved" A-posten www.semrushchina.cn og går ind i den hurtige tunnel, får hurtigt response — HTML-siden, hvor det er angivet:
- download denne js fra sso.semrush.com,
- hent CSS-filer fra cdn.semrush.com,
- og tag også billeder fra dab.semrush.com
- og så videre.
Browseren begynder at søge i det "ydre" internet efter disse ressourcer, idet den hver gang passerer gennem den tidskrævende firewall.
Men i den tidligere test præsenteres resultaterne, når der ikke er ressourcer på siden semrush.com, kun semrushchina.cn, mens *.semrushchina.cn opløses til adressen på en virtuel maskine i Shenzhen, for derefter at komme ind i tunnelen.
Kun kun, ved maksimalt at dirigere al mulig trafik gennem din løsning til hurtig passage af den kinesiske firewall, kan man opnå acceptable hastigheder og tilgængelighedsindikatorer for websitet samt ærlige testresultater af løsningerne.
Vi gjorde dette uden en eneste kodeændring på produktteamets side.
Subfilter
Løsningen blev praktisk talt udviklet med det samme, efter at dette problem opstod. Vi havde brug for PoC (Proof of Concept), at vores firewall passage-løsninger faktisk fungerer godt. For at gøre dette skal al trafik på websitet dirigeres gennem denne løsning. Og vi anvendte i nginx.
Subfilter — det er en temmelig enkel modul i nginx, der gør det muligt at ændre en streng i svaret til en anden streng. Så vi ændrede alle forekomster semrush.com og få en fungerende kommando. semrushchina.cn i alle svar.
Og… det virkede ikke, fordi vi fra backend fik komprimeret indhold, og derfor fandt subfilter ikke den nødvendige streng. Vi måtte tilføje endnu en lokal server til nginx, som udpakkede svaret og sendte det videre til den næste lokale server, som allerede håndterede strengudskiftningen, komprimeringen og leveringen til den næste proxy-server i kæden.
Som et resultat ville klienten, der modtog <subdomain>.semrush.com, modtage <subdomain>.semrushchina.cn , og gik lydigt gennem vores løsning.
Det er dog ikke nok blot at ændre domænet i én retning, da backends stadig forventer semrush.com i de efterfølgende forespørgsler fra klienten. Derfor, på den samme server, hvor udskiftningen finder sted i én retning, får vi underdomænet fra forespørgslen ved hjælp af et simpelt regulært udtryk, og derefter gør vi proxy_pass med variablen $host, der er sat til $subdomain.semrush.com. Det kan virke forvirrende, men det fungerer. Og det fungerer godt. For separate domæner, der kræver en anden logik, oprettes der blot egne serverblokke, og en separat konfiguration laves. Nedenfor er de forkortede nginx konfigurationer præsenteret for illustration og demonstration af denne ordning.
Den næste konfiguration håndterer alle forespørgsler fra Kina til .semrushchina.cn:
lyt 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;
}
}Denne konfiguration proxerer til localhost port 83, hvor næste konfiguration venter:
lyttende 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;
}
}Jeg gentager, dette er forkortede konfigurationer.
Cirka sådan. Det kan se komplekst ud, men det er let at forstå. I virkeligheden er det mere enkelt end det ser ud 🙂
Slut på det lyriske afsnit
I et stykke tid var vi lykkelige, fordi myten om faldende IPSEC-tunneler ikke blev bekræftet. Men så begyndte tunnelerne at falde. Flere gange om dagen i nogle minutter. Ikke meget, men det var uacceptabelt for os. Da begge tunneler blev termineret côté Ali på en router, besluttede vi, at det muligvis var et regionalt problem, og vi skulle opsætte en backup-region.
Vi fik opsat det. Tunnelerne begyndte at falde på forskellige tidspunkter, men failover fungerede glimrende på upstream-niveauet i nginx. Men så begyndte tunnelerne at falde omtrent samtidig 🙂 Og 502 og 504 begyndte igen. Uptime blev dårligere, så vi begyndte at overveje muligheden for Alibaba CEN (Cloud Enterprise Network).
CEN
CEN — det er forbindelsen mellem to VPC fra forskellige regioner inden for Alibaba Cloud, hvilket betyder, at du kan forbinde private netværk fra forskellige regioner inden for clouden. Og vigtigst af alt: denne kanal har en ret striks SLA. Den er meget stabil både i hastighed og uptime. Men det er aldrig så simpelt:
- den er MEGET svær at få, hvis du ikke er kinesisk statsborger eller virksomhed,
- du skal betale for hver megabit kapacitet af kanalen.
Efter at have fået mulighed for at forbinde Fastlandet Kina og Udenlandsk, oprettede vi CEN mellem to Ali-regioner: cn-shenzhen og us-east-1 (den nærmeste punkt til us-east4). I Ali us-east-1 opsatte vi endnu en virtuel maskine for at have endnu en hop.
Det viste sig at være:
Resultaterne af browser-testene nedenfor:
Løsning
Driftstid
Median
75 Percentil
95 Percentil
Cloudflare
86.6
18s
30s
60s
IPsec
99.79
18s
21s
30s
CEN
99.75
16s
21s
27s
Resultaterne er lidt bedre end med IPSEC. Men gennem IPSEC kan du potentielt overføre med en hastighed på 100 Mbit/s, mens du kun kan overføre med CEN med en hastighed på 5 Mbit/s, og det er dyrere.
Det indbyder til en hybrid, ikke? Forbind hastigheden fra IPSEC med stabiliteten fra CEN.
Sådan gjorde vi det, vi sendte trafik både gennem IPSEC og gennem CEN i tilfælde af, at IPSEC-tunnelen faldt. Oppetiden blev meget højere, men hastigheden på websiteindlæsning var stadig utilfredsstillende. Så jeg skitserede alle de diagrammer, vi allerede havde brugt og testet, og besluttede at prøve at tilføje lidt GCP til denne ordning, nemlig GLB.
GLB
GLB — det er (eller Google Cloud Load Balancer). Den har en vigtig fordel for os: i konteksten af CDN har den anycast IP, hvilket gør det muligt at rute trafik til det nærmeste datacenter til kunden, hvilket gør, at trafikken hurtigere når det hurtige Google-netværk og mindre går gennem det "normale" internet.
Uden at tænke længe, satte vi op HTTP/HTTPS LB i GCP og satte vores virtuelle maskiner med subfilter som backend.
Der var flere ordninger:
- Brug Cloudflare China Network, men denne gang angav vi den globale IP GLB.
- At terminere kunderne i cn-shenzhen, og derfra proxere trafik direkte til GLB.
- Gå direkte fra Kina til GLB.
- At terminere kunderne i cn-shenzhen, derfra proxere til asia-east1 via IPSEC (i us-east4 via CEN), derfra videre til GLB (bare rolig, der vil være et billede og forklaring nedenfor)
Vi testede alle disse muligheder og endnu nogle hybride:
- Cloudflare + GLB
Denne ordning tilfredsstillede os ikke på grund af oppetid og DNS-fejl. Men testen blev udført før fejlrettelsen fra CF, måske er det blevet bedre nu (dog udelukker det ikke HTTP-tidsoverskridelser).
- Ali + GLB
Denne ordning tilfredsstillede os heller ikke med hensyn til oppetid, da GLB ofte faldt ud af upstream på grund af umuligheden af at oprette forbindelse inden for acceptabel tid eller timeout, da adressen til GLB for serveren inden i Kina forbliver udenfor, dvs. bag den kinesiske firewall. Der skete ikke nogen magi.
- GLB only
En mulighed, der ligner den forrige, men hvor der ikke blev brugt servere i Kina: trafik gik direkte til GLB (vi ændrede DNS-poster). Resultaterne tilfredsstillede ikke, da situationen med at passere firewallen var meget værre for almindelige kinesiske kunder, der bruger tjenester fra almindelige internetudbydere, end hos Ali Cloud.
- Shenzhen -> (CEN/IPSEC) -> Proxy -> GLB
Her besluttede vi at bruge det bedste fra alle løsningerne:
- stabilitet og garanteret SLA fra CEN
- høj hastighed fra IPSEC
- "hurtigt" Google-netværk og dets anycast.
Diagrammet ser cirka sådan ud: trafik fra brugerne termineres på en virtuel maskine i ch-shenzhen. Der er opsat upstreams i nginx, hvoraf nogle henviser til private IP-servere, der ligger i den modsatte ende af IPSEC-tunnelen, mens andre upstreams henviser til private IP-adresser på den anden side af CEN. IPSEC blev konfigureret til regionen asia-east1 i GCP (der var den nærmeste region til Kina på tidspunktet for oprettelsen af løsningen. Nu har GCP også tilstedeværelse i Hong Kong). CEN — til regionen us-east1 i Ali Cloud.
Derefter blev trafikken fra begge ender dirigeret til anycast IP GLB, det vil sige til det nærmeste Google point of presence, og gik gennem deres netværk til regionen us-east4 i GCP, hvor der stod ombyttede virtuelle maskiner (med subfilter i nginx).
Denne hybride løsning, som vi forventede, har gjort det muligt at udnytte fordelene ved hver teknologi. Generelt går trafikken gennem en hurtig IPSEC, men hvis der opstår problemer, fjerner vi hurtigt disse servere fra upstreams i et par minutter og sender trafikken kun gennem CEN, indtil tunnelen stabiliseres.
Ved at implementere den fjerde løsning på listen ovenfor, nåede vi det, vi ønskede, og som virksomheden krævede på det tidspunkt.
Resultaterne af browser-tests for den nye løsning sammenlignet med de tidligere:
Løsning
Driftstid
Median
75 Percentil
95 Percentil
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
I den løsning, vi implementerede, fungerer alt godt, men der mangler en CDN, der kunne accelerere trafikken på regions- og endda byniveau. I teorien skulle det fremskynde webstedets ydeevne for slutbrugerne ved at udnytte de hurtige kommunikationskanaler fra CDN-udbyderen. Og vi har altid tænkt på det. Og nu er tiden kommet til næste iteration af projektet: at finde og teste CDN-udbydere i Kina.
Og det vil jeg fortælle jer om i den næste og afsluttende del 🙂
Kilde: habr.com
