Senaste inläggen RSS

Amazon S3 och CloudFront

Av murtlest den 29 September 2009

Detta Àr en ny del i serien av inlÀgg som riktar sig till vÄra nördiga anvÀndare som Àr intresserade av tekniken bakom Pusha.

Pusha vÀxer sÄ det knakar, för ett halvÄr sedan vÀxte vi ur vÄrt dÄvarande webbhotell och flyttade istÀllet över Pusha till en dedikerad server hos Bahnhof. Nu börjar Àven denna server vara nÄgot i minsta laget för oss och vi kommer inom en inte allt för avlÀgsen framtid förmodligen behöva dela upp vÄr infrastruktur sÄ att vi har en databasserver och sedan x antal webbfrontar. För ett par veckor sedan genomförde vi dock en ÄtgÀrd som gjorde att vi kan vÀnta ytterliggare ett tag med denna omstrukturering.

Vad vi gjorde var att vi flyttade alla statiska filer till Amazon S3 (Simple Storage Server).

Simple Storage Server

S3 Àr en tjÀnst som Amazon tillhandahÄller och som har skapats just för att lÄta anvÀndare lagra statiska filer. Detta kan anvÀndas till mÄnga olika saker, man kan till exempel anvÀnda det för att lagra backuper eller som i Pushas fall, för att leverera de statiska delarna av en webbsida.

Requests

NÀr man skriver in en webbadress frÄgar webblÀsaren först servern efter den aktuella sidan, webbservern returnerar (i de flesta fall) html-koden för sidan, sedan gÄr webblÀsaren igenom koden och tittar efter bilder, externa css- och javascript-filer o.s.v. och gör sedan en request till servern för varje sÄdan fil som den behöver för att kunna rendera webbsidan. Man kan ganska enkelt komma upp i 100 requests pÄ bara en sidladdning frÄn en enda anvÀndare. Det Àr requests som tar bÄde cpu-kraft och minne frÄn servern. För Pusha sÄ blir det, förutom sjÀlva sidvisningarna, Àven en hel del requests frÄn tidningar och bloggar som har lagt in nÄgon av vÄra pushaknappar. De största tidningarna, som DN och SVD, har som tur Àr lagt bilderna pÄ sin egen server. Men mÄnga lÀnkar Àven in dem direkt frÄn oss. Detta Àr helt okej för vÄr del, men det gör att servern inte bara fÄr requests nÀr nÄgon gÄr in pÄ Pusha.se, utan Àven varje gÄng nÄgon gÄr in pÄ andra bloggar och tidningar.

Kostnad

SÄ den stora fördelen med att anvÀnda sig av Amazon S3 istÀllet för att lÄta sin egen server leverera alla statiska filer Àr att lasten minskar pÄ den egna servern. En annan fördel med just Amazon S3 Àr att man bara betalar för det man anvÀnder. AlltsÄ kan Àven vÀldigt smÄ företag och privatpersoner anvÀnda S3 utan att det behöver bli speciellt dyrt.

Vi gör ca en halv miljon requests om dagen till Amazon S3 och vi fÄr endast betala ca 250 kronor i mÄnaden för tjÀnsten. Dock lagrar vi endast vÀldigt smÄ filer. Aktuell prissÀttning kan du hitta hÀr.

Kom igÄng med S3

För att börja anvÀnda Amazon S3 mÄste du först skaffa ett Amazon-konto och sedan lÀgga till S3-tjÀnsten (som mÄste vara kopplat till ett kreditkort). Detta kan du göra pÄ http://aws.amazon.com. NÀr du Àr registrerad och klar sÄ fÄr du ett Access Key ID och en Access Key Secret (ungefÀr som ett anvÀndarnamn och lösenord) som du anvÀnder för att komma Ät S3. Det finns mÄnga olika möjligheter för att administrera och ladda upp filer till ditt S3-konto, till exempel finns det kommandoradsklienter och ett API. För att bekanta sig med S3 kan jag rekommendera den webbaserade klienten s3fm.com. Denna klient Àr helt skriven i javascript sÄ din Access Key Secret lÀmnar aldrig din webblÀsare.

API och PHP

Ofta vill man dock kunna ladda upp filer till S3 “automatiskt” frĂ„n en applikation, t.ex. vill vi pĂ„ Pusha att profilbilderna som anvĂ€ndaren laddar upp ska sparas pĂ„ S3. DĂ„ mĂ„ste man anvĂ€nda sig av Amazons S3 API. I Amazons dokumentation finns instruktioner för hur man anvĂ€nder API’t med php, tyvĂ€rr tycker jag att deras php-exempel Ă€r vĂ€ldigt dĂ„liga och utelĂ€mnar mĂ„nga viktiga detaljer. Jag brukar istĂ€llet anvĂ€nda en php-klass skriven av Jason Kruit för att komma Ă„t API’t och alla exempel i detta inlĂ€gg anvĂ€nder sig av den klassen. Du kan ladda ned klassen hĂ€r, och du hittar dokumentation för den hĂ€r.

Buckets, Objects och Keys

S3 bestÄr av tre saker; buckets, objects och keys. För att kunna lagra nÄgot pÄ S3 sÄ mÄste du ha en bucket att lagra det i. Det vanliga Àr att du har en bucket per projekt eller domÀn. Man Àr begrÀnsad till max 100 olika buckets sÄ en per projekt Àr ganska lagom, det Àr inte lÀmpligt att skapa buckets som man skapar kataloger pÄ en vanlig server eftersom man dÄ ganska snabbt kommer upp i 100. SÄhÀr skapar du en bucket:

S3::setAuth('access_key','access_secret');
S3::putBucket('images.example.com', S3::ACL_PRIVATE, "EU");

Bucketen vi skapade hÀr fÄr namnet images.example.com, man bör alltid döpa sin bucket som subdomÀnen man tÀnkt peka till den, detta dels för att man dÄ undviker namnkonflikter med andras buckets och för att det Àr ett mÄste om man vill anvÀnda CloudFront, som jag kommer till senare.

Objects Ă€r sjĂ€lva filerna med tillhörande metadata som man vill lagra pĂ„ S3. Varje object kan vara upp till 5 gigabyte. Varje object identifueras med hjĂ€lp av namnet pĂ„ bucketen samt en key. En key Ă€r alltsĂ„ i princip namnet pĂ„ filen. En key kan innehĂ„lla snedstreck sĂ„ du kan fĂ„ det att se ut som vanlig katalogstruktur genom att skapa nycklar som “backups/2009/10/01/databas.tar.gz”. API’t innehĂ„ller dessutom metoder för att hĂ€mta filer med ett speciellt prefix sĂ„ du kan enkelt hĂ€mta en lista pĂ„ alla filer som har en key som börjar med “backups”, nĂ„got som gör att det Ă€r ganska enkelt att “hĂ€rma” vanliga filsystem med S3. I klienten s3fm sĂ„ listar man tillochmed prefixen som kataloger trots att det egentligen inte finns nĂ„got annat Ă€n en massa keys och objects i en bucket.

LÄt oss ladda upp en fil till vÄr bucket:

S3::putObject(S3::inputFile('/tmp/bild.png'),
              'images.example.com',
              'bild.png',
              S3::ACL_PUBLIC_READ);

RĂ€ttigheter

Observera att jag har satt olika rÀttigheter pÄ bucketen och objektet. Det finns ett antal olika rÀttigheter man kan sÀtta pÄ sina buckets och objects, nÀr det gÀller att leverera statiska filer till en webbsajt sÄ ska alla anvÀndare sjÀlvklart ha lÀsrÀttigheter. Dock bör man undvika att ge alla anvÀndare lÀsrÀttigheter för sjÀlva bucketen, annars kommer de kunna lista alla filer som finns i bucketen vilket man oftast vill undvika.

HTTP-Ätkomst

NĂ€r du skapat en bucket och lagt in ett object med en viss key sĂ„ kan du komma Ă„t ditt object pĂ„ följande url: http://bucket.s3.amazonaws.com/key (ersĂ€tt “bucket” med namnet pĂ„ din bucket och key med din key). Om du vill kunna anvĂ€nda din egen domĂ€n för att peka pĂ„ dina statiska filer sĂ„ kan du sĂ€tta upp ett CNAME-record i dina DNS-instĂ€llningar. Om du t.ex. döpt din bucket till images.example.com sĂ„ kan du skapa ett CNAME-record som pekar till http://images.example.com.s3.amazonaws.com

CloudFront

Som ni sÀkert vet har en servers fysiska position en avgörande betydelse för hur snabbt den kan leverera data till klienterna. AlltsÄ vill man gÀrna ha en server sÄ nÀra sina anvÀndare som möjligt. Amazon har servrar pÄ mÄnga olika platser i vÀrlden och man kan vÀlja att fÄ sin bucket placerad i Europa nÀr man skapar sin bucket. TyvÀrr har inte s3fm denna funktionalitet inbyggd Ànnu sÄ vill du skapa en EU-bucket mÄste du göra det via APIt.

I fallet med Pusha kan vi vĂ€lja att prioritera anvĂ€ndare frĂ„n Europa eftersom det Ă€r en svensk sajt men för sajter som riktar sig till anvĂ€ndare frĂ„n hela vĂ€rlden Ă€r det svĂ„rare. DĂ€rför har Amazon Ă€ven skapat en tjĂ€nst som heter CloudFront som ser till att lĂ€gga dina S3-filer pĂ„ servrar som Ă€r sĂ„ nĂ€ra anvĂ€ndarna som möjligt. Jonas Lejon som bland annat driver Bloggy har gjort en jĂ€mförelse mellan att lĂ€gga filerna i en EU-bucket eller att aktivera CloudFront för en bucket och det visar sig att CloudFront Ă€r snabbare. DĂ€rför anvĂ€nder vi CloudFront Ă€ven för Pusha – trots att vi bara har Sverige som mĂ„lgrupp.

Att sĂ€tta upp en CloudFront “distribution” Ă€r inte speciellt svĂ„rt, man anger vilken av ens buckets man vi skapa en distribution för och en subdomĂ€n om man vill ha en fin domĂ€n för sin distribution.

S3::createDistribution($bucket, true, array("images.example.com"));

NĂ€r man gjort detta sĂ„ kommer det ta en stund innan distributionen Ă€r “deployed”, enligt Amazons dokumentation ska det bara ta ett par minuter men jag har varit med om att det tagit upp till en timme, sĂ„ bli inte orolig om det dröjer ett tag.

$dists = S3::listDistributions();
foreach($dists as $dist){
   echo '<p>Status: ' . $dist['status'] . '</p>';
   echo '<p>Domain: ' . $dist['domain'] . '</p>';
}

Amazon skapar en slumpad domÀn för din CloudFront distribution i stil med d1k31g0nhq45vg.cloudfront.net. Du kan sÀtta upp ett CNAME-record som pekar till denna domÀn och pÄ sÄ sÀtt fÄ en snyggare domÀn.

Versionering

NÄgot jag tyckte var en stor nackdel med CloudFront först var att om man uppdaterar en fil pÄ S3 sÄ tar det upp till ett dygn innan filen har uppdaterats pÄ alla noder. Detta kÀndes som ett stort problem nÀr man vill deploya en ny version av sin webbapplikation med t.ex. en annan logga, att det kan ta ett dygn innan vissa av filerna uppdateras. Lösningen pÄ detta problem Àr att alltid ha med ett versionsnummer i sin key. NÀr vi skapar en ny Pusha-version nu för tiden sÄ laddas först alla statiska filer upp till S3 med en key som ser ut nÄgot i stil med /121/i/logo.png, dÀr 121 Àr den nya versionens nummer. NÀr vi sedan deployar den versionen sÄ ligger alla filer redan pÄ S3. Eftersom de flesta av vÄra bilder lÀnkas in i vÄr css som ocksÄ ligger i samma bucket och under samma version sÄ behöver vi inte ens versionsnumret dÀr utan kan lÀnka in bilderna relativt:

   background:#fff url("../i/body-bg-long.png") repeat-x;

Caching

NÀr man har versionsnummer pÄ alla sina filer sÄ vill man sÀtta sÄ hÄrd caching pÄ dem som möjligt för att undvika onödiga requests, Àven om requestsen inte lÀngre segar ned din server sÄ fÄr du betala Amazon för varje request.

S3::putObject(
   S3::inputFile($file),
   $bucket,
   $key,
   S3::ACL_PUBLIC_READ,
   array(),
   array("Content-Type"=>AmazonS3::getContentType($file),
         "Cache-Control" => "max-age=315360000",
         "Expires" => gmdate("D, d M Y H:i:s T", strtotime("+5 years"))
   )
);

Nackdelar

Det enda jag egentligen tycker att Amazon gjort lite dumt Ă€r att de inte tillĂ„ter nollĂ€ngdsnycklar. Man kan med andra ord inte lĂ€gga nĂ„gon fil som “startsida” pĂ„ sin domĂ€n. I vanliga webbservrar brukar ju index.html laddas automatiskt nĂ€r man gĂ„r till domĂ€nen men med S3 finns det inget liknande sĂ€tt att skapa en förstasida. Detta gör att det i princip Ă€r omöjligt att hosta en hel webbsajt pĂ„ S3, nĂ„got som annars hade varit ett enkelt och billigt sĂ€tt för smĂ„ företag och privatpersoner som bara vill ha en statisk hemsida. Att Amazon kommer Ă€ndra pĂ„ detta Ă€r föga troligt. Det har varit bland de mest efterfrĂ„gade förĂ€ndringarna sedan 2006 och fortfarande har ingenting hĂ€nt. Anledningen till att de inte vill Ă€ndra pĂ„ det Ă€r att det skulle krĂ€va en förĂ€ndring av API’t som kan förstöra gammal kod. NollĂ€ngdsnycklar anvĂ€nds nĂ€mligen till att lista allt som finns i bucketen idag. Det Ă€r numera möjligt att sĂ€tta ett index-dokument för sin bucket vilket gör det möjligt att hosta en statisk sajt helt och hĂ„llet pĂ„ Amazon S3, sĂ„ nu finns det inte lĂ€ngre nĂ„gra nackdelar.

Fler Amazon-tjÀnster

Förutom denna lilla nackdel sĂ„ tycker jag att Amazon S3 och CloudFront Ă€r utmĂ€rkta tjĂ€nster. Amazon erbjuder Ă€ven andra “molntjĂ€nster” som t.ex. EC2 (Elastic Compute Cloud) som lĂ„ter dig sĂ€tta upp servrar dynamiskt dĂ€r du betalar per timme du anvĂ€nder servern. Jag har bara testat EC2 vĂ€ldigt kort och mitt första intryck Ă€r att det tyvĂ€rr Ă€r ganska dyrt om man vill anvĂ€nda det för att sĂ€tta upp webbservrar, det passar nog bĂ€st om man har tunga berĂ€kningsjobb som man vill köra intensivt under korta perioder.

SimpleDB Ă€r en annan Amazon-tjĂ€nst. Precis som det lĂ„ter sĂ„ Ă€r det en databas-tjĂ€nst. Dock Ă€r det ingen relationsdatabas, som MySQL. SimpleDB liknar mer Google’s BigTable, sĂ„ det Ă€r tyvĂ€rr inte sĂ„ enkelt att migrera till om man Ă€r van vid relationsdatabaser.

Jag tycker det Àr fantastiskt bra att Amazon erbjuder dessa tjÀnster, med nÄgra enkla knapptryck kan vilket litet företag som helst konkurrera pÄ samma villkor som Google och bara betala för det de anvÀnder.

Andra tjÀnster

För att minska detta inlÀggs ensidiga hyllande av Amazon sÄ tÀnkte jag avsluta med att lista nÄgra alternativ. Jag har inte testat nÄgon av dessa tjÀnster, men jag vill visa att det finns alternativ:
http://www.akamai.com/
http://www.pantherexpress.net/
http://limelightnetworks.com/
http://simplecdn.com/
http://bitgravity.com/

Hoppas ni tyckte detta inlÀgg var instressant och/eller lÀrorikt. Har du nÄgra frÄgor Àr det bara att lÀmna en kommentar pÄ Pusha sÄ ska jag försöka svara.

Skriv en kommentar pÄ Pusha »

29 Sep

Information

Om Pusha Blogg

Information om utvecklingen av sajten Pusha, en samlingsplats där du som medlem bestämmer innehållet genom att posta och rösta på länkar.

Hett på Pusha

Fler heta länkar

Knapp för bloggare

Pusha fïżœr bloggare

Visste du att du kan få fler besökare till din blogg med en Pusha-knapp?

Läs mer här »