Barbour Outlet Barbour Outlet Deutschland

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 »