Bună!
Sunt din nou cu voi, Nikita — inginerul sistemic de la companie SEMrush. Cu acest articol continui povestea despre cum am gândit o soluție de ocolire a Firewall-ului chinezesc pentru serviciul nostru semrush.com.
În Am povestit:
- ce probleme apar după ce se ia decizia „Trebuie să facem ca serviciul nostru să funcționeze în China”
- ce probleme are internetul chinezesc
- de ce este necesară licența ICP
- cum și de ce am decis să testăm mediile noastre de testare cu ajutorul Catchpoint
- ce rezultat a avut prima noastră variantă de soluție, bazată pe Cloudflare China Network
- cum am găsit un bug în DNS Cloudflare
Această parte este, din punctul meu de vedere, cea mai interesantă, deoarece se concentrează pe implementările tehnice specifice ale medii de testare. Și vom începe, sau mai degrabă vom continua, cu Alibaba Cloud.
Alibaba Cloud
Alibaba Cloud — un furnizor de cloud destul de mare, care are toate serviciile necesare pentru a se numi corect cloud provider. Este bine că au posibilitatea de a se înregistra utilizatorii străini și că o mare parte din site este tradusă în engleză (pentru China, aceasta este o abundență). În acest cloud se poate lucra cu multe regiuni din lume, China continentală, precum și Asia Oceaniei (Hong Kong, Taiwan etc.).
IPSEC
Am început cu geografia. Deoarece site-ul nostru de testare se afla în Google Cloud, a fost necesar să „legăm” Alibaba Cloud de GCP, așa că am deschis lista locațiilor în care Google este prezent. În acel moment, nu aveau încă un centru de date în Hong Kong.
Regiunea cea mai apropiată a fost asia-east1 (Taiwan). La Ali, regiunea cea mai apropiată de China continentală față de Taiwan a fost cn-shenzhen (Shenzhen).
Folosind terraform Am descris și am ridicat întreaga infrastructură în GCP și Ali. Tunelul de 100 Mbit/s între cloud-uri s-a stabilit practic instantaneu. Pe partea din Shenzhen și Taiwan am ridicat mașini virtuale proxy. În Shenzhen, traficul utilizatorilor este terminat, este proxificat prin tunel în Taiwan, iar de acolo merge direct pe IP-ul nostru extern în us-east (Coasta de Est a Statelor Unite). Ping-ul între mașinile virtuale prin tunel 24 ms, ceea ce nu este prea rău.
În același timp, am plasat zona de testare în Alibaba Cloud DNS. După delegarea zonei către NS Ali, timpul de rezolvare a scăzut de la 470 ms la 50 ms. Anterior, zona era de asemenea pe Cloudflare.
Paralel cu tunelul către asia-east1 am ridicat și un alt tunel din Shenzhen direct în us-east4. A fost create încă câteva mașini virtuale proxy și au început să măsoare ambele soluții, rutând traficul de test prin Cookies sau DNS. Schema băncii de testare este descrisă în următorul desen:
Latenta pentru tuneluri a fost următoarea:
Ali cn-shenzhen GCP asia-east1 — 24ms
Ali cn-shenzhen GCP us-east4 — 200ms
Teste browser Catchpoint au raportat o îmbunătățire excelentă a indicatorilor.
Comparați rezultatele testelor pentru cele două soluții:
Soluție
Uptime
Medie
Percentilă 75
Percentilă 95
Cloudflare
86.6
18s
30s
60s
IPsec
99.79
18s
21s
30s
Acestea sunt datele soluției care utilizează un tunel IPSEC prin asia-east1. Prin us-east4 rezultatele au fost mai slabe și au fost mai multe erori, așa că nu voi prezenta rezultatele.
Din rezultatele acestui test al celor două tuneluri, unul dintre ele terminându-se în cel mai apropiat regiune de China, iar celălalt în punctul de destinație final, a devenit clar că este important să "ies cât mai repede" de sub firewall-ul chinezesc, iar ulterior să folosească rețele rapide (furnizori de CDN, furnizori de cloud etc.). Nu trebuie să încerci să treci prin firewall și să ajungi direct la destinație. Aceasta nu este calea cea mai rapidă.
În general, rezultatele sunt destul de bune, totuși, semrush.com are o medie de 8.8s, iar percentila 75 este de 9.4s (în același test).
Și înainte de a merge mai departe, aș dori să fac o mică deviație lirică.
O mică digresiune
După ce utilizatorul accesează site-ul www.semrushchina.cn, care se rezolvă prin servere DNS "rapide" chinezești, cererea HTTP trece prin soluția noastră rapidă. Răspunsul se întoarce pe aceeași cale, dar în toate scripturile JS, paginile HTML și celelalte elemente ale paginii web este specificat domeniul semrush.com pentru resurse suplimentare care trebuie încărcate la redarea paginii. Adică clientul rezolvă înregistrarea principală A www.semrushchina.cn și intră în tunelul rapid, primind rapid un răspuns — pagina HTML, care conține:
- descarcă un anumit js de la sso.semrush.com,
- ia fișiere CSS de la cdn.semrush.com,
- și ia imagini de la dab.semrush.com
- și așa mai departe.
Browserul începe să meargă pe internetul "extern" pentru aceste resurse, trecând de fiecare dată prin firewall-ul care consumă timp de răspuns.
Dar în testul anterior sunt prezentate rezultatele atunci când pe pagină nu există resurse semrush.com, doar semrushchina.cn, iar *.semrushchina.cn se rezolvă în adresa mașinii virtuale din Shenzhen, pentru a ajunge apoi în tunel.
Doar așa, maximizând tot traficul posibil prin soluția noastră de trecere rapidă a firewall-ului chinez, putem obține viteze acceptabile și indicatori de disponibilitate a site-ului, precum și rezultate corecte ale testelor soluțiilor.
Am făcut acest lucru fără nicio modificare a codului pe partea produselor echipelor.
Subfilter
Soluția a apărut practic imediat după ce a apărut această problemă. Aveam nevoie de PoC (Proof of Concept), pentru a demonstra că soluțiile noastre de trecere a firewall-ului funcționează cu adevărat bine. Pentru aceasta, trebuie să direcționăm tot traficul site-ului prin această soluție. Și am aplicat în nginx.
Subfilter — este un modul destul de simplu în nginx, care permite înlocuirea unei linii din corpul răspunsului cu alta linie. Așadar, am înlocuit toate aparițiile semrush.com pe semrushchina.cn în toate răspunsurile.
Și… asta nu a funcționat, deoarece de la backend-uri primeam conținut comprimat, astfel subfilter nu găsea linia dorită. A fost necesar să adăugăm încă un server local în nginx, care decomprima răspunsul și-l transfera următorului server local, care se ocupa cu înlocuirea liniei, comprimarea și livrarea acestuia următorului proxy server din lanț.
În final, unde clientul ar fi primit .semrush.com, el primea .semrushchina.cn și mergea obedient prin soluția noastră.
Cu toate acestea, nu este suficient să schimbăm domeniul într-o singură direcție, deoarece backend-urile continuă să aștepte semrush.com în cererile ulterioare ale clientului. Prin urmare, pe același server unde se face înlocuirea într-o direcție, folosind o expresie regulată simplă, obținem subdomeniul din cerere, iar apoi facem proxy_pass cu variabila $host, setată la $subdomain.semrush.com. Poate părea complicat, dar funcționează. Și funcționează bine. Pentru domenii distincte, care necesită o altă logică, se creează pur și simplu blocuri de server proprii și se face o configurație separată. Mai jos sunt prezentate configurațiile nginx scurtate pentru ilustrare și demonstrarea acestui schema.
Următoarea configurație gestionează toate cererile din China pe .semrushchina.cn:
ascultă 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;
}
}Această configurație proxy-izează pe localhost portul 83, iar acolo ne așteaptă următoarea configurație:
ascultă 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;
}
}Repet, acestea sunt configurații reduse.
Așa ar putea arăta. Poate părea complicat, dar este simplu în cuvinte. În realitate, totul este mai ușor decât o sfeclă fiertă 🙂
Sfârșitul unei digresiuni lirice
O perioadă am fost fericiți, deoarece mitul tunelurilor IPSEC căzând nu s-a confirmat. Dar apoi tunelurile au început să cadă. De câteva ori pe zi, timp de câteva minute. Puțin, dar nu ne-a convenit. Deoarece ambele tuneluri erau terminate de partea Ali pe un singur router, am decis că, poate, aceasta este o problemă regională și că trebuie să activăm un backup regional.
Am activat. Tunelurile au început să cadă în momente diferite, dar failover-ul la nivel de upstream în nginx a funcționat perfect. Dar apoi tunelurile au început să cadă aproape simultan 🙂 Și au reapărut 502 și 504. Uptime-ul a început să se degradeze, așa că am început să analizăm opțiunea cu Alibaba CEN (Cloud Enterprise Network).
CEN
CEN — este conectivitatea între două VPC-uri din regiuni diferite din Alibaba Cloud, adică se pot conecta rețele private din diferite regiuni din cloud. Și cel mai important: acest canal are o SLAdestul de strictă. Este foarte stabil atât în ceea ce privește viteza, cât și în ceea ce privește uptime-ul. Dar niciodată nu este atât de simplu:
- este FOARTE dificil de obținut, dacă nu ești cetățean sau entitate juridică chineză,
- trebuie să plătești pentru fiecare megabit de capacitate a canalului.
După ce am obținut posibilitatea de a conecta China continentală și Străinătate, am creat un CEN între două regiuni Ali: cn-shenzhen și us-east-1 (cel mai apropiat punct de us-east-4). În Ali us-east-1 am ridicat încă o mașină virtuală, pentru a avea un alt hop.
A ieșit așa:
Rezultatele testelor din browser sunt mai jos:
Soluție
Uptime
Medie
Percentilă 75
Percentilă 95
Cloudflare
86.6
18s
30s
60s
IPsec
99.79
18s
21s
30s
CEN
99.75
16s
21s
27s
Performanțele sunt puțin mai bune decât cele ale IPSEC. Dar prin IPSEC poți potențial descărca cu o viteză de 100 Mbit/s, iar prin CEN doar cu o viteză de 5 Mbit/s și mai scump.
Se cere un hibrid, nu? Să combinăm viteza IPSEC și stabilitatea CEN.
Așa am procedat, dirijând traficul atât prin IPSEC, cât și prin CEN în caz de cădere a tunelului IPSEC. Uptime-ul a devenit mult mai ridicat, dar viteza de încărcare a site-ului lăsa de dorit. Atunci am schițat toate schemele pe care le-am folosit și testat deja și am decis să încerc să adaug în această schemă puțin GCP, și anume GLB.
GLB
GLB — acesta este (sau Google Cloud Load Balancer). Acesta are un avantaj important pentru noi: în contextul CDN, acesta IP anycast, ceea ce permite dirijarea traficului către cel mai apropiat centru de date de client, datorită căruia traficul ajunge mai rapid în rețeaua rapidă Google și circulă mai puțin pe internetul 'obișnuit'.
Fără a sta mult pe gânduri, am lansat HTTP/HTTPS LB în GCP și backend-ul l-am setat cu mașinile noastre virtuale cu subfilter.
Au fost câteva scheme:
- Utilizați Cloudflare China Network, dar de data aceasta Origin-ul a fost indicat ca fiind global IP GLB.
- Terminăm clienții în cn-shenzhen, iar de acolo direcționăm traficul direct în GLB.
- Să mergem direct din China în GLB.
- Terminăm clienții în cn-shenzhen, de acolo direcționăm către asia-east1 prin IPSEC (în us-east4 prin CEN), de acolo mergem către GLB (răbdare, mai jos va fi o imagine și o explicație)
Am testat toate aceste opțiuni și câteva hibrid:
- Cloudflare + GLB
Această schemă nu ne-a mulțumit în privința uptime-ului și erorilor DNS. Dar testul a fost realizat înainte de a fi corectat bug-ul din partea CF, poate că acum este mai bine (cu toate acestea, acest lucru nu exclude timeout-urile HTTP).
- Ali + GLB
Această schemă nu ne-a satisfăcut din punct de vedere al uptime-ului, deoarece GLB adesea ieșea din upstream din cauza imposibilității de conectare într-un timp acceptabil sau a timeout-ului, deoarece pentru serverul din China adresa GLB rămâne în continuare în exterior, ceea ce înseamnă că se află în spatele firewall-ului chinez. Nu a fost magie.
- GLB only
O opțiune, similară cu cea anterioară, doar că nu a folosit servere în China: traficul mergea direct la GLB (am schimbat înregistrările DNS). Prin urmare, rezultatele nu ne-au mulțumit, deoarece la clienții obişnuiți din China, care folosesc servicii de furnizori de internet obișnuiți, situația în ceea ce privește trecerea prin firewall este mult mai rău decât la Ali Cloud.
- Shenzhen -> (CEN/IPSEC) -> Proxy -> GLB
Aici am decis să folosim cele mai bune aspecte din toate soluțiile:
- stabilitate și SLA garantat de CEN
- rapiditate mare de la IPSEC
- rețeaua ‘rapidă’ Google și IP anycast.
Schema arată aproximativ așa: traficul utilizatorilor este terminat pe o mașină virtuală în ch-shenzhen. Acolo sunt configurate upstream-uri nginx, dintre care unele fac referire la IP-uri private ale serverelor aflate la capătul opus al tunelului IPSEC, iar alte upstream-uri se referă la adrese private ale serverelor de pe partea opusă a CEN. IPSEC a fost configurat până în regiunea asia-east1 GCP (era cea mai apropiată regiune de China în momentul creației soluției. Acum GCP are de asemenea o prezență în Hong Kong). CEN — până în regiunea us-east1 în Ali Cloud.
Ulterior, traficul din ambele capete a fost direcționat către anycast IP GLB, adică cel mai apropiat punct de prezență Google, și a fost trimis prin rețelele sale în regiunea us-east4 GCP, unde se aflau mașinile virtuale de substituție (cu subfilter în nginx).
Această soluție hibridă, așa cum ne-am așteptat, a permis valorificarea avantajelor fiecărei tehnologii. În general, traficul circulă printr-un IPSEC rapid, dar dacă apar probleme, eliminăm rapid aceste servere din upstream-uri pentru câteva minute și direcționăm traficul doar prin CEN, până când tunelul se stabilizează.
Implementând a patra soluție din lista de mai sus, am atins ceea ce ne-am dorit și ceea ce ne-a cerut afacerea în acel moment.
Rezultatele testelor din browser pentru noua soluție comparativ cu cele anterioare:
Soluție
Uptime
Medie
Percentilă 75
Percentilă 95
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
În soluția implementată de noi totul este bine, doar că nu există CDN care să poată accelera traficul la nivel regional și chiar la nivel de orașe. Teoretic, acest lucru ar trebui să îmbunătățească performanța site-ului pentru utilizatorii finali prin utilizarea canalelor rapide de comunicare ale furnizorului de CDN. Și ne-am gândit mereu la asta. Iată că a venit momentul pentru următoarea etapă a proiectului: căutarea și testarea furnizorilor de CDN din China.
Și despre asta vă voi povesti în următoarea, partea finală 🙂
Sursa: habr.com
