Just nu i M3-nätverket
Jump to content

Optimera webbtrafik


dune

Recommended Posts

Hej,

 

En site jag driver har två mindre webbsidor som laddas om rätt ofta med META REFRESH. Dessa står för ungefär en tredjedel av all webbtrafik som den siten konsumerar. Så nu försöker jag hitta på ett smidigt sätt att optimera bort omladdningarna om det inte har skett någon förändring på sidan.

 

Sidorna är PHP-drivna och jag funderar på hur man skulle kunna göra det på ett bra sätt, om det över huvud taget är möjligt.

 

Går det att lösa något med http-headers? Hur reagerar META-REFRESHEN då?

 

Någon som pysslat med något liknande som kan ge input?

 

Jag vill inte gå över till flash eller något liknande utan helst hålla mig till PHP.

 

Servern kör Apache på Gentoo Linux 2.4.x och jag har root-tillgång så jag kan installera moduler osv om det är nödvändigt.

 

 

Bra svar ger poäng, såklart.

 

 

.dune.

----------------------------------------------

- "I find this a nice feature but it is not according to the documentation.

Or is it a BUG?"

- "Let´s call it an accidental feature. :-)"

 

Link to comment
Share on other sites

Om ingen annan svarar innan imorrn så har jag själv jobbat med något liknande där en viss sida tar den mesta trafiken och jag har velat köra klientcache på den (om det är det du är ute efter?). Tyvärr är jag inte direkt nykter just nu, och inte heller i närheten av min arbetsdator, så jag kan inte visa dig, men om du ger mig nån dag (om jag inte är FÖR bakis) så kanske jag kan visa dig hur jag gjorde det imorrn? :)

 

--

Some say I am crazy.. but the voices in my head disagree...

 

Stoppa mjukvarupatenten nu! http://www.ffii.se/

 

Link to comment
Share on other sites

Om ingen annan svarar innan imorrn så har jag själv jobbat med något liknande där en viss sida tar den mesta trafiken och jag har velat köra klientcache på den (om det är det du är ute efter?).

Jag antar att det är vad jag är ute efter. Sidorna som drar mest trafik uppdateras men med relativt lite information och jag skulle vilja minska mängden trafik mot servern så ja.

 

Bakis är alla tillåtna att vara :)

 

 

.dune.

----------------------------------------------

- "I find this a nice feature but it is not according to the documentation.

Or is it a BUG?"

- "Let´s call it an accidental feature. :-)"

 

Link to comment
Share on other sites

c

 

[edit]NEEEEEEEEJ, jag gjorde som jag brukar, att trycka Ctrl+a, Ctrl+c och Alt+m i en snabb följd för att kopiera in allt i minnet och sedan skicka iväg meddelandet. Men nu blev det bara ett c istället... ARRGHHH!

 

Jaja, jag skriver väl om mitt meddelande då, även fast det tar emot...[/edit]

 

[inlägget ändrat 2004-10-25 10:26:55 av Bj0rN]

Link to comment
Share on other sites

PHP sätter några headers som default för att förhindra cachning, dessa är bland annat Expires och Cache-Control. För att motverka detta och sätta igång cachning så sätter jag själv dessa headers oxå vilket då "overridar" det som PHP sätter som default. Såhär gör jag det:

 

[color="#ff0000"]header[/color]("Expires: " . [color="#ff0000"]gmdate[/color]('D, d M Y H:i:s', [color="#ff0000"]time[/color]()+300) . " GMT\n");
[color="#ff0000"]header[/color]("Cache-Control: public\n");

Expires headern säger då att klienten kan cacha sidan i fem minuter eftersom sidan "går ut" då. Cache-Control har med hur sidan får cachas att göra. Jag sätter public eftersom man i normala fall inte får cacha sidor som är skyddade. Egentligen skulle du även här kunna säga hur länge sidan kan cachas och när den sedan måste omvalideras genom att sätta headern såhär istället:

 

[color="#ff0000"]header[/color]("Cache-Control: [color="#ff0000"]max[/color]-age=300, must-revalidate\n");

Detta får effekten att sidor ser ut att laddas mycket snabbare för klienten eftersom det egentligen ligger i klientens cache, samtidigt så vet jag att klienten får ny information på regelbunden basis eftersom jag sätter en fem minuters gräns på cachningen.

 

I samband med cachningen på klientsidan kör jag även Turck MMCache vilket cachar koden på serversidan. Detta snabbar upp en hel del i sig och tar även bort en del load på servern.

 

--

Some say I am crazy.. but the voices in my head disagree...

 

Stoppa mjukvarupatenten nu! http://www.ffii.se/

 

Link to comment
Share on other sites

Expires headern säger då att klienten kan cacha sidan i fem minuter eftersom sidan "går ut" då. Cache-Control har med hur sidan får cachas att göra. Jag sätter public eftersom man i normala fall inte får cacha sidor som är skyddade. Egentligen skulle du även här kunna säga hur länge sidan kan cachas och när den sedan måste omvalideras genom att sätta headern såhär istället:

 

Detta är inte riktigt vad jag vill ha, men nästan. Det ser ut att vara en bra grej att implementera eftersom jag ändå har en massa sidladdningar. Frågan är om följande går att uppnå:

 

Jag har en php-sida där det dynamiska innehållet uppdateras förhållandevis sällan. Skulle jag tex kunna göra följande med meta-refresh: Gå till en annan php-sida, tex kolla.php med ett MD5/CRC-argument och mät det mot CRC på den php-sida som är "klar att skickas" från servern. Om CRC inte stämmer så är sidan alltså förändrad och borde skickas ut till browsern, om CRC stämmer så har sidan inte förändrats, ladda bara om sidan från cache.

 

Det känns genomförbart men i och med att jag inte har jobbat speciellt mycket med PHP så vill jag gärna kolla av det innan jag börjar experimentera med det...

 

kör jag även Turck MMCache vilket cachar koden på serversidan.
Skall kika på det... :)

 

 

.dune.

----------------------------------------------

- "I find this a nice feature but it is not according to the documentation.

Or is it a BUG?"

- "Let´s call it an accidental feature. :-)"

 

Link to comment
Share on other sites

Aha, nu hänger jag med.

 

Skulle jag tex kunna göra följande med meta-refresh: Gå till en annan php-sida, tex kolla.php med ett MD5/CRC-argument och mät det mot CRC på den php-sida som är "klar att skickas" från servern. Om CRC inte stämmer så är sidan alltså förändrad och borde skickas ut till browsern, om CRC stämmer så har sidan inte förändrats, ladda bara om sidan från cache.

Visst skulle det fungera, men du skulle inte minska load på servern, snarare höja den eftersom du då gör två anrop, ett till sidan som kollar din dynamiska sida, och ett från den sidan till den dynamiska. Det enda du vinner är ju att du slipper skicka extra data över nätet vilket iofs är något bra det oxå.

 

Det finns något som heter ETag i cache sammanhang. Den skulle du kunna använda lite beroende på hur ditt dynamiska innehåll skapas upp och om du kör med någon typ av Last modified datum i nån tabell i nån databas.

 

En ETag kan i princip innehålla vad som helst, själv brukar jag köra med en md5 summa som blandar in senaste modifierade datum och användarens id för att få cachningen användarspecifik. Om du inte har något Last-modified fält i databasen skulle du kunna ta ut all data från databasen och köra en md5 summa på det och lägga till användarens id eller sessions id och sedan skicka iväg en ETag header.

 

Du jämför ETag headern med en header från browsern som heter If-None-Match. Om dessa är lika så har användaren samma data som ligger i databasen och du kan skicka en 304 Not Modified header vilket innebär att klienten kommer hämta informationen från cachen istället.

 

Då man skickar en 304 header måste även vissa andra headers skickas med, jag har skrivit ihop lite dummykod för att illustrera hur det fungerar:

 

<?[color="#0000ff"]php[/color]

$allHeaders = [color="#ff0000"]getallheaders[/color]();

$etag = [color="#ff0000"]md5[/color]('2004-10-26');

[color="#0000ff"]if[/color] ($allHeaders['[color="#0000ff"]if[/color]-None-Match'] == $etag) {
[color="#ff0000"]header[/color]("HTTP/1.1 304 Not Modified\n");
[color="#ff0000"]header[/color]("[color="#ff0000"]date[/color]: " . [color="#ff0000"]gmdate[/color]('D, d M Y H:i:s', [color="#ff0000"]time[/color]()) . " GMT\n");
[color="#ff0000"]header[/color]("ETag: " . $etag . "\n");
[color="#ff0000"]header[/color]("Expires: " . [color="#ff0000"]gmdate[/color]('D, d M Y H:i:s', [color="#ff0000"]time[/color]()+300) . " GMT\n");
[color="#ff0000"]header[/color]("Cache-Control: private\n");
[color="#0000ff"]exit[/color];
}

[color="#ff0000"]header[/color]("ETag: " . $etag . "\n");

[color="#0000ff"]echo[/color] [color="#ff0000"]rand[/color](0,9999999);
[color="#0000ff"]exit[/color];

?>

$etag variabeln i ditt fall ska då alltså vara en md5 summa på innehållet i sidan tillsammans med en unik identifierare för användaren så att inte en cachande proxy gör några dumheter.

 

Även om vi har headern Cache-Control: private så kan det ju faktiskt finnas äldre proxies som kanske inte förstår den headern och cachar ändå, vilket kan få katastrofala följder om proxyn ger samma information till alla användare bakom proxyn om det är personifierad data på sidan.

 

[EDIT]Min formattering behölls inte då jag använde mig av KOD taggarna. Inte bra i vissa fall då headers är case-sensitive. En bugg i KOD taggs hanterandet tror jag minsann!

 

$allHeaders['If-None-Match'] ska se ut som jag skrev nu, och inte som det ser ut i KOD taggen.[/EDIT]

 

--

Some say I am crazy.. but the voices in my head disagree...

 

Stoppa mjukvarupatenten nu! http://www.ffii.se/

 

[inlägget ändrat 2004-10-26 12:47:14 av Bj0rN]

Link to comment
Share on other sites

Visst skulle det fungera, men du skulle inte minska load på servern, snarare höja den eftersom du då gör två anrop, ett till sidan som kollar din dynamiska sida, och ett från den sidan till den dynamiska. Det enda du vinner är ju att du slipper skicka extra data över nätet vilket iofs är något bra det oxå.
Load spelar inte så stor roll. Det är en rätt liten webbsida som bara visar status på en mängd saker så den är inte speciellt tung.

 

Jag tror att i dagsläget prioriterar jag nog att spara webbtrafiken framför load på servern...

 

Skall sätta mig och experimentera lite!

 

Tusen tack så länge. Jag återkommer nog i frågan :)

 

 

.dune.

----------------------------------------------

- "I find this a nice feature but it is not according to the documentation.

Or is it a BUG?"

- "Let´s call it an accidental feature. :-)"

 

Link to comment
Share on other sites

Problemet är väl att webben inte är gjord för push...Du kommer nog inte ifrån att dina besökare kommer att behöva polla din sida. När man använder Refresh så svarar åtminstone Firefox typ som om den aldrig sett sidan, dvs inte har den cachad. Så, att svara med 304 borde vara rätt förvirrande.

 

Åtminstone så kan inte jag se nån lösning.

 

Link to comment
Share on other sites

[edit]NEEEEEEEEJ, jag gjorde som jag brukar, att trycka Ctrl+a, Ctrl+c och Alt+m i en snabb följd för att kopiera in allt i minnet och sedan skicka iväg meddelandet. Men nu blev det bara ett c istället... ARRGHHH!

 

Det brukar fungera att trycka ctrl+z för att ångra senaste inmatningen även i primitiva textboxar som den här ^^

 

.Wey

2. Everything around us can be represented and understood through numbers.

 

Link to comment
Share on other sites

Jo, det brukar det, men i mitt fall hann meddelandet skickas iväg även fast Eforum sa åt mig att det inte räcker med en bokstav i meddelandet... lite jobbigt..

 

--

Some say I am crazy.. but the voices in my head disagree...

 

Stoppa mjukvarupatenten nu! http://www.ffii.se/

 

Link to comment
Share on other sites

När man använder Refresh så svarar åtminstone Firefox typ som om den aldrig sett sidan, dvs inte har den cachad. Så, att svara med 304 borde vara rätt förvirrande.

Hrrmm, underligt... Jag testade att sätta en meta refresh jag med nu, och du har alldeles rätt, då verkar Firefox skita i Not Modified headern...

 

Men det går ju såklart att lösa genom att använda javascript istället:

 

<?[color="#0000ff"]php[/color]

$allHeaders = [color="#ff0000"]getallheaders[/color]();

$etag = [color="#ff0000"]md5[/color]('2004-10-26');

[color="#0000ff"]if[/color] ($allHeaders['[color="#0000ff"]if[/color]-None-Match'] == $etag) {
[color="#ff0000"]header[/color]("HTTP/1.1 304 Not Modified\n");
[color="#ff0000"]header[/color]("[color="#ff0000"]date[/color]: " . [color="#ff0000"]gmdate[/color]('D, d M Y H:i:s', [color="#ff0000"]time[/color]()) . " GMT\n");
[color="#ff0000"]header[/color]("ETag: " . $etag . "\n");
[color="#ff0000"]header[/color]("Expires: " . [color="#ff0000"]gmdate[/color]('D, d M Y H:i:s', [color="#ff0000"]time[/color]()+300) . " GMT\n");
[color="#ff0000"]header[/color]("Cache-Control: private\n");
[color="#0000ff"]exit[/color];
}

[color="#ff0000"]header[/color]("ETag: " . $etag . "\n");

?>
<html>
<head>
<script type="text/javascript">
<!--
[color="#0000ff"]function[/color] onLoad() {
setTimeout("reloadPage()",4000);
}

[color="#0000ff"]function[/color] reloadPage() {
document.location.href="test.[color="#0000ff"]php[/color]";
}

[color="#006400"]//-->[/color]
</script>
</head>
<body onLoad="onLoad()">

<?[color="#0000ff"]php[/color]
[color="#0000ff"]echo[/color] [color="#ff0000"]rand[/color](0, 999999);
?>

</body>
</html>

 

--

Some say I am crazy.. but the voices in my head disagree...

 

Stoppa mjukvarupatenten nu! http://www.ffii.se/

 

Link to comment
Share on other sites

Angående [EDIT]:

 

Rapportera felet till Erik. Tror dock att det finns en del andra redan rapporterade buggar i kodradsfärgläggningen som inte åtgärdats, men ändå...

 

_________

TicoRoman - Anfall är bästa försvar

 

 

[inlägget ändrat 2004-10-26 22:26:44 av TicoRoman]

Link to comment
Share on other sites

Cool :thumbsup:. Jag fick det att funka (med lite småändringar):

[log]

<?php

$allHeaders = getallheaders();

 

$etag = md5(filemtime($_SERVER['SCRIPT_FILENAME']));

 

if ($allHeaders['If-None-Match'] == $etag) {

header("HTTP/1.1 304 Not Modified\n");

header("date: " . gmdate('D, d M Y H:i:s', time()) . " GMT\n");

header("ETag: " . $etag . "\n");

exit;

}

 

header("ETag: " . $etag . "\n");

 

?>

<html>

<head>

<script type="text/javascript">

<!--

function onLoad() {

setTimeout("reloadPage()",4000);

}

 

function reloadPage() {

document.location.href="<?php echo $_SERVER['REQUEST_URI']; ?>";

}

 

//-->

</script>

</head>

<body onLoad="onLoad()">

<?php

echo 'Senast ändrad: ' . date ('j F Y H:i:s.', filemtime($_SERVER['SCRIPT_FILENAME']));

?>

</body>

</html>

[/log]

 

 

Link to comment
Share on other sites

Hej BjOrN,

 

vad är anledningen till att du skriver ut rand(0, 999999); i slutet av filen?

 

_________

TicoRoman - Anfall är bästa försvar

 

Link to comment
Share on other sites

Ingen anledning alls. Jag gjorde bara så för att man på ett enkelt sätt ska se om sidan man tittar på är cachad eller om den är tagen från servern. Om inte siffran ändras vid omladdning är sidan tagen från cachen och inte servern.

 

--

Some say I am crazy.. but the voices in my head disagree...

 

Stoppa mjukvarupatenten nu! http://www.ffii.se/

 

Link to comment
Share on other sites

Jag gjorde bara så för att man på ett enkelt sätt ska se om sidan man tittar på är cachad
Ah självklart.. ibland är jag bra trögtänkt. :)

 

Jag har inte tidigare jobbat med cachehantering, men den här tråden fångade min uppmärksamhet. I kombination med komprimering kan användandet av bandbredden minskas oerhört.

 

:thumbsup:

 

_________

TicoRoman - Anfall är bästa försvar

 

Link to comment
Share on other sites

I kombination med komprimering kan användandet av bandbredden minskas oerhört.

Absolut! Det är ett rätt så intressant område oxå IMHO. Själv försöker jag så ofta jag kan använda mig av cache funktioner, både på serversidan och ut mot klienten för att snabba upp visningen av sidor så snabbt som möjligt.

 

Just den här cache grejen skrev jag först till en bildbank för att snabbt visa upp thumbnails i ett sökresultat om de inte har ändrats och man redan har sett bilderna vid något tillfälle. Det snabbar upp sidvisningen avsevärt! Tillsammans med komprimering av webbtrafiken och någon form av optimiserar programvara så kan man snabba upp sajter avsevärt!

 

--

Some say I am crazy.. but the voices in my head disagree...

 

Stoppa mjukvarupatenten nu! http://www.ffii.se/

 

Link to comment
Share on other sites

Trots de uppenbara fördelarna med komprimering är det få webbplatser som använder det. Enligt en undersökning av Port80 i juni 2004 är det endast 5,3 % som använder någon form av komprimering. Undersökningen baseras på 1000 "leading corporations' Web sites". Ett år tidigare var det endast 2,9 %.

 

http://www.port80software.com/surveys/top1000compression/

 

På samma sida finns ett verktyg som öppnar en webbplats, undersöker om komprimering används samt hur stora besparingar i form av nedladdningstid och trafikkostnader komprimering kan ge.

 

Resultatet för //eforum.idg.se/ är:

 

Original size: 112673 bytes

Size if compressed: 21674 bytes

Possible savings in bytes: 90999 bytes

 

Percentage saved by compression: 81.0%

Transfer speed improvement: 5.1 X

 

Rätt så uppenbar skillnad med andra ord. Även om verktyget kanske kan vara mer eller mindre exakt så framgår fördelarna klart. Även en bandbreddbesparing på 10% borde betyda mycket för stora sajter som genererar mycket trafik - antar jag.

 

Vad kan det bero på att så få webbplatser använder komprimering? Tekniken som ändå funnits sedan HTTP/1.0 (med reservation för att jag minns helt fel) och är implementerad i "alla" webbläsare.

 

Komprimering är förmodligen något resurskrävande, men datorkraft är väl billigare än bandbredd?

 

_________

TicoRoman - Anfall är bästa försvar

 

 

[inlägget ändrat 2004-10-31 21:47:47 av TicoRoman]

[bild bifogad 2004-10-31 22:51:08 av TicoRoman]

638530_thumb.jpg

Link to comment
Share on other sites

Om datorkraft är billigare eller inte beror delvis på hur du betalar för datorkraften och hur du betalar för bandbredden.

 

om du t ex betalar för att ha en viss kapacitet men betalar en rörlig summa baserad på hur många maskiner du har och hur mycket plats dom tar så kanske du inte vill ta ha för mycket kraft i form av många maskiner eller maskiner som tar upp flera enheter rackutrymme (U). Alt så är du mer intresserad av att hantera många anslutningar för du har ändå en fast bandbredd och därmed intresserad av mycket kraft för anslutningar vilket inte alltid innebär att krutet läggs på kraftiga cpu:er.

 

Hittills har nog komprimering ansetts som något som tar mer prestanda än det är värt då det har varit mer eller mindre brist på cpukraft för att komprimera många sidor samtidigt men däremot varit i jämnförelse lätt att få iokraft nog för att fylla nätverksinterfacet. Om du sen vill använda ssl så tog ju det avsevärd kraft oxå

 

I dagens läge blir dock komprimering mer intressant då du redan kan trycka in kraftiga cpu:er som kan hänga med iosubsystemet och nätverket utan problem dessutom utan att priset flyger iväg allt för mycket. Plats för maskinerna är numera dessutom mer värdefull så man kan inte ha hur många maskiner som helst.

 

Betalar man per meg eller inriktar sig på kunder med begränsningar i bandbredd så är det säkert mer intressant med komprimering speciellt om man kan sprida lasten över flera maskiner utan att kostnaden ökar för mycket per maskin

 

ekvationen är ju ganska enkel igentligen

kostnad=bandbreddskostnad+maskinkostnad+utrymmeskostnad

 

Bandbreddskostnad är oftast antingen antal kapacitetsenheter*enhetspris, trafikmängd i enhet*enhetspriset. första köps ofta i fasta enheter som motsvarar linjehastighet eller del av linjehastighet t ex 10mbit eller 100mbit eller specificationer av linjehastighet som t1 och t3. Oftast så är kostnaden för att fylla hela linan större för trafikmängd än kostnaden för kapaciteten.

 

Maskinkostnaden beror på kostnaden för maskinen och antalet maskiner som beräknas genom att räkna ut antalet sidor varje maskin klarar och dela det med antalet önskade sidor per minut.

 

Utrymmeskostnaden är olika beroende på förvaringen av servrarna och kan handla om att betala hyran för den skrubb som 1 server står i till kostnad per U i ett rack i en colocation facilitet.

 

Så om man hypotiserar att det krävs 3 maskiner för att komprimera och levera samma mängd sidor som en maskin som inte komprimerar om man använder samma maskiner och en maskin med motsvarande kraft som dom 3 maskinerne kostar 4 ggr så mycket som var och en av dom maskinerna och den svagare maskinen är 1U och den krafigare är 4U.

Lägger du dessutom på en kostnad per U i racket så går priset upp ytterliggare med 2-3xEnhetspriset för du behöver 2-3U mer för att levera samma mängd sidor. Om dock kostnaden för trafiken är lägre än den kostnaden och du inte anser att du kommer behöver 4 ggr kapaciteten inom överskådlig tid alt kostnaden för 4ggr så mycket trafik är för hög så kan det ändå vara värt det.

I siffror med hypotetiska värden. 10000 för svagare maskin och 40000 för dyrare och 1000 per U så blir maskinkostnade alltså antingen 11000 för 1 st 1U server eller 33000 resp 44000 för dom 2 andra lösningarna. Om du kan spara in 22000 resp 33000 i bandbreddskostnad genom komprimerings är det ju värt det annars är det ju en onödig kostnad.

 

En fungerande komprimering över samtliga browsers är jag inte säker på att det funnits så länge (relativt, menar datortid)

 

Men komprimering är sannolikt något som kommer komma mer i framtiden

 

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.



×
×
  • Create New...