Denna artikel är en spegelartikel om maskinöversättning, klicka här för att hoppa till originalartikeln.

Utsikt: 13027|Svar: 0

StackOverflow är så stort, vad är dess arkitektur?

[Kopiera länk]
Publicerad på 2018-04-11 17:33:18 | | | |
För att göra det lättare att förstå vad den här artikeln handlar om, låt oss börja med förändringen i Stack Overflows genomsnittliga dagliga statistik. Följande siffror kommer från statistiken per den 12 november 2013:

  • Lastbalanseraren accepterade 148 084 833 HTTP-förfrågningar
  • Av dessa var 36 095 312 sidinläsningar
  • 833 992 982 627 byte (776 GB) HTTP-trafik används för att skicka
  • Totalt mottogs 286 574 644 032 byte (267 GB) data
  • Totalt skickades 1 125 992 557 312 byte (1 048 GB) data
  • 334 572 103 SQL-frågor (inklusive endast från HTTP-förfrågningar)
  • 412 865 051 Redis-förfrågningar
  • 3 603 418 förfrågningar om taggmotorn
  • Det tog 558 224 585 ms (155 timmar) på SQL-frågor
  • Det tog 99 346 916 ms (27 timmar) på Redis-förfrågningar
  • Tillbringade 132 384 059 ms (36 timmar) på tagmotorförfrågan
  • Det tog 2 728 177 045 ms (757 timmar) på ASP.Net processbehandling



Följande data visar förändringarna i statistiken per den 9 februari 2016, så du kan jämföra:

  • HTTP-förfrågningar mottagna av lastbalanseraren: 209 420 973 (+61 336 090)
  • 66 294 789 (+30 199 477) varav sidan laddas
  • HTTP-data skickad: 1 240 266 346 053 (+406 273 363 426) byte (1,24 TB)
  • Total mängd mottagen data: 569 449 470 023 (+282 874 825 991) byte (569 GB)
  • Total mängd skickad data: 3 084 303 599 266 (+1 958 311 041 954) byte (3,08 TB)
  • SQL-frågor (endast från HTTP-förfrågningar): 504 816 843 (+170 244 740)
  • Redis cache-träffar: 5 831 683 114 (+5 418 818 063)
  • Elastiska sökningar: 17 158 874 (ej spårade 2013)
  • Tagmotorförfrågningar: 3 661 134 (+57 716)
  • Kumulativ tid som krävs för att köra SQL-frågor: 607 073 066 (+48 848 481) ms (168 timmar)
  • Redis cache-träfftid förbrukad: 10 396 073 (-88 950 843) ms (2,8 timmar)
  • Tid som förbrukas av taggmotorförfrågningar: 147 018 571 (+14 634 512) ms (40,8 timmar)
  • Tid som förbrukas i ASP.Net bearbetning: 1 609 944 301 (-1 118 232 744) ms (447 timmar)
  • 22,71 (-5,29) ms 49 180 275 utdelningssidor Genomsnittlig renderingstid (varav 19,12 ms förbrukas i ASP.Net)
  • 11,80 (-53,2) ms 6 370 076 första sidor genomsnittlig renderingstid (varav 8,81 ms förbrukas i ASP.Net)



Du kanske undrar varför ASP.Net behandlar 61 miljoner fler förfrågningar per dag men minskar handläggningstiden med 757 timmar (jämfört med 2013). Detta beror främst på de uppgraderingar vi gjorde på våra servrar i början av 2015, samt mycket arbete med optimering av prestandan i apparna. Glöm inte: prestanda är fortfarande en säljpunkt. Om du är mer nyfiken på de specifika hårdvarudetaljerna, oroa dig inte, jag kommer att ge de specifika hårdvarudetaljerna för servrarna som används för att driva dessa sajter i form av ett appendix i nästa artikel (jag uppdaterar denna länk när tiden är inne).

Så vad har förändrats de senaste två åren? Inte mycket, bara att byta ut några servrar och nätverksutrustning. Här är en översikt över de servrar som används för att driva din webbplats idag (notera hur de har förändrats sedan 2013)

  • 4 Microsoft SQL Server-servrar (2 av dem använder ny hårdvara)
  • 11 IIS-webbservrar (ny hårdvara)
  • 2 Redis-servrar (ny hårdvara)
  • 3 Tag Engine-servrar (2 av dem använder ny hårdvara)
  • 3 Elasticsearch-servrar (samma som ovan)
  • 4 HAProxy lastbalanseringsservrar (2 tillagda för att stödja CloudFlare)
  • 2 nätverksenheter (Nexus 5596 kärnor + 2232TM Fabric Extender, alla enheter uppgraderade till 10 Gbps bandbredd)
  • 2 x Fortinet 800C brandvägg (ersätter Cisco 5525-X ASA)
  • 2 Cisco ASR-1001-routrar (ersätter Cisco 3945-routrar)
  • 2 Cisco ASR-1001-x routrar (NYA!) )



Vad behöver vi för att få Stack Overflow att fungera? Inte mycket har förändrats sedan 2013, men tack vare optimeringarna och den nya hårdvaran som nämnts ovan behöver vi nu bara en webbserver. Vi har redan testat denna situation av misstag, med framgång flera gånger. Observera: Jag sa precis att det fungerar, jag sa inte att det är en bra idé. Men varje gång detta händer är det ganska intressant.

Nu när vi har några grundläggande siffror för idéer för serverskalning, låt oss se hur vi gjorde dessa häftiga webbsidor. Få system existerar helt oberoende (och våra är inget undantag), och utan en helhetssyn som integrerar dessa delar minskar betydelsen av arkitekturplanering avsevärt. Vårt mål är att förstå den övergripande situationen. Det kommer att finnas många artiklar som går djupt in på varje specifikt område i framtiden. Denna artikel är bara en sammanfattning av den logiska strukturen för nyckelhårdvaran, och nästa artikel kommer att innehålla specifika detaljer om denna hårdvara.

Om du vill se hur hårdvaran ser ut idag, här är några bilder jag tog på Skåp A (Skåp B är exakt likadant som det) när jag uppgraderade servern i februari 2015:



Nu ska vi dyka ner i arkitekturens layout. Följande är en sammanfattning av den logiska arkitekturen för de huvudsakliga befintliga systemen:



Grundläggande principer

Här är några vanliga principer som inte behöver introduceras i tur och ordning:

  • Allt har redundanta backups.
  • Alla servrar och nätverksenheter har minst två anslutningar med 10 Gbps bandbredd.
  • Alla servrar har två strömkällor som levererar ström via två UPS-enheter, två generatorer bakom dem och två nätspänningsmatningsmatare.
  • Alla servrar har en redundant backup placerad i Rack A och Rack B.
  • Alla servrar och tjänster har dubbla redundanta backuper i ett separat datacenter (i Colorado), även om jag främst täcker New York.
  • Allt har redundanta backups.


Internet

Först måste du hitta vår webbplats, som är en DNS-grej. Att hitta webbplatser går snabbt, så nu ger vi det till CloudFlare eftersom de har DNS-servrar i varje hörn av världen. Vi uppdaterar DNS-poster via API:er, och de ansvarar för att "hantera" DNS. Men i våra skurkaktiga sinnen har vi fortfarande våra egna DNS-servrar på grund av djupt rotade förtroendefrågor. När apokalypsen är apokalyptisk – kanske på grund av GPL, Punyon eller cacheproblem – och folk fortfarande vill programmera för att avleda sin uppmärksamhet, byter vi till våra egna DNS-servrar.

När din webbläsare hittar vårt gömställe går HTTP-trafik från våra fyra ISP:er (Level 3, Zayo, Cogent och Lightower i New York) in i en av våra fyra avancerade routrar. Vi använder Border Gateway Protocol (BGP, ett mycket standardiserat protokoll) för att peer-to-peer-trafik från nätverksleverantörer för att kontrollera det och erbjuda det mest effektiva sättet att få tillgång till våra tjänster. ASR-1001 och ASR-1001-X routrar är indelade i två grupper, där varje grupp ska använda aktiv/aktiv modus för att hantera trafik från båda nätverksleverantörerna – här finns redundanta backup. Även om de alla har samma fysiska bandbredd på 10 Gbps, är trafiken från utsidan fortfarande oberoende av trafiken från det externa VLAN:et och är ansluten separat till lastbalanseringen. Efter att trafiken passerat genom routern kommer du till lastbalanseraren.

Jag tror det är dags att nämna att vi har MPLS med 10 Gbps bandbredd mellan de två datacenterna, även om detta egentligen inte är direkt relaterat till webbplatstjänster. Vi använder denna teknik för att utföra extern replikering och snabb återställning av data för att hantera vissa nödsituationer. "Men Nick, det finns ingen redundans i det här!" Ur ett tekniskt perspektiv har du rätt (i positiv mening), det är egentligen en enda felpunkt på denna nivå. Men vänta! Genom nätverksleverantören har vi också två ytterligare OSPF-failover-rutter (MPLS är förstahandsvalet, och dessa är andra och tredje alternativet av kostnadsskäl). Var och en av de tidigare nämnda enheterna kommer att kopplas till Colorados datacenter enligt lastbalanseringstrafiken i nätverket vid en failover. Självklart kunde vi ha kopplat ihop dessa två uppsättningar enheter med varandra, så att det finns fyra uppsättningar vägar, men glöm det, låt oss gå vidare.

Lastbalansering (HAProxy)

Lastbalansering är implementerad med HAProxy 1.5.15, som körs på CentOS 7 (vår favoritversion av Linux). Och lägg till TLS (SSL) säkert överföringsprotokoll på HAProxy. Vi håller också ett öga på HAProxy 1.7, som omedelbart kommer att ge stöd för HTTP/2-protokollet.

Till skillnad från andra servrar med dubbla 10Gbps LACP-nätverksanslutningar har varje lastbalanserare två 10Gbps-anslutningar: en för det externa nätverket och en för DMZ. Dessa servrar har 64 GB eller mer minne för att hantera SSL-protokollskiktet mer effektivt. När vi kan cacha och återanvända fler TLS-sessioner i minnet förbrukar vi mindre beräkningsresurser när vi ansluter till samma klient. Detta innebär att vi kan återställa sessioner snabbare och billigare. Minne är så billigt att det är ett enkelt val.

Lastbalansering i sig är lätt att ställa in. Vi lyssnar på olika webbplatser på flera olika IP-adresser (främst för certifikat- och DNS-hanteringsskäl) och dirigerar sedan trafiken till olika backends (främst baserat på värdheaders). Det enda vi gör här är att begränsa hastigheten och skrapa ut viss headerinformation (från webblagret) för att logga in i HAProxys systemloggmeddelanden, på så sätt kan vi registrera prestandamått för varje förfrågan. Vi kommer att nämna detta i detalj senare.

Webblager (IIS 8.5, ASP.Net MVC 5.2.3 och .Net 4.6.1)

Lastbalansering fördelar trafiken mellan 9 av det vi kallar den primära webbservern (01-09) och 2 utvecklingswebbservrar (10-11, vår testmiljö). Huvudservern kör Stack Overflow, Careers och alla Stack Exchange-sajter, medan meta.stackoverflow.com och meta.stackexchange.com körs på två andra servrar. Huvudappen för frågor och svar är multi-tenant, vilket innebär att en enda app hanterar alla förfrågningar från frågestället. Med andra ord kan vi köra hela Q&A-appen på en applikationspool på en server. Andra appar som Careers, API v2, Mobile API, etc., är oberoende av varandra. Här är vad du ser i IIS för master- och dev-servrarna:



Här är fördelningen av Stack Overflows webblager som syns i Opserver (vår interna övervakningspanel):



Och här är resursförbrukningen för dessa webbservrar:



Jag kommer att gå in mer i detalj i en senare artikel om varför vi tillhandahåller så många resurser, med fokus på rullande byggande, spelrum och redundans.

Tjänstelager (IIS, ASP.Net MVC 5.2.3, . NET 4.6.1 och HTTP. SYS)

Bredvid webblagret finns service-lagret. De körs också ovanpå IIS 2012 i Windows 8.5R2. Detta lager kör vissa interna tjänster som stödjer webblagret och andra interna system i produktionsmiljön. De två huvudsakliga tjänsterna är: "Stack Server", som kör en taggmotor och baseras på http.sys (inte IIS); Providence API (baserat på IIS). En intressant fakta: Jag var tvungen att korrelera de två processerna för att ansluta till olika sockets, eftersom Stack Server mycket ofta gick åt L2- och L3-cachen när den uppdaterade listan med två minuters mellanrum.

Maskinerna som kör dessa tjänster är kritiska för taggmotorn och backend-API:erna, så de måste vara redundanta, men inte 9 gånger redundanta. Till exempel laddar vi alla artiklar och deras taggar från databasen var n:e minut (för närvarande 2 minuter), vilket inte är lågt. Vi vill inte upprepa denna lastoperation 9 gånger på webblagret, 3 gånger är tillräckligt säkert för oss. Vi använder också olika hårdvarukonfigurationer för dessa servrar för att bättre optimera för tagmotorns och elastic index-jobbens beräknings- och dataladdningsegenskaper (som också körs i detta lager). "Tag engine" i sig är ett relativt komplext ämne som kommer att tas upp i en särskild artikel. Grundprincipen är att när du går åt adressen /questions/tagged/java, besöker du taggningsmotorn för att få de frågor som matchar den. Motorn hanterar all taggmatchning utom /search, så överallt, inklusive den nya navigeringen, får data via denna tjänst.

Caching & Publicering/Prenumerering (Redis)

Vi använde Redis på vissa ställen, och den har stenfast stabilitet. Även om det finns så många som 160 miljarder operationer per månad, överstiger CPU:n per instans inte 2 %, vilket vanligtvis är lägre:



Vi använder Redis för Caching-system på nivå 1/L2. "L1"-nivån är HTTP-cachen som fungerar i en webbserver eller någon liknande applikation. "L2"-nivån är att erhålla data via Redis efter att föregående nivås cache har misslyckats. Vår data lagras i Protobuf-formatet, implementerat via protobuf-dot-net skrivet av Marc Gravel. För Redis-klienten använde vi StackExchange.Redis-biblioteket, som är ett open source-bibliotek utvecklat internt. Om en webbserver inte träffar både L1- och L2-cachen hämtar den data från sina datakällor (databasfrågor, API-anrop och så vidare) och sparar resultaten i den lokala cachen och Redis. Nästa server kan saknas i L1-cachen när samma data hämtas, men den hämtar data i L2/Redis, vilket eliminerar behovet av databasfrågor eller API-anrop.

Vi kör också många Q&A-sajter, var och en med sin egen L1/L2-cache: nyckel som prefix i L1-cachen och databas-ID i L2/Redis-cachen. Vi kommer att fördjupa oss i detta ämne i framtida artiklar.

Utöver de två huvudsakliga Redis-servrarna (en master och en slav) som kör alla platsinstanser, satte vi också upp en instans för maskininlärning (främst av minnesskäl) med två andra dedikerade slavservrar. Denna grupp servrar används för att erbjuda tjänster som att rekommendera frågor på startsidan och förbättra jobbmatchningen. Denna plattform heter Providence, och Kevin Montrose skrev om den.

Huvudservern för Redis har 256 GB RAM (ungefär 90 GB använt), och Providence-servern har 384 GB minne (cirka 125 GB använt).

Redis är inte bara för caching, det har också en publicerings- och prenumerationsmekanism där en server kan publicera ett meddelande och andra prenumeranter kan ta emot meddelandet (inklusive Redis från nedströmsklienter på servern). Vi använder denna mekanism för att rensa L1-cachen på andra tjänster för att bibehålla cachekonsistens på webbservern. Men det har en annan viktig användning: websockets.

Websockets (NetGain)

Vi använder websockets för att skicka realtidsuppdateringar till användare, såsom notiser i toppmenyn, röster, ny navigering, nya svar, kommentarer och mer.

Socket-servern körs på webblagret, med inbyggda sockets. Detta är en mycket liten applikation baserad på vår open source-biblioteksimplementation: StackExchange.NetGain. Under rusningstider hade vi ungefär 500 000 samtidiga websocket-anslutningar, vilket är många webbläsare. Rolig fakta: några av dessa webbläsare har varit öppna i över 18 månader, och du måste hitta någon som kan se om dessa utvecklare fortfarande är vid liv. Följande diagram visar mönstret för websocket-samtidighet denna vecka:



Varför använda websockets? I vår skala är det mycket mer effektivt än opinionsundersökningar. På så sätt kan vi helt enkelt skicka mer data med färre resurser och vara mer realtidsorienterade för användarna. Detta tillvägagångssätt är dock inte utan problem: tillfälliga portar, uttömda filhandtag på lastbalanserare, är mycket intressanta problem, och vi kommer att prata om dem senare.

Sökning (Elasticsearch)

Spoiler: Det finns inte mycket att bli entusiastisk över här. Webblagret använder Elasticsearch 1.4 och implementerar en ultralätt, högpresterande StackExchange.Elastic-klient. Till skillnad från det mesta planerar vi inte att göra denna del öppen källkod, helt enkelt för att den exponerar en mycket liten delmängd av de API:er vi behöver använda. Jag är säker på att att göra det offentligt väger tyngre än förlusten och bara kommer att förvirra utvecklarna. Vi använder elastic:/search på dessa ställen för att räkna ut relaterade frågor och ge förslag när vi ställer frågor.

Varje elastiskt kluster (ett för varje datacenter) innehåller 3 noder, var och en med sitt eget index. Karriärsajten har också några ytterligare index. En något mindre standardiserad del av vår konfiguration i elastiska kretsar är att vårt kluster med tre servrar är lite kraftfullare än den vanliga konfigurationen: varje server använder SSD-lagring, 192 GB minne, dubbel nätverkskapacitet på 10 Gbps bandbredd.

Samma applikationsdomän som Stack Server (ja, vi blev slängda runt av .Net Core här) har också en taggmotor, som också använder Elasticsearch för kontinuerlig indexering. Här använder vi ett litet trick, som att använda ROWVERSION i SQL Server (datakällan) för att jämföra med "sista plats"-dokumentet i Elastic. Eftersom det tydligen är sekventiellt är det lätt för oss att genomsöka och indexera innehåll om det ändras efter senaste besöket.

Huvudanledningen till att vi använder Elasticsearch istället för teknologier som SQL fulltextsökning är dess skalbarhet och kostnadseffektivitet. SQL är relativt dyrt för CPU:er, medan Elastic är mycket billigare och har många nya funktioner på sistone. Varför inte använda Solr? Vi behöver söka över nätverket (med flera index samtidigt), och Solr stöder inte detta scenario vid tidpunkten för våra beslut. Anledningen till att vi inte har använt 2.x än är att typerna har förändrats mycket i 2.x, vilket innebär att vi måste indexera om allt om vi vill uppgradera. Jag har helt enkelt inte tillräckligt med tid att planera för kravändringar och migreringar.

Databas (SQL Server)

Vi använder SQL Server som en enda sanningskälla. All data i Elastic och Redis kommer från SQL Server. Vi har två SQL Server-kluster och är konfigurerade med AlwaysOn-tillgänglighetsgrupper. Varje kluster har en primärserver i New York (som tar nästan all belastning) och en replikaserver, utöver en replikaserver i Colorado (vårt katastrofåterställningsdatacenter). Alla kopieringsoperationer är asynkrona.

Det första klustret är en uppsättning Dell R720xd-servrar, var och en med 384 GB minne, en PCIe SSD med 4 TB utrymme och två 12-kärniga CPU:er. Den inkluderar Stack Overflow, Sites (det är ett dåligt namn, jag förklarar det senare), PRIZM och Mobiles databas.

Det andra klustret är en uppsättning Dell R730xd-servrar, var och en med 768 GB minne, en PCIe SSD med 6 TB utrymme och två 8-kärniga processorer. Detta kluster innehåller alla andra databaser, inklusive Careers, Open ID, Chat, undantagsloggar och andra Q&A-sajter (t.ex. Super User, Server Fault, etc.).

På databaslagret vill vi hålla CPU-användningen på en mycket låg nivå, även om CPU-användningen i praktiken kommer att vara något högre när vissa planerade cacheproblem uppstår (som vi felsöker). För närvarande är NY-SQL02 och 04 de primära servrarna och 01 och 03 är replikaservrarna, och vi startade om dem idag på grund av SSD-uppgraderingen. Så här presterade de under de senaste 24 timmarna:



Vår användning av SQL är mycket enkel. Enkelt betyder snabbt. Även om vissa frågesatser kan vara förvrängda, sker vår interaktion med SQL på ett ganska naturligt sätt. Vi har en del äldre Linq2SQL, men alla våra nya utvecklingar använder Dapper, vårt öppna mikro-ORM-ramverk som använder POCO. Låt mig förklara det på ett annat sätt: Stack Overflow har bara en lagrad projeder i sin databas, och jag tänker ta bort denna sista lagrade projete och ersätta den med kod.

Bibliotek

Nåväl, låt oss ändra oss, här är saker som kan hjälpa dig mer direkt. Jag har nämnt några av dem tidigare, men jag ger dig en lista över de många open source-.Net-bibliotek som vi underhåller och som alla använder. Vi gör dem open source eftersom de inte har något kärnvärde i affärsvärlden, men de kan hjälpa utvecklare runt om i världen. Jag hoppas att du kan använda dem nu:

  • Dapper (.Net Core) – Ett högpresterande mikro-ORM-ramverk för ADO.Net
  • StackExchange.Redis – En högpresterande Redis-klient
  • MiniProfiler – en lättviktsprofilerare som vi använder på varje sida (stöder även Ruby, Go och Node)
  • Exceptionell – För felloggning i SQL, JSON, MySQL, etc
  • Jil – Högpresterande JSON-serialisering och deserializer
  • Sigil – .Net CIL Generation Helper (används när C# inte är tillräckligt snabbt)
  • NetGain – Högpresterande websocket-server
  • Opserver – Övervakningsdashboard som direkt pollar de flesta system och kan hämta information från Orion, Bosun eller WMI
  • Bosun – Övervakningssystem i bakgrunden, skrivet i Go






Föregående:Enum Enum kontrollerar om ett värde ingår i ett ENUM
Nästa:Hur kan jag hitta MB snabbt
Friskrivning:
All programvara, programmeringsmaterial eller artiklar som publiceras av Code Farmer Network är endast för lärande- och forskningsändamål; Ovanstående innehåll får inte användas för kommersiella eller olagliga ändamål, annars kommer användarna att bära alla konsekvenser. Informationen på denna sida kommer från internet, och upphovsrättstvister har inget med denna sida att göra. Du måste helt radera ovanstående innehåll från din dator inom 24 timmar efter nedladdning. Om du gillar programmet, vänligen stöd äkta programvara, köp registrering och få bättre äkta tjänster. Om det finns något intrång, vänligen kontakta oss via e-post.

Mail To:help@itsvse.com