![]() |
Hur kraftig server skall man ha?
Hej,
Håller på att utvecklar en iphone app som är ansluten till en databas, varje app kommer att pinga servern 1gång per sekund dvs den hämtar info från db'n varje sekund. Jag tänker lite långsökt och optimistiskt just nu men säg att man har 10M användare till appen som kommer vara gratis och säg att 1M använder appen samtidigt, det innebär att vi kommer att ha en väldans massa requests till databasen som är en mySQL databas, det jag undrar är hur kraftig server skall man ha för att kunna hantera detta? klarar mySQL detta? någon med någon erfarenhet av mass trafik, vad bör man tänka på? Är det lastbalansering mellan olika servrar som gäller eller ska man preppa en server med massor med RAM minne? Uppskattar all hjälp man kan få kring detta. |
Tyvärr är det tråkiga svaret: "det beror på".
Att alla användare skall pinga databasen varje sekund kommer ge dig huvudvärk om (när?) din app blir populär. Det kan bli mycket svårt att skala upp. Har du några möjligheter att rent arkitektursikt att lösa det på annat sätt? Har du funderat på VPS / en molnapplikation, det skulle kunna ge dig större möjligheter att skala upp om det smäller till. |
Har tyvärr inte så stenkoll på serverside tekniken, vad skulle en VPS/moln app innebära? Det är just därför jag är lite orolig säg att den växer och växar kraftigt så kan man med en server trycka in mer RAM minne men vet inte om det skulle räcka?
Skulle va snällt om du kunde utveckla detta med VPS / molnapp. |
Det finns mycket teori bakom det hela men räkna med att ett paket, hur litet det än är, kommer att belasta din lina med minst 64 bytes, eller ca 0,5kbit. Så, håller du ner paketstorleken till detta vid ditt "pingande" så belastas dina servrar med 500 Mbit/sek. Sen är det ju klart att det även innebär en miljon databasaccesser per sekund.
En normal server klarar kanske ett par hundra anrop per sekund i genomsnitt. Sen är det klart, att om varje förfrågan måste ut på hårddisken och samla lite data så klarar du som mest kanske 60 förfrågningar per sekund om du har en 7200rpm hårddisk, men det är högst teoretiskt. En vanlig databas är nog inte vad du skall ha ... |
Oj så pass, vad är det då man skall ha om inte en vanlig db?
Jag funderade på en dedikerad server med 16gb i ram minne och ett par Tbit i hårddisk och db'n är en mySQL, jag borde alltså räkna bort detta helt? |
En miljon pings mot databasen varje sekund? Det låter som om du har en klassisk subscriber-modell du vill tillämpa. Isåfall bör du istället lösa det med en applikation som hanterar anslutningar och hämtar kollektivt från databas/cache/nosql för sina anslutningar. Annars skapar du dig utmaningar du inte alls borde ha.
Det för tillfället mest populära valet för sådana typer av applikationer är nog node.js. Förut var det mer egenknackad java. En hyfsad mysql-burk klarar ett gäng tusen enklare frågor i sekunden utan problem. Att den bara skulle klara 60 skrivningar på en 7200 disk är kanske inte heller så bra slutsats. Förutsatt att du inte flushar till disk vid varje skrivning ska du lätt kunna komma upp i ett par hundra om det inte är för mycket data att skriva och mer sekventiellt än slumpmässigt. Behöver du nå en miljon reads per sekund bör du nog titta på färdiga klusterlösningar. Vill du inte släppa mysql finns det mysql cluster och percona cluster. Annars finns det gott om nosql-lösningar med kluster-arkitektur. Men då du inte sagt något alls om din data är det svårt att försöka rekommendera något. Men som sagt, rent arkitekturellt misstänker jag (som coredev redan nosade på) att du är helt fel ute. |
Nu vet jag ju inte vad det gäller för app, men här kommer några generella tankar.
- När det gäller arkitekturen på din programvara så behöver inte allt alltid ske i realtid, ibland räcker det med att det verkar ske i realtid. - En sekund är en väldigt kort tid för en människa, vi hinner inte ens reagera på den tiden. Är du säker på att var femte sekund inte räcker? Redan där har du minskat belastningen med 1/5. - Måste man vara uppkopplad i alla lägen i appen, finns det tillfällen då man inte behöver polla servern lika ofta / öht? Genom att stänga av pollningen när t.ex. en dialogruta öppnas så kan du spara mycket resurser. - Vissa data ändras mer sällan, memcached kan vara din vän i vissa sådana fall. |
Lite mer info om själva appen, så att ni får en bättre bild av det hela...
Appen är ett ord spel, där man lägger ord i brickor och man möter en motspelare, brickläggandet sker i realtid, dvs man lägger en bokstav och den visas hos motspelaren direkt, så det är ett konstant pingande. Motspelaren lägger en bricka, den uppdaterar DBn och därefter så sitter motspelaren och lyssnar på db'n och hämtar info't därifrån. Det är inga stora datamängder som hanteras utan det är mer att dte är uppslag mot DBn konstant. Sedan finns det ett chatt där man sitter och lyssnar på DBn konstant, detta går ju att lösa med en uppdatera knapp men det känns lite B-aktigt. Chatten fungerar på samma sätt, man skriver och hämtar infot från en DB tabell. Skulle en klustrad mySQL lösning fungera i detta syfte? |
Att försöka lösa det problemet genom att hämta från databasen hela tiden är helt fel väg att gå om du vill få någon som helst prestanda i systemet.
För varje "action" (lägga bricka, skriva meddelande) behöver du en skrivning till databasen, men det finns ingen anledning för varje användare att fråga databasen efter ny data precis hela tiden var och en för sig. Istället skulle du kunna ha en server-applikation som varje klient ansluter till. Varje anslutning premenurerar på olika kanaler. T ex wordgame-2323 eller chatt-2342 (om de nu är skilda). För varje skrivning så skickas även datan till denna server-applikation som skickar meddelandet till alla subscribers över anslutningen som redan är öppen. Det är endast när en helt ny anslutning, eller en disconnect sker, som det finns anledning att hämta allt från databasen. Eventuellt kan också denna server-applikation skicka kompletta spel-informationen för ordspelet varje gång en handling sker - med vettig serialiserad datastruktur rör det sig nog inte om mer än någon eller några kb? Men vill du absolut inte förändra något i ditt tänk kan du mycket väl lösa det genom mycket sämre prestanda och ökade skalbarhetsproblem genom en anpassad klusterdatabas. |
En server är inte skalbart i grunden, även om det säkert funkar till en viss nivå.
Jag föredrar mer kraftiga VPS paket, eller flera VPS paket utspridda på flera server. Eller i vissa fall flera fysiska servrar, dock flera fysiska servrar blir en viss begränsning och osmidighet för en kund att hantera än VPS. Fördelar med virtuell miljö är att man kan växa i steg, du kan bygga ett MySQL kluster som du lägger till mer noder efter belastning. Efter du har antagligen väldigt mycket mer read en write, och ett kluster för hantera endast stor mängd read är inte så komplicerat. Se till att ha mycket minne så du har hela DB i minnet. |
Appen är så gått som klar och den är ansluten mot mySQL etc, så att ändra hela tänket nu skulle kännas som en rejäl uppförsbacke men om det är vad det krävs så får man helt enkelt tänka om.
Hur skulle en VPS lösning se ut? skulle vi kunna vidare på samma ätnk med VPS? |
Då förstår jag vad du vill uppnå. Jag är ingen fena på det direkt men det är helt klart nån push-teknik du skall använda. Då behöver du bara skicka data från servern till anslutna klienter när det finns data att skicka.
Hur som helst så är det inte webbservern som skall hantera dessa anslutningar utan dedikerade spelservrar. Själva anropen och inloggningarna skulle kunna, men inte nödvändigtvis, ske via webbservrar. Men ett tips om man vill att klienten skall polla med jämna mellanrum är även att skicka med lite data tillbaka som talar om hur hög belastningen på servern är, då kan klienterna dr ut lite på pingintervallet när belastningen är hög. |
Citat:
Mitt råd är du skall köra igång som det är. Skulle din app bli jättepoppis så tar du det då. :-) |
Citat:
En VPS-lösning läggs optimalt på ett moln med ordentligt med on-demand instanser lediga vid varje tillfälle, t ex amazon eller rackspace. I ditt fall behöver du egentligen ingen replikering mellan VPSerna utan ett spel behöver bara kommas åt via en instans. Nästa instans kan du dirigera andra spel mot. Applikationen måste då vara medveten om vilka instanser som får vilka spel. För två servrar kan du t ex låta jämna/udda ids hamna på varsin server. Sen behöver du användarna på en central server (som i sin tur kan replikeras för att öka prestandan) samt en id-generering centralt så att id på ett spel blir unikt över alla instanser och därmed kan dirigeras rätt. Vill du läsa på lite om fenomenet brukar det kallas database sharding och är ett väldigt vanligt tillvägagångssätt för större datamängder eller last. Märk väl att du måste ha en sharding som du kan ändra i realtid för att du ska ha ordentlig nytta av det. Försöker du med replikering av all data till alla instanser kommer du vid en viss last stöta på större och större fördröjning i replikeringen. Till slut kommer det behöva lösas med flera servrar som i en hierarki sköter replikeringen - väldigt mycket overhead, låg fault-tolerance och väldigt omständigt att hantera. Främsta anledningen till denna utgång är att du endast har en tråd till replikeringen i MySQL medans writes till mastern använder flera trådar. |
Grunden till börja bygga en skalbar lösning från början är att börja med sätta upp en SLB.
Sedan kan du bygga på med nya MySQL / Webservrar bakom efter belastnings behov. Beroende på nivå av MySQL kan du sätta upp Galera Cluster, exempelvis Galera Multi-Master Replication lösning. Vilket har en hel del fördelar. Sedan om man har väldigt mycket ram så du har DB i minnet bara samt väldigt fet write cache så spelar diskarna väldigt liten roll i det hela. Då är det mer fråga om CPU för hantera frågorna. |
Tack för alla svar, det var inte så lätt som man trodde, har tittat lite på det här med cloud, man verkar kunna öka det både i bredden och längden med claud, fast vågar inte ens tänka tanken på hur mycket det skulle kosta med de volymerna jag räknar på. Såg att citynetwork hade en claud lösning men som sagt vet inte om man vågar köra på Claud, då sitter man fast där i molnet och är tvungen att öka hela tiden och kostnaderna ökar proportionenligt.
|
@Clarence, har tittat på en klustrad variant med 2mysql maskiner och en front end och så kör jag memcache på mysql maskinerna men det är som du säger att det kommer skapa problem, du nämnde något med en applikation för att hålla datat och sedan när det är klart så skriver man till DBn hur skulle det se ut i det här fallet? Vår app går som sagt ut på att då man lägger en bricka så uppdateras DBn med brickan, när man startar ett spel och utmanar en annan person så initierar vi en rad i en tabell med GameId etc, kan man då via den här applikationen du nämner lagra all brick data och sedan när spelet är slut så trycker man in det i DBn?
Frågan är då hur klarar den här applikationen att hantera all den här datan är det inte samma sak som att skriva till DBn? kommer kräva ett riktigt stort minne att hålla 1M spel som konstant pingar applikationen i shack eller är jag helt ute och cyklar? Är beredd på att ändra i tänket och koden för att få det här att lira, med din lösning skulle det räcka med en kraftig maskin? |
Att ha en subscriber-modell innebär ingen skillnad i hur du lagrar informationen (db, memcache). Det innebär inte nödvändigtvis heller någon förändring i hur du hämtar informationen (db, memcache). Däremot så gör det ofantlig nytta i att minska antalet requests till din applikation.
Med en pull-struktur, liksom den du beskriver, måste varje användare gå till din server och ställa en fråga för varje möjlighet som ska ges för uppdatering. Med en push-struktur med subscriber-modell ansluter de till din server i början av spelet. Varje gång någon lägger en bricka skickas även det meddelandet in till din push-server (eller om den läser ny brickor t ex var 0.1 sekund). Denna skickar sedan ut meddelandet till de som är registrerade som mottagare (i ditt fall en motståndare) över den redan öppna anslutningen utan att en besökare behöver belasta din server med ett extra request för varje tick i uppdateringen. Den skickar bara vad den behöver skicka, när det ska skickas, bottleneck här ligger i antalet spelare istället för hur snabbt saker ska hända. För en snabb lösning, som jag dock är osäker på hur väl den skalar, titta på socket.io och subscriber model. 1M samtidiga spelande kommer du aldrig klara på en burk, oavsett metod eller kod.Men du har en väldig overhead om du ska låta dina användare pinga en gång i sekunden jämfört med att använda en push-modell. Du kommer inte lyckas skala till en miljon samtidiga användare utan extern expertis om du inte gör ett rejält djupdyk i skalbarhet och prestanda av liknande applikationer. När man kommer upp i sådana nivåeer är det också viktigt att ha finansieringen klar för sig. Det är därför de flesta stora startups har investerare, inte för att begränsa sin handlingsförmåga. |
Allt är en kostnadsfråga i grunden, tekniskt kan du ha 100 servrar i ett mySQL cluster som i sin tur skalar väldigt bra i prestanda. Men är inte gratis.
Sedan kan jag nog se stora problem med en push-modell med om det handlar om flera 100 tusentals aktiva spelare/anslutningar. Då tror jag att man får dela upp det i "små cluster/grupper" där olika användare hamnar i olika cluster grupper som är helt skild och en central db struktur som synkar det nödvändiga mellan varandra. |
Ok får ta och kolla på subscriber metoden, är den avancerad har du någon erfarenhet utav den? En annan grej jag kom att tänka på är om man har ett lager mellan DB dvs en webbservice som man ansluter till, den skriver i sin tur en xml fil för varje spel när spelet är klart och får status finished så lägger man in datat i DBn och raderar xml-filen?
|
Citat:
Du kanske till och med skapar en rad i databasen vid spelets början och så heter filen radens id-nummer + .xml. Kanske kan du skippa XML för att snabba upp det ytterligare på servern, Nyckel=Värde på en ny rad räcker ofta mycket långt. JSON kan vara ett mellanalternativ om du behöver lite mer struktur. En ytterligare optimering är att du skriver en egen serverapplikation i t.ex. c++ istället för att använda en webserver + ett scriptspråk. :-) |
Tror du att det skulle räcka med en server då, att man har en dedikerad server med 32gb i ram och mysql installerad på den? är xml snabbare än txt filer om man kör den här varianten? eller spelar det ingen roll om man kör xml eller txt filer?
Så tanken blir så här man har en tabell som heter Games och med tabellerna enligt nedan: |Games| gameID Player1 Player2 TimeStamp Chat sedan heter txt eller xml filen det som står i gameID.txt man lagrar dessa txt filer lokalt i en mapp när ett spel får status avslutat så skriver man in det datat i databas tabellen och deletar txt filen? Vad skulle jag kunna göra med JSON i det här sammanhanget aldrig använt det? Vad skulle serverapplikationne göra? skulle dessa skapa xml filerna eller vad är tanken med serverapplikationen? Har du någon erfarenhet av detta och skulle kunna hjälpa till naturligtvis mot betalning. |
Jag skulle inte placera kolumnen 'Chat' i din Games tabell.
Jag tror personligen det blir bättre om du skapar en tabell enbart för chatten. |Chat| gameID int primary player int/var # i denna kolumn har du antingen användarens medlemsid, eller spelarens namn. text varchar Hur har du tänkt att din tabell ska agera? Ska en ny rad läggas till i databasen för varje speländring, eller har du tänkt uppdatera den befintliga raden? Jag tror personligen att du måste spendera mer tid på att effektivisera din nuvarande kod, databashantering, och eventuell cachning istället för att fundera hur kraftig server du behöver. |
Att implementera en subscriber-modell är inte speciellt avancerat. Men förstår du dig inte på den kommer du givetvis inte kunna skriva koden ännu. Vill du göra det enkelt för dig kan du använda node.js med socket.io och sedan på klientsidan antingen använda ett bibliotek för websockets eller kommunicera genom en osynlig webview.
Att skriva till en mellanlagring i form av en XML-fil/JSON förstår jag inte riktigt anledningen till. Har du en väl konfigurerad sql med buffring av writes kommer du få mycket bättre throughput på den än att manipulera ett json/xml-dokument varje skrivning. Som captaindoe är inne på tror jag också du försöker fokusera för mycket på hur kraftig burk du behöver. Om du istället fokuserar på att skapa en effektiv kod som du dessutom kan skala upp till flera servrar utan problem så lägger du tiden på rätt ställe. Du bör inte försöka dimensionera för 1M användare från start, du bör ta de enkla stegen som förenklar det problemet senare. |
Intressant tråd!
Till att börja med vill jag säga att det är väldigt svårt att lyckas ordentligt med mobilappar i dagens stenhårda konkurrens. Därför tycker jag att man rent tekniskt ska göra det så enkelt för sig möjligt i den första releasen utan att göra för mycket avkall på kvaliteten hos användaren för att se hur det går med appen. Det handlar väldigt mycket om tur och timing för att lyckas, samt att givetvis ha en bra app som folk vill ha. Det gäller att få en bra start. Fingertoppskänsla kan reducera turkfaktorn en del, men inte eliminera den. Utifrån detta skulle jag ge dig följande råd: Investera inte för mycket pengar och tid på att göra det perfekt tekniskt. Lansera och testa först och ta tag i problemen efterhand som de uppkommer, gärna med lite framförhållning så försök vara förutseende. Kör på som du tänkte ifrån början, fast du kanske ska justera ned pull-tiden en del(testa dig fram vad som fungerar, men du kan ju börja med den ganska låg och sedan tycka ut en uppdatering om belastningen blir hög). Ha dock i åtanke att du så småningom behöver ändra till en subscriber/push-teknik. Jag tror du kan komma upp upp hyfsade volymer om du väljer rätt teknik på serversidan. Mitt förslag där är följande: - Kör MySQL i botten om det är det du är mest bekväm med(tänk på index och struktur). - Framför databasen kör du memcached(eller något annat cachesystem) för att hantera all aktiv data. - För att göra det enkelt för dig kan du kör med en webbserver för att hantera kommunikationen. Du behöver då en webbserver som kan hantera många samtidiga användare och många anslutningar. Mitt förslag här är Nginx. Hur det sedan ska fungera är att när en spelare gör ett drag så sparas detta givetvis ned i databasen. Men du sparar även detta direkt i memcached(sätt en ganska lång time-to-live/cachetid så att den inte behöver refreshas hela tiden, t.ex. 1 dag. optimera detta efter hur appen fungerar). När motspelarens app ansluter till servern kollar du i memcached om datan finns där, vilket den bör göra om inte uppdateringen var mer än ett dygn(cachetiden) sedan. Med det här systemet kommer det nästan bara vara updates/inserts emot databasen och det finns inget jättebehov för att detta görs i realtid heller(viss fördröjning i skrivningarna är helt okej). Läsningarna kommer normalt varken röra databasen eller hårddisken(om du kör någon opcode cache t.ex. APC) så det kommer inte kräva mycket prestanda för höga volymer. För att göra hårdvaran billig(vid små volymer) och skalbar bör du som sagt köra någon cloud-lösning. Då kan du skala upp din server väldigt enkelt vid behov. När det inte längre räcker med en server kan du klona din server till flera och sätta upp en lastbalanserare. Ett första enkelt steg innan det kan vara att separera ut MySQL-databasen till en egen server. Har du lite erfarenhet av detta sätter du upp detta på en timme. Logiken på servern kan du snabbt koda ihop i t.ex. PHP. Med det här systemet kan du definitivt hantera tusentals användare på en ganska enkel server. 40-50 000 hits per sekund bör gå att få till. |
Att skriva direkt till databasen är verkligen inge bra ide. Det som blir mer populärt numera att lägga ut vissa funktioner till andra som egentligen inte vill hålla på med, Apple har t.e.x game center för att kunna bygga enklare typer av spel utan att behöva ha egna servrar. Sen är det som alltid att ska man bygga något bra skalbart system så kräver det tid och pengar.
|
Skulle kollat på Amazon AWS för skalbarhet. Plus att jag tror det även finns "Iphone database hosting" för folk som vill att någon annan sköter allt det och kan fokusera på appen.
|
Citat:
Lätt att sätta upp med Juggernaut (https://github.com/maccman/juggernaut). Annars har jag som tumregel på Amazon AWS, 10-50 unika simultananvändare (50 är ganska stabilt om det är t.ex. ett forum eller community) per process per kärna, beroende på applikationens komplexitet/storlek. RAM är oftast inget problem innan saker ska börjas cachas i minnet. Med vänlig hälsning, Robert |
Tack för era svar!
Det stämmer att det är svårt att lyckas med appar men har en känsla gällande just den här appen och därför vill jag göra rätt från början, för om spelarna märker av störningar i systemet så tappar den värdighet och man lägger undan den utan att rekomendera den till sina vänner. Jag valde att köra en sån här lösning vad gäller serverskde: 1front end maskin som finns i en molntjänst (anl till att jag inte kör amazon eller andra cloud lösningar helt och hållet är att jag behöver bra diskar) Sedan har jag 2klustrade db- servrar med mysal på bakom webbfronten, och det är rätt så kraftiga maskiner jag har. Kör för tillfället med vanliga sql satser men funderar på att gå över till memcache och NoSQL om det visar sig att appen växer, på så sätt kan kag både efffektivisera kod och miljö. Jag hoppas ovan är en bra lösning, då är vi inga gurus på att skriva bra sql'er och undrar vad det är man bör tänka på vid vanliga select, updates och inserts till enskilda tabeller utan några avancerade joinar? |
Citat:
Jag skulle hur som helst starkt rekommendera att ni mellanlagrar så mycket som möjligt i något cachesystem som, t.ex. memcached. Det är väldigt enkelt att implementera. Det finns lösningar för att köra NoSQL i MySQL också med riktigt bra prestanda. Då kan man köra vanliga SQL-queries, fast med vissa begränsningar. |
Just nu ligger vi på en windows testserver med stöd för php och mysql databas, sedan gör vi enkla sql queries till databasen. Då vi går i produktion kommer vi att ha 3 servrar 1 webfront och 2 klustrade servrar med mySQL i.
Funderar på att köra memcache och sedan för att öka prestandan än mer gå över till NoSQL. @ITisGood hur skulle en nosql query se ut i php koden om man skall skriva till en mySQL databas, vad gäller memcache (värt att notera har ingen erfarenhet av varken det ena eller andra) fyller det någon funktion om datat man selectar alltid är annorlunda? eller faller dess funktion då? för antar att det är det som selectas cachas och sedan hämtar man det från memcachen istället för databasen? I vårt fall är det konstant nytt data som man hämtar från DBn kan hända att det är samma i vissa fall då vi alltid requestar databasen för att se om någon ny info har tillkommit DBn, detta för att få en realtid känsla på det hela. |
Citat:
Använder du memcache är poängen att du INTE ska kolla av databasen varje request. Istället dubbellagrar du informationen du behöver kolla av, ofta denormaliserat i memcache och normaliserat i databasen. På så sätt går du vid varje read request och kollar om datan du behöver finns i memcache (man brukar sätta en time to live på data i memcache så det finns risk att den har expirerat) och går bara till databasen när den inte finns. Fördelen är att både svarstider och last på servern sjunker rejält. Det finns i princip inga sajter med mycket trafik som inte har denna funktionalitet på några delar av sajten (inte alltid memcache, men någon typ av minnescache). Allt annat är att kasta pengar i sjön och skapa problem i onödan. |
Bör inte varnish https://www.varnish-cache.org/ vara en bra teamspelare för hårt belastade applikationer.
|
Alla tider är GMT +2. Klockan är nu 18:27. |
Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson