|
|
Zverejnené 11. 4. 2018 17:33:18
|
|
|
|

Aby bolo jednoduchšie pochopiť, o čom tento článok je, začnime zmenou priemernej dennej štatistiky Stack Overflow. Nasledujúce údaje pochádzajú zo štatistík k 12. novembru 2013:
- Load balancer prijal 148 084 833 HTTP požiadaviek
- Z toho bolo 36 095 312 nabitých stránok
- Na odosielanie sa používa 833 992 982 627 bajtov (776 GB) HTTP prevádzky
- Celkovo bolo prijatých 286 574 644 032 bajtov (267 GB) dát
- Celkom bolo odoslaných 1 125 992 557 312 bajtov (1 048 GB) dát
- 334 572 103 SQL dotazov (vrátane iba HTTP požiadaviek)
- 412 865 051 požiadaviek na Redis
- 3 603 418 požiadaviek Tag Engine
- SQL dotazy trvali 558 224 585 ms (155 hodín)
- Trvalo to 99 346 916 ms (27 hodín) na požiadavkách Redisu
- Na požiadavku na tag engine sme strávili 132 384 059 ms (36 hodín)
- Spracovanie ASP.Net procesu trvalo 2 728 177 045 ms (757 hodín)
Nasledujúce údaje ukazujú zmeny v štatistikách k 9. februáru 2016, takže môžete porovnať:
- HTTP požiadavky prijaté load balancerom: 209 420 973 (+61 336 090)
- 66 294 789 (+30 199 477), z ktorých sa stránka načíta
- HTTP dáta odoslané: 1 240 266 346 053 (+406 273 363 426) bajtov (1,24 TB)
- Celkové množstvo prijatých dát: 569 449 470 023 (+282 874 825 991) bajtov (569 GB)
- Celkové množstvo odoslaných dát: 3 084 303 599 266 (+1 958 311 041 954) bajtov (3,08 TB)
- SQL dotazy (len z HTTP požiadaviek): 504 816 843 (+170 244 740)
- Redis Cache návštevy: 5 831 683 114 (+5 418 818 063)
- Elastické vyhľadávania: 17 158 874 (nesledované v roku 2013)
- Požiadavky na tag engine: 3 661 134 (+57 716)
- Kumulatívny čas potrebný na vykonanie SQL dotazov: 607 073 066 (+48 848 481) ms (168 hodín)
- Spotrebovaný čas zásahu keše Redis: 10 396 073 (-88 950 843) ms (2,8 hodiny)
- Čas spotrebovaný požiadavkami na tag engine: 147 018 571 (+14 634 512) ms (40,8 hodín)
- Čas strávený spracovaním ASP.Net: 1 609 944 301 (-1 118 232 744) ms (447 hodín)
- 22,71 (-5,29) ms 49 180 275 vydaných strán priemerný čas renderovania (z toho 19,12 ms sa spotrebuje v ASP.Net)
- 11,80 (-53,2) ms 6 370 076 prvých strán priemerný čas vykreslenia (z toho 8,81 ms sa spotrebuje v ASP.Net)
Možno sa pýtate, prečo ASP.Net spracováva o 61 miliónov viac požiadaviek denne, ale skracuje čas spracovania o 757 hodín (v porovnaní s rokom 2013). Je to hlavne vďaka vylepšeniam, ktoré sme urobili na našich serveroch začiatkom roku 2015, ako aj množstvu práce na optimalizácii výkonu priamo v aplikáciách. Nezabudnite: výkon je stále predajným argumentom. Ak vás viac zaujímajú konkrétne hardvérové detaily, nebojte sa, konkrétne hardvérové detaily serverov používaných na prevádzku týchto stránok poskytnem vo forme prílohy v ďalšom článku (tento odkaz aktualizujem, keď príde čas).
Čo sa teda zmenilo za posledné dva roky? Nie veľa, len výmena niektorých serverov a sieťového vybavenia. Tu je prehľad serverov, ktoré dnes slúžia na prevádzku vašej webovej stránky (všimnite si, ako sa zmenili od roku 2013)
- 4 Microsoft SQL Server servery (2 z nich používajú nový hardvér)
- 11 IIS webových serverov (nový hardvér)
- 2 Redis servery (nový hardvér)
- 3 Tag Engine servery (2 z nich používajú nový hardvér)
- 3 Elasticsearch servery (rovnaké ako vyššie)
- 4 HAProxy servery na vyvažovanie záťaže (2 pridané na podporu CloudFlare)
- 2 sieťové zariadenia (Nexus 5596 core + 2232TM Fabric Extender, všetky zariadenia upgradované na 10Gbps šírku pásma)
- 2 x Fortinet 800C firewall (nahrádza Cisco 5525-X ASA)
- 2 Cisco ASR-1001 smerovače (nahrádza Cisco 3945 smerovače)
- 2 Cisco ASR-1001-x routery (NOVY!) )
Čo potrebujeme, aby Stack Overflow fungoval? Od roku 2013 sa toho veľa nezmenilo, ale vďaka optimalizáciám a novému hardvéru spomenutému vyššie nám teraz stačí len jeden webový server. Túto situáciu sme už neúmyselne otestovali a úspešne niekoľkokrát. Upozornenie: Len som povedal, že to funguje, nie že je to dobrý nápad. Ale zakaždým, keď sa to stane, je to celkom zaujímavé.
Teraz, keď máme základné čísla o nápadoch na škálovanie serverov, pozrime sa, ako sme vytvorili tieto skvelé webové stránky. Len málo systémov existuje úplne nezávisle (a naše nie sú výnimkou) a bez holistického pohľadu, ktorý tieto časti integruje, je význam architektonického plánovania výrazne znížený. Naším cieľom je pochopiť celkovú situáciu. V budúcnosti bude mnoho článkov, ktoré sa budú hlboko venovať každej konkrétnej oblasti. Tento článok je len zhrnutím logickej štruktúry kľúčového hardvéru a nasledujúci článok bude obsahovať konkrétne detaily o tomto hardvéri.
Ak chcete vidieť, ako tento hardvér dnes vyzerá, tu je niekoľko fotografií, ktoré som urobil z kabinetu A (kabinet B je presne rovnaký ako on) pri upgrade servera vo februári 2015:
Teraz sa pozrime na architektonické usporiadanie. Nasleduje zhrnutie logickej architektúry hlavných existujúcich systémov:
Základné princípy
Tu sú niektoré bežné princípy, ktoré nie je potrebné postupne zavádzať:
- Všetko má redundantné zálohy.
- Všetky servery a sieťové zariadenia majú aspoň dve pripojenia s 10Gbps šírkou pásma.
- Všetky servery majú dva zdroje napájania, ktoré dodávajú energiu cez dve UPS jednotky, dva generátory za nimi a dva napájacie napätie v sieti.
- Všetky servery majú redundantnú zálohu umiestnenú v racku A a racku B.
- Všetky servery a služby majú dvojité redundantné zálohy v samostatnom dátovom centre (v Colorade), hoci ja pokrývam hlavne New York.
- Všetko má redundantné zálohy.
internet
Najprv musíte nájsť našu webovú stránku, čo je DNS záležitosť. Vyhľadávanie webových stránok je rýchle, preto ho teraz dávame CloudFlare, pretože majú DNS servery v každom kúte sveta. DNS záznamy aktualizujeme cez API a tie sú zodpovedné za "správu" DNS. Avšak v našich zlovestných mysliach stále máme vlastné DNS servery kvôli hlboko zakoreneným problémom s dôverou. Keď je apokalypsa apokalyptická – možno kvôli GPL, Punyonu alebo problémom s cacheovaním – a ľudia stále chcú programovať tak, aby odvádzali svoju pozornosť, prechádzame na vlastné DNS servery.
Keď váš prehliadač nájde naše útočisko, HTTP prevádzka od našich štyroch ISP (Level 3, Zayo, Cogent a Lightower v New Yorku) vstupuje do jedného zo štyroch pokročilých smerovačov. Používame Border Gateway Protocol (BGP, veľmi štandardný protokol) na peer-to-peer prevádzku od poskytovateľov sietí, aby sme ju kontrolovali a poskytli najefektívnejší spôsob prístupu k našim službám. Smerovače ASR-1001 a ASR-1001-X sú rozdelené do dvoch skupín, pričom každá by mala používať aktívny/aktívny režim na spracovanie prevádzky od oboch poskytovateľov siete – tu sú zálohy redundantné. Hoci všetky majú rovnakú fyzickú šírku pásma 10Gbps, prevádzka zvonku je stále nezávislá od prevádzky z externej VLAN a je pripojená k vyvažovaniu záťaže samostatne. Po tom, čo prenos prejde cez router, prídete k load balanceru.
Myslím, že je čas spomenúť, že máme MPLS s 10Gbps šírkou pásma medzi dvoma dátovými centrami, hoci to priamo nesúvisí s webovými službami. Túto technológiu používame na vykonávanie replikácie mimo pracoviska a rýchle obnovovanie dát na riešenie určitých núdzových situácií. "Ale Nick, v tomto nie je žiadna nadbytočnost!" No, z technického hľadiska máš pravdu (v pozitívnom zmysle), na tejto úrovni ide naozaj o jeden bod zlyhania. Ale počkajte! Prostredníctvom sieťového poskytovateľa máme tiež dve ďalšie OSPF núdzové trasy (MPLS je prvou voľbou a tieto sú druhou a treťou voľbou z dôvodu nákladov). Každá z vyššie spomenutých sád zariadení bude pripojená k dátovému centru v Colorade podľa potreby, aby sa v prípade failoveru vyvážila sieťová prevádzka. Samozrejme, mohli sme tieto dve sady zariadení navzájom prepojiť, takže by vznikli štyri sady ciest, ale zabudnime na to, poďme ďalej.
Vyvažovanie záťaže (HAProxy)
Load balancing je implementovaný v HAProxy 1.5.15, bežiaci na CentOS 7 (naša obľúbená verzia Linuxu). A pridať TLS (SSL) bezpečný prenosový protokol na HAProxy. Sledujeme tiež HAProxy 1.7, ktorý okamžite poskytne podporu pre protokol HTTP/2.
Na rozdiel od iných serverov s duálnymi 10Gbps LACP sieťovými pripojeniami má každý load balancer dve 10Gbps pripojenia: jedno pre externú sieť a druhé pre DMZ. Tieto servery majú 64GB alebo viac pamäte na efektívnejšie spracovanie SSL protokolovej vrstvy. Keď môžeme ukladať a opätovne používať viac TLS relácií v pamäti, spotrebúvame menej výpočtových zdrojov pri pripojení k tomu istému klientovi. To znamená, že môžeme obnoviť sedenia rýchlejšie a lacnejšie. Pamäť je taká lacná, že je to ľahká voľba.
Samotné vyvažovanie záťaže sa ľahko nastavuje. Počúvame rôzne webové stránky na viacerých IP adresách (hlavne kvôli správe certifikátov a DNS) a potom smerujeme prevádzku na rôzne backendy (hlavne na základe hlavičiek hosta). Jediné, čo tu robíme, je obmedziť rýchlosť a získať časť informácií z hlavičky (z webovej vrstvy) na prihlásenie do systémových logovacích správ HAProxy, čím môžeme zaznamenávať výkonnostné metriky pre každú požiadavku. Podrobne to spomenieme neskôr.
Webová vrstva (IIS 8.5, ASP.Net MVC 5.2.3 a .Net 4.6.1)
Load balancing rozdeľuje prevádzku medzi 9 serverov, ktoré nazývame primárny webový server (01-09) a 2 vývojové webové servery (10-11, naše testovacie prostredie). Hlavný server beží na Stack Overflow, Careers a všetkých stránkach Stack Exchange, zatiaľ čo meta.stackoverflow.com a meta.stackexchange.com bežia na ďalších dvoch serveroch. Hlavná aplikácia Q&A je multi-tenant, čo znamená, že jedna aplikácia spracováva všetky požiadavky z Q&A stránky. Inými slovami, môžeme spustiť celú Q&A aplikáciu na jednom aplikačnom poole na jednom serveri. Iné aplikácie ako Careers, API v2, Mobile API a podobne sú nezávislé. Tu je, čo vidíte v IIS pre master a dev servery:
Tu je rozloženie webovej vrstvy Stack Overflow, ako je vidieť v Opserveri (našom internom monitorovacom paneli):
A tu je spotreba zdrojov týchto webových serverov:
Podrobnejšie sa vysvetlím v nasledujúcom článku o tom, prečo poskytujeme toľko zdrojov, pričom sa zameriam na rolling build, voľnosť a redundanciu.
Servisná vrstva (IIS, ASP.Net MVC 5.2.3, . NET 4.6.1 a HTTP. SYS)
Vedľa webovej vrstvy je servisná vrstva. Bežia tiež na IIS 2012 vo Windows 8.5R2. Táto vrstva spúšťa niektoré interné služby, ktoré podporujú webovú vrstvu a ďalšie interné systémy produkčného prostredia. Dve hlavné služby sú: "Stack Server", ktorý beží na tag engine a je založený na http.sys (nie IIS); Providence API (založené na IIS). Zaujímavý fakt: musel som korelovať oba procesy, aby som sa pripojil k rôznym socketom, pretože Stack Server veľmi často pristupoval k L2 a L3 cache pri obnovovaní zoznamu problémov v dvojminútových intervaloch.
Stroje, ktoré prevádzkujú tieto služby, sú kritické pre tagový engine a backend API, takže musia byť redundantné, ale nie 9x redundantné. Napríklad všetky články a ich tagy z databázy načítavame každých n minút (momentálne 2 minúty), čo nie je málo. Nechceme túto operáciu načítavania opakovať 9-krát na webovej vrstve, 3-krát je pre nás dosť bezpečné. Používame tiež rôzne hardvérové konfigurácie pre tieto servery, aby sme lepšie optimalizovali výpočtové a načítavacie charakteristiky tag engine a elastic index úloh (tiež bežiacich v tejto vrstve). Samotný "tag engine" je pomerne zložitá téma, ktorá bude rozobraná v samostatnom článku. Základný princíp je, že keď pristupujete k adrese /questions/tagged/java, navštívite tagovací engine, aby ste získali otázky, ktoré s ním zodpovedajú. Vyhľadávač rieši všetky tagy okrem /search, takže všade, vrátane novej navigácie, získava údaje cez túto službu.
Cacheovanie a publikovanie/odberanie (Redis)
Použili sme Redis na niektorých miestach a má pevnú stabilitu. Aj keď je mesačne až 160 miliárd operácií, CPU na inštanciu nepresahuje 2 %, čo je zvyčajne menej:
Používame Redis pre cache systémy na úrovni L1/L2. Úroveň "L1" je HTTP cache, ktorá funguje na webovom serveri alebo v podobnej aplikácii. Úroveň "L2" slúži na získavanie dát cez Redis po zlyhaní predchádzajúcej cache úrovne. Naše dáta sú uložené vo formáte Protobuf, implementovanom prostredníctvom protobuf-dot-net napísaného Marcom Gravelom. Pre klienta Redis sme použili knižnicu StackExchange.Redis, čo je open-source knižnica vyvinutá interne. Ak webový server nezasiahne ani L1 ani L2 cache, načíta dáta zo svojich dátových zdrojov (databázové dotazy, API volania a podobne) a uloží výsledky do lokálnej cache a Redis. Ďalší server môže chýbať v L1 cache pri získavaní rovnakých dát, ale v L2/Redis tieto dáta získa, čím sa eliminuje potreba databázových dotazov alebo API volaní.
Prevádzkujeme tiež veľa Q&A stránok, každá s vlastnou L1/L2 cache: kľúč ako prefix v L1 cache a databázové ID v L2/Redis cache. Touto témou sa budeme venovať v budúcich článkoch.
Okrem dvoch hlavných Redis serverov (jeden master a jeden slave), ktoré bežia na všetkých inštanciách lokality, sme tiež nastavili inštanciu pre strojové učenie (hlavne z dôvodu pamäte) na dvoch ďalších dedikovaných slave serveroch. Táto skupina serverov sa používa na poskytovanie služieb, ako je odporúčanie otázok na domovskej stránke a lepšie priradenie úloh. Táto platforma sa volá Providence a Kevin Montrose o nej písal.
Hlavný server Redis má 256 GB RAM (približne 90 GB využité) a server Providence má 384 GB pamäte (približne 125 GB využitej).
Redis nie je len na cachovanie, má aj mechanizmus publikovania a odberu, kde jeden server môže zverejniť správu a ostatní odberatelia ju môžu prijať (vrátane Redis od klientov na serveri). Tento mechanizmus používame na vymazanie L1 cache na iných službách, aby sme udržali konzistenciu cache na webovom serveri. Ale má aj iné dôležité využitie: websockety.
Websockety (NetGain)
Websockets používame na posielanie aktualizácií v reálnom čase používateľom, ako sú notifikácie v hornom paneli, hlasovania, nové navigácie, nové odpovede, komentáre a ďalšie.
Samotný socket server beží na webovej vrstve, využívajúc natívne sockety. Ide o veľmi malú aplikáciu založenú na našej open-source implementácii knižnice: StackExchange.NetGain. V časoch špičky sme mali približne 500 000 súbežných websocket pripojení, čo je veľa prehliadačov. Zaujímavosť: niektoré z týchto prehliadačov sú otvorené už viac ako 18 mesiacov a budete musieť nájsť niekoho, kto zistí, či títo vývojári ešte žijú. Nasledujúci graf ukazuje vzor súbežnosti websocketov tento týždeň:
Prečo používať websockety? V našom rozsahu je to oveľa efektívnejšie ako prieskumy. Týmto spôsobom môžeme jednoducho posielať viac dát s menšími zdrojmi a byť pre používateľov viac v reálnom čase. Tento prístup však nie je bez problémov: dočasné porty, vyčerpané súbory na load balanceroch sú veľmi zaujímavé a o nich budeme hovoriť neskôr.
Vyhľadávanie (Elasticsearch)
Spoiler: Tu nie je veľa dôvodov na nadšenie. Webová vrstva používa Elasticsearch 1.4 a implementuje ultraľahkého, výkonného klienta StackExchange.Elastic. Na rozdiel od väčšiny vecí neplánujeme túto časť sprístupniť ako open source, jednoducho preto, že odhaľuje veľmi malú podmnožinu API, ktoré potrebujeme používať. Som si istý, že zverejnenie tejto správy preváži stratu a len by to vývojárov zmiatlo. Na týchto miestach používame elastic:/search na výpočet súvisiacich otázok a dávame odporúčania pri kladení otázok.
Každý Elastic klaster (jeden pre každé dátové centrum) obsahuje 3 uzly, z ktorých každý má svoj vlastný index. Stránka Careers má tiež niekoľko ďalších indexov. O niečo menej štandardnou súčasťou našej konfigurácie v elastických kruhoch je, že náš klaster troch serverov je o niečo výkonnejší než bežná konfigurácia: každý server používa SSD úložisko, 192GB pamäte, duálnu sieť s šírkou pásma 10Gbps.
Tá istá aplikačná doména ako Stack Server (áno, tu nás používal .Net Core) hostí aj tagový engine, ktorý tiež používa Elasticsearch na kontinuálne indexovanie. Tu používame malý trik, napríklad použitie ROWVERSION v SQL Serveri (zdroj dát) na porovnanie s dokumentom "last place" v Elastic. Keďže je zjavne sekvenčný, je pre nás jednoduché prehľadávať a indexovať obsah, ak je po poslednej návšteve upravený.
Hlavným dôvodom, prečo používame Elasticsearch namiesto technológií ako SQL fulltextové vyhľadávanie, je jeho škálovateľnosť a nákladová efektívnosť. SQL je na CPU relatívne drahý, zatiaľ čo Elastic je oveľa lacnejší a v poslednej dobe prináša veľa nových funkcií. Prečo nepoužiť Solr? Musíme vyhľadávať naprieč sieťou (s viacerými indexmi naraz) a Solr tento scenár v čase našich rozhodnutí nepodporuje. Dôvod, prečo sme ešte nepoužili 2.x, je ten, že typy sa v 2.x výrazne zmenili, čo znamená, že musíme všetko znovu indexovať, ak chceme upgradovať. Jednoducho nemám dosť času plánovať zmeny požiadaviek a migrácie.
Databáza (SQL Server)
SQL Server používame ako jediný zdroj pravdy. Všetky dáta v Elastic a Redis pochádzajú zo SQL Serveru. Máme dva SQL Server klastry a sme nakonfigurovaní s AlwaysOn dostupnosťovými skupinami. Každý klaster má primárny server v New Yorku (ktorý preberá takmer všetku záťaž) a replika server, okrem repliky servera v Colorade (naše dátové centrum na obnovu po havárii). Všetky kopírovacie operácie sú asynchrónne.
Prvým klastrom je sada serverov Dell R720xd, každý s 384GB pamäte, PCIe SSD s 4TB priestorom a dvoma 12-jadrovými procesormi. Zahŕňa Stack Overflow, Sites (to je zlý názov, vysvetlím to neskôr), PRIZM a databázu Mobile.
Druhý klaster tvorí sada serverov Dell R730xd, každý s 768GB pamäte, PCIe SSD s 6TB miesta a dvoma 8-jadrovými procesormi. Tento klaster obsahuje všetky ostatné databázy, vrátane Careers, Open ID, Chat, záznamov výnimiek a ďalších Q&A stránok (napr. Super User, Server Fault a pod.).
Na databázovej vrstve chceme udržať využitie CPU na veľmi nízkej úrovni, hoci v praxi bude využitie CPU mierne vyššie, keď nastanú plánované problémy s cachovaním (čo riešime). Momentálne sú primárne servery NY-SQL02 a 04 a repliky 01 a 03, ktoré sme dnes reštartovali kvôli aktualizácii SSD. Takto sa im darilo za posledných 24 hodín:
Naše používanie SQL je veľmi jednoduché. Jednoduché znamená rýchlo. Aj keď niektoré query príkazy môžu byť perverzné, naša interakcia so SQL prebieha pomerne natívnym spôsobom. Máme niektoré staršie Linq2Sql, ale všetky naše nové vývoje používajú Dapper, náš open-source micro-ORM framework, ktorý používa POCO. Dovoľte mi to vysvetliť inak: Stack Overflow má v databáze len jednu uloženú procedúru a túto poslednú zostávajúcu uloženú procedúru zruším a nahradím ju kódom.
Knižnica
Tak zmeníme názor, tu sú veci, ktoré vám môžu pomôcť priamo. Niektoré z nich som už spomínal, ale dám vám zoznam mnohých open-source .Net knižníc, ktoré udržiavame a ktoré všetci používajú. Otvárame ich ako open source, pretože nemajú jadrovú obchodnú hodnotu, ale môžu pomôcť vývojárom po celom svete. Dúfam, že ich teraz môžete použiť:
- Dapper (.Net Core) – Vysokovýkonný mikro-ORM framework pre ADO.Net
- StackExchange.Redis – Vysokovýkonný Redis klient
- MiniProfiler – ľahký profiler, ktorý používame na každej stránke (podporuje aj Ruby, Go a Node)
- Výnimočné – Na zaznamenávanie chýb v SQL, JSON, MySQL a podobne
- Jil – Vysokovýkonná JSON serializácia a deserializátor
- Sigil – .Net CIL Generation Helper (používaný, keď C# nie je dostatočne rýchly)
- NetGain – Vysokovýkonný websocket server
- Opserver – Monitorovací dashboard, ktorý priamo skúma väčšinu systémov a dokáže získavať informácie z Orionu, Bosunu alebo WMI
- Bosun – Monitorovací systém na pozadí, napísaný v jazyku Go
|
Predchádzajúci:enum enum kontroluje, či je hodnota zahrnutá v enumBudúci:Ako môžem rýchlo nájsť MB
|