Lav dit eget CDN (Content Delivery Network)

Hvis du har mange statiske filer som folk tit downloader kan det give mening at opbygge en speciel konstruktion til formålet kaldet et Content Delivery Network, som i princippet blot er en række servere optimeret til at levere ligepræcis det indhold du ønsker, rasende hurtigt, fra forskellige lokationer.

Vi vil selvfølgelig lave det med Apache, og her i dette indlæg vil jeg starte med et simpelt setup som jeg i efterfølgende indlæg vil bygge videre på. Jeg ønsker at bruge mine lab maskiner som base for CDN’et:

lab1.mikjaer.com : 109.202.159.61
lab2.mikjaer.com : 109.202.159.62

Begge maskiner er installeret med Debian og Apache, hverken MySQL eller PHP skal bruges her, vi skal nemlig udelukkende hoste statisk indhold. I det her tilfælde har jeg valgt at hoste et par store .iso filer for at have noget at teste med.

Selve “tricket” ligger i DNS Opsætningen, vi benytter noget som kaldes en RRD( Round Robin DNS) Opsætning, som i princippet blot handler om at oprette flere A-Records for den samme adresse, så vil navneserverne selv sørge for at blande dem og sende dem ud i forskellig rækkefølge. Det betyder at forskellige brugere vil tilgå forskellige adresser. Fordelingen vil være, givet et stort nok grundlag, nogenlunde ligeligt fordelt mellem adresserne.

Den eksakte opsætning af dine A Records afhænger af din DNS Udbyder, så det vil jeg ikke gennemgå, men resultatet skulle gerne ende med at se således ud:

root@lab1:~# host -t a cdn.mikjaer.com
cdn.mikjaer.com has address 109.202.159.62
cdn.mikjaer.com has address 109.202.159.61

Som du kan se får du nu en liste over alle ip adresserne istedet for blot én som normalt, i teorien kan du oprette så mange du vil. I realiteten skal du holde dig omkring max 10. da du ellers kan få problemer med blandt andet caching og pakke-fragmentering.

For at demonstrere princippet med den tilfældige rækkefølge har jeg kørt den to gange direkte mod navneserveren (min lokale navneserver cache’r resultatet og derfor vil du ikke se rækkefølgen ændre sig så længe vi bruger den)

root@lab1:~# host -t a cdn.mikjaer.com ns1.mikjaer.com | grep has\ address
cdn.mikjaer.com has address 109.202.159.61
cdn.mikjaer.com has address 109.202.159.62
root@lab1:~# host -t a cdn.mikjaer.com ns1.mikjaer.com | grep has\ address
cdn.mikjaer.com has address 109.202.159.62
cdn.mikjaer.com has address 109.202.159.61

Dertil skal det nævnes at flere nyere browsere genkender RRD og i tilfælde af udfald automatisk vil spørge en af de andre servere.

Nu er der faktisk ikke så meget andet at gøre end at lægge data på dit nye CDN, lad os uploade en ISO:

mike$ scp debian-6.0.3-amd64-netinst.iso root@lab1.mikjaer.com:/var/www/test.iso
root@lab1.mikjaer.com's password:
debian-6.0.3-amd64-netinst.iso                        100%  168MB   1.1MB/s   02:35
mike$ scp debian-6.0.3-amd64-netinst.iso root@lab2.mikjaer.com:/var/www/test.iso
root@lab2.mikjaer.com's password:
debian-6.0.3-amd64-netinst.iso                        100%  168MB   1.1MB/s   02:37

For at teste lidt på det har jeg åbnet 2 vinduer der kører en Apache Status:

root@lab1:~# watch -n 1 apachectl status

og for at generere lidt trafik til mit screenshot kører jeg flg. kommando på 2 andre maskiner:

root@lab3:~# watch wget --delete-after http://lab1.mikjaer.com/test.iso

Resultatet ser således ud:

Hvert “W” repræsenterer en process der bliver serviceret, og den ene af dem vil altid være Apachestatus selv, og dermed er der altså to processer igang, i og med at det er en lukket test kan jeg roligt antage at begge processer er mine egne. Evt. kan jeg stoppe dem og se at de forsvinder hvis jeg vil være helt sikker.

Nu åbner jeg apachestatus på begge servere og kører den her fra én server:

root@lab3:~# watch wget --delete-after http://cdn.mikjaer.com/test.iso

og kan nu se hvordan download processen på Apachestatus hopper fra den ene til den anden skærm, hvilket jo viser at RRD virker, som en sidste finale vil jeg skrive et hurtigt script der illustrere det endnu bedre:

test.sh:

#!/bin/bash
for (( c = 1; c<=100; c++))
do
        wget --delete-after http://cdn.mikjaer.com/test.iso &
done

Sæt execute permissions og kør scriptet:

root@lab3:~# chmod 755 test.sh
root@lab3:~# ./test.sh

På begge, eller flere, klient maskiner, og så på dine Apachetop vinduer hvordan processerne fordeler sig jævnt ud på dit CDN:

Og du kan se, i løbet af ingenting har vi opbrugt de 12MB/s som et 100mbit netkort kan levere, og belastningen bliver fint fordelt på de to noder i vores CDN.

Hvis det ikke virker for dig skyldes det typisk at du bruger en lokal DNS som cacher resultaterne, det gør Google’s DNS’er f.eks. Det vil ikke udgøre et reelt problem fordi at dine besøgende typisk vil være geografisk spredt ud over landet/verden og dermed også flere forskellige DNS Caches. Dertil skal lægges at nyere browsere (dvs. ikke wget) selv tager højde for RRD og håndterer det korrekt.

Hvis det her virkelig skal batte noget skal du selvfølgelig ikke bruge virtuelle servere som jeg har gjort, du skal bruge fysiske servere der sider på hver deres forbindelser – eller ihvertfald på en så stor forbindelse at du ikke ender med en flaskehals der ?

ps. Hvis du får brug for at stoppe test.php scriptet igen, så log ind på maskinen med en anden terminal og skriv:

root@lab1:~# killall -9 test.sh
root@lab1:~# killall wget

 

Dette indlæg blev udgivet i Apache, Knowledge Base, Linux, Networking, Old Base. Bogmærk permalinket.

Skriv et svar