Et simpelt og effektivt PHP-cachesystem. WordPress Super Cache, et must-have WP-plugin

Caching af mellemdata er den mest primitive og samtidig den mest brugbare måde at optimere på, hvor du ikke behøver at bøvle med nogle komplekse algoritmer eller præ-optimering. Hvis du skal arbejde med PHP, skal du være opmærksom på de gennemprøvede metoder og værktøjer, der er nødvendige for at få dit websted til at flyve.

Statiske lokale variable

En hurtig og effektiv måde at cache resultaterne af en funktion/metode på er at bruge statiske lokale variabler. Lad os se på et eksempel, der udfører komplekse beregninger:

Nu, hver gang du bruger en funktion i kode, uanset antallet af opkald, vil funktionen kun udføre beregninger én gang.

Denne cacheteknik er uafhængig af eksterne udvidelser og understøttes på sprogniveau. Fordi statiske lokale variabler kun er tilgængelige inden for den funktion, hvori de er defineret, kan det være problematisk at opdatere cachen. Typisk kræver dette, at en form for boolesk variabel sendes til $use_cache eller i stedet bruges statiske klassevariabler.

Statiske variabler deles ikke mellem PHP processer og kan kun cache i kort tid - hvilket dækker udførelsestiden for scriptet. En god kandidat er en metode, der kaldes mange gange fra flere steder, for eksempel for at gemme brugertilstand eller et resultat, der kræver stort volumen matematiske beregninger.

Den samme funktionalitet kan implementeres ved hjælp af globale variabler, men dette vil forurene det globale navneområde og anbefales ikke.

APC delte hukommelsesfunktioner

PHP er et semi-kompileret sprog, hvilket betyder, at hvert script ikke kompileres direkte i maskinkode, men til mellemkode, kendt som et sæt opkoder (bytecode). Dette trin kompilering bruger mange CPU-ressourcer og skal udføres hver gang scriptet udføres. APC (Alternativ PHP Cache) er en udvidelse, der springer dette kompileringstrin over ved at cache opkoder i hukommelsen.

Selvom hovedformålet med APC normalt anses for at være opcode-cachefunktionalitet, inkluderer udvidelsen også nogle ekstra hukommelsesadgangsfunktioner.

Nu er fordelen ved denne tilgang indlysende - det er brugen af ​​delt hukommelse. Denne type hukommelse deles mellem forskellige processer/tråde, og i modsætning til statiske variable vil data, der cachelagres på denne måde, eksistere på tværs af flere anmodninger.

For at ugyldiggøre en cache kan du bruge time to live (TTL) værdier som i eksemplet ovenfor eller følgende funktioner:

Andre bemærkninger om understøttelse af delt hukommelse i APC:

Der er et direktiv i INI-konfigurationsfilen for at begrænse cachestørrelsen. Med passende TTL-værdier giver dette mulighed for at prioritere cachelagrede data, hvor, hvis hukommelsesgrænsen nås, vil udløbne/gamle værdier blive fjernet fra cachen.

Fra et præstationsperspektiv vil statiske variable altid være hurtigere end apc_fetch/apc_store funktioner, da adgang til delt hukommelse skal låses og synkroniseres for at forhindre konflikter.

APC er en ret populær udvidelse og understøttes af major PHP udviklere og (meget sandsynligt) vil blive bundtet med PHP 5.4.

Memcached til store distribuerede caches

Når først et websted begynder at modtage mange hits, bliver det til sidst en opgave at fordele belastningen mellem forskellige maskiner. Som et resultat skal du normalt flytte PHP på tværs af flere applikationsservere. Hvis du har brugt APC-cache før - har hver applikationsserver nu en separat og redundant cache.

Memcached på den anden side er en distribueret service til lagring af nøgleværdidata. Udvidelsen kan installeres på en separat dedikeret server eller i den samme PHP-applikationsstak. Det er vigtigt at forstå, at der ikke er nogen synkronisering/replikering mellem flere Memcached-servere, og de ved slet ikke noget om hinanden. Den faktiske server, der vil blive brugt til lagring, vælges på klientsiden ved hjælp af en hashing-algoritme baseret på de angivne "nøgle"-data. Det er derfor, i modsætning til APC, duplikeres cachelagrede data ikke mellem forskellige maskiner, og hukommelsen bruges bedre til store distribuerede applikationer.

API'et ligner meget den delte hukommelsesfunktionalitet i APC. Samme eksempel med valutaveksling, implementeret med ved hjælp af PHP Memcache-udvidelser:

Cache-opdatering er den samme som i APC - ved hjælp af TTL-funktionalitet eller et sæt funktioner.

Den lokale APC-cache vil altid være større hurtig metode sammenlignet med Memcached.

Der er altid forsinkelser i netværket, når klienten skal kommunikere med backend-tjenesten via en dedikeret tekstprotokol.

Databasetabeller i Random Access Memory

Selvom det ikke er specifikt for PHP, har mange databasestyringssystemer en tabelimplementering i hukommelsen. Data, der er gemt i sådanne tabeller, bevares ikke mellem servergenstarter, er garanteret indeholdt i hukommelsen og bliver aldrig sideført til disk. Dette betyder hurtigere adgang til poster, hvilket gør dem velegnede til datacache.

MySQL leverer in-memory-tabeller i MEMORY-lagerundersystemet. Selvom dataene bliver ryddet, efter at serveren er genstartet, vil tabelskemaerne blive bevaret:

CREATE TABLE test (...) MOTOR = HUKOMMELSE

PostgreSQL har midlertidige tabeller, der kun eksisterer under en session; for at cache data i en midlertidig tabel, skal en vedvarende forbindelse til databasen opretholdes.

OPRET MIDLERTIDIG TABELtest (...)

I SQLite kan du oprette en hel database i hukommelsen, men med de samme begrænsninger som i PostgreSQL - dataene vil kun eksistere i sessionens varighed, og du skal bruge vedvarende forbindelser at vedligeholde dem mellem flere anmodninger.

Så hvad kan du gøre med en tabel i RAM? Selvom sådan et bord aldrig vil eksistere hurtigere adgang til nøgleværdidata i APC/Memcached, får du kraften i SQL. Cachelagrede data kan filtreres, sorteres, grupperes og endda kombineres med andre data i tabeller.

Simpel filcache

Flad fil-cache bør være et alternativ til metoderne nævnt ovenfor og bør kun bruges, når systemet ikke har de nødvendige udvidelser, eller de pågældende data ikke kan gemmes i hukommelsen (f.eks. på grund af størrelse)

Fordi caching udføres for at forbedre ydeevnen, og præstationsoptimeringer er et resultat af høj samtidighed - bør fillåsning altid bruges til at forhindre læse/skrive race-forhold:

I de gode gamle dage var det så simpelt at oprette hjemmesider som at skrive et par stykker HTML-sider, var at sende websider til browseren simpelthen at sende en fil af webserveren. Besøgende på webstedet kunne se disse små, kun tekst-sider næsten øjeblikkeligt (undtagen for brugere af langsomme modemer). Når siden er blevet indlæst, cacher browseren den et sted på lokal computer så hvis siden bliver bedt om igen, kan du tage den lokal version fra cachen, kun afsendelse kort anmodning for at sikre, at siden på serveren ikke er blevet ændret. Anmodninger blev behandlet hurtigt og så effektivt som muligt, og alle var glade (undtagen dem, der brugte 9600 baud-modem).

Udseende dynamiske websiderændrede tingene til det værre, og effektivt "bryde" denne model for visning af websider på grund af tilstedeværelsen af ​​to problemer:

  • Når serveren modtager en anmodning om en dynamisk webside, udføres en mellemliggende behandling, f.eks. parsing af scriptet af motoren PHP som skal afsluttes. Takket være dette får vi en forsinkelse, før webserveren begynder at sende output til browseren. For simpelt PHP-script dette er ikke vigtigt, men for mere kompleks applikation motor PHP kan tage mange skridt, før siden er klar til at blive sendt. Disse yderligere handlinger føre til en mærkbar forsinkelse mellem brugeranmodninger og den faktiske visning af sider i deres browsere.
  • En typisk webserver, såsom Apache, bruger filændringstid til korrekt at fortælle webbrowseren cachetilstanden for den anmodede side. Faktisk til dynamiske websider PHP-et script kan kun ændres lejlighedsvis, mens indholdet det viser, muligvis placeret i en database, ændres ofte. Webserveren kan ikke vide, at der er sket ændringer i databasen, men den sender ikke den sidste ændringsdato. Hvis klienten (browseren) ikke modtager nogen indikation af, hvor længe dataene har været korrekte, antager den, at den næste gang skal anmode om en ny side. Webserveren vil altid svare med en opdateret version af siden, uanset om data er ændret. For at undgå denne ulempe bruger de fleste webudviklere metatags eller HTTP- overskrifter for at fortælle browseren, at den aldrig skal bruge den cachelagrede version af siden. Dette negerer dog webbrowserens naturlige evne til at cache websider og har nogle væsentlige mangler. For eksempel kan indholdet af en dynamisk side ændre sig en gang om dagen, så fordelen ved at lade browseren cache siden selv i 24 timer er indlysende.
  • Normalt for små PHP-applikationer er det ganske muligt at ignorere eksistensen af ​​disse problemer, men efterhånden som kompleksiteten og trafikken på dit websted stiger, kan du støde på problemer. Begge disse problemer kan dog løses, det første ved server-side caching, det andet ved at administrere klient-side caching inde fra din applikation. Den tilgang du tager for at løse problemerne vil afhænge af din applikation, men i dette kapitel vil vi se, hvordan du kan løse både problemer ved hjælp af PHP og nogle biblioteksklasser PÆRE.

    Hvordan forhindrer jeg browsere i at cache en side?

    Før vi ser på klient- og server-cachingteknikker, skal vi først forstå, hvordan man forhindrer webbrowsere (og proxyservere) i at cache sider i første omgang. Den vigtigste måde at opnå dette på er at bruge HTML-metatags:

    Ved at indsætte en tidligere dato i Expires-metatagget fortæller du browseren, at den cachelagrede kopi af siden altid er forældet. Det betyder, at browseren aldrig skal cache siden. Metatag Pragma: no-cache er en ret godt understøttet konvention, som de fleste webbrowsere følger. Når de først opdager dette tag, cacher de normalt ikke siden (selvom der ikke er nogen garanti, dette er kun en konvention).

    Det lyder godt, men der er to problemer med at bruge metatags:

  • Hvis tagget ikke eksisterede, da siden først blev anmodet af browseren, men vises senere (f.eks. ændrede du filen pageheader.php include, som er overskriften på hver webside), vil browseren forblive lykkeligt uvidende og bruge sin cachelagret kopi af originalen.
  • Proxyservere, der cacher websider, såsom delte ISP, vil slet ikke undersøge indholdet direkte HTML-dokument. I stedet stoler de kun på den webserver, som dokumenterne kom fra, og protokollen HTTP. Med andre ord kan webbrowseren tænke, at den ikke skal cache siden, men proxyserveren mellem browseren og din webserver ved det sandsynligvis ikke - og vil fortsætte med at sende den samme, nu forældede side til klienten .
  • Den bedste tilgang er at bruge protokollen direkte HTTP ved hjælp af PHP header()-funktionen, svarende til de to metatags ovenfor:

    Vi kan gå et skridt videre ved at bruge Cache-Control-headeren, som er kompatibel med browsere, der understøtter HTTP 1.1:

    Header("Udløber: Man, 26. juli 1997 05:00:00 GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-kontrol: post-check=0, pre-check=0", FALSE); header("Pragma: ingen cache");

    Dette sikrer, at ingen webbrowser eller mellemliggende proxyserver cacher siden, så besøgende altid får den bedst mulige oplevelse. nyeste version indhold. Faktisk burde den første header være selvstændig, dette Den bedste måde sikre, at siden ikke er cachelagret. Cache-Control og Pragma headerne blev tilføjet for at være på den sikre side. Selvom de ikke virker i alle browsere eller proxyer, vil de fange nogle tilfælde, hvor Expires ikke fungerer som forventet (f.eks. hvis datoen på klientens computer er indstillet forkert).

    At undgå caching giver os naturligvis de problemer, vi diskuterede i begyndelsen af ​​dette kapitel. Vi vil nu se på at løse disse problemer.

    Internet Explorer og cachelagring af filer

    Hvis ved servicering af en fil download PHP-scriptet bruger overskrifter såsom Content-Disposition: attachment, filename=myFile.pdf eller Content-Disposition: inline, filename=myFile.pdf du vil have problemer med Internet Explorer'om, hvis du fortæller browseren om ikke at cache siden.

    Internet Explorer håndterer downloads på en ret usædvanlig måde og sender to anmodninger til hjemmesiden. Den første anmodning downloader filen og gemmer den i cachen, indtil den anden anmodning foretages (uden at gemme svaret). Denne anmodning får processen til at overføre filen til slutbrugeren i henhold til filtypen (for eksempel starter Acrobat Reader hvis filen er PDF-dokument). Dette betyder, at hvis du sendte headers, der forhindrer browseren i at cache siden, Internet Explorer vil slette filen mellem første og anden anmodning, hvilket resulterer i slutbruger får ikke noget. Hvis filen du giver PHP-script ændres ikke, en af ​​de enkleste løsninger ville være at fjerne de "caching-forbudte" headere fra scriptet.

    Hvis filen, der downloades, ændres regelmæssigt (dvs. du vil have browseren til at downloade den nyeste version), skal du bruge Sidst-ændret-headeren, som vil blive dækket senere i dette kapitel, og sikre dig, at ændringstiden mellem to på hinanden følgende anmodninger ikke lave om. Du skal gøre dette på en måde, der ikke påvirker brugere af browsere, der håndterer downloads korrekt. En løsning i dette tilfælde ville være at gemme filen på din webserver og give et simpelt link til den, så webserveren kan rapportere caching-headerne for dig. Selvfølgelig er denne løsning muligvis ikke acceptabel, hvis autoriseret adgang til filen antages; denne løsning tillader direkte indlæsning af den gemte fil.

    Hvordan kan jeg fange data på serversiden til caching?

    Det er tid til at se på, hvordan vi kan reducere latens ved hjælp af server-side output caching. Den generelle tilgang er at begynde at rendere siden som normalt, køre databaseforespørgsler og så videre PHP. Men før vi sender resultatet til browseren, fanger vi det og gemmer det klar side, for eksempel i filen. Ved næste anmodning, PHP-scriptet kontrollerer først for tilstedeværelsen af ​​en cachelagret version af siden. Hvis det eksisterer, sender scriptet den cachelagrede version til browseren og eliminerer dermed forsinkelsen i genskabelse af siden.

    Et par ord om caching ved hjælp af skabeloner Hvordan administrerer jeg caching på klientsiden? ved hjælp af PHP?

    Det er tid til at se på en mekanisme, der giver os mulighed for at kontrollere cachen på klientsiden med midler PHP. Denne tilgang vil kun fungere, hvis du bruger PHP i forbindelse med serveren Apache da vi vil bruge getallheaders()-funktionen til at få headerne sendt af browseren. Denne funktion virker kun i Apache.

    Nye funktionsnavne

    Hvis du bruger PHP 4.3.0 s Apache HTTP-headere tilgås af funktionerne apache_request_headers() og apache_response_headers(). Getallheaders()-funktionen er blevet et alias for den nye apache_request_headers()-funktion.

    Mekanismen til at arbejde med webbrowserens cache er igen HTTP. Mange headere er involveret i at instruere webbrowsere og proxyservere til uafhængigt at cache en side, en situation kompliceret af det faktum, at nogle af dem kun er tilgængelige fra HTTP 1.1.

    Tjek HTTP-headere i din browser

    Simpelt men meget praktisk værktøj at kontrollere anmodning og svar headers er LiveHttpHeaders– browser tilføjelse Mozilla. Det er nødvendigt at vide præcis, hvilke headere dit script sender, især når du har at gøre med caching-headere HTTP.

    For nemheds skyld vil vi kun overveje HTTP 1.0-cache-headerne, nemlig Expires, Last-Modified og If-Modified-Since, samt HTTP 304 (Ikke ændret) statuskoden.

    Andre titler tilgængelige fra HTTP 1.1, såsom Cache-Control og ETag, er beregnet til at give en avanceret mekanisme, der kan bruges i forbindelse med websessionstilstand, med andre ord kan versionen af ​​en given side, der vises til en uautoriseret besøgende, være væsentlig anderledes end den, der vises. til en autoriseret bruger. Overskrifter HTTP 1.1 blev oprindeligt tilføjet for at tillade sådanne sider at blive cachelagret.

    Side levetid udløb

    Den nemmeste header at bruge er Expire header, som angiver en dato (muligvis i fremtiden), hvor siden udløber. Indtil dette tidspunkt har webbrowseren lov til at bruge den cachelagrede version af siden.

    Eksempel 7. 6.php

    SetExpires-funktionen sender headeren HTTP Udløber med en fremtidig tid angivet i sekunder. Ovenstående eksempel viser nuværende tid GMT og viser et link, der giver dig mulighed for at gå til siden igen. Ved at bruge din browsers Opdater-knap kan du fortælle browseren, at du vil opdatere sin cache. Ved at bruge linket vil du se, at tiden kun ændres en gang hvert 10. sekund.

    Datoer og tidspunkter i HTTP

    Datoer i HTTP beregnes altid i forhold til Greenwich Mean Time (GMT). PHP funktion gmdate() er nøjagtig den samme funktion som date() , bortset fra at den automatisk kompenserer for GMT-tid baseret på systemuret og din servers regionsindstillinger.

    Når browseren støder på Expires-headeren, cacher den siden. Alle efterfølgende anmodninger om siden, der er lavet inden den angivne udløbstid, bruger den cachelagrede version af siden, og der sendes ingen anmodninger til webserveren.

    Expires-headeren er for det meste enkel at implementere, men i de fleste tilfælde, medmindre du er en meget organiseret person, har du ingen mulighed for at vide præcis, hvornår en given side på dit websted er opdateret. Da browseren først vil kontakte serveren, efter at siden er blevet forældet, er der ingen måde at fortælle browseren, at en side i dens cache er forældet. Du mister også en del trafik til din hjemmeside, fordi browseren ikke kontakter serveren, når den anmoder om en cachelagret side.

    Tidspunkt for sideskift

    Det er mere praktisk at bruge sidehovederne Last-Modified og If-Modified-Since, der er tilgængelige i HTTP 1.0. Teknisk kendt som at lave en betinget GET-anmodning, returnerer du alt indhold baseret på tilstanden If-Modified-Since-anmodningsoverskrift.

    Når du bruger denne metode, skal du sende en Last-Modified header, hver gang dit PHP-script tilgås. Næste gang browseren anmoder om siden, vil den sende en If-Modified-Since-header indeholdende klokkeslættet, som dit script kan bruge til at afgøre, om siden er blevet opdateret siden sidste anmodning. Hvis dette ikke er tilfældet, sender dit script en HTTP 304-statuskode for at angive, at siden ikke er ændret uden at udskrive sideindholdet.

    Indstil cachefilens modifikationstid med denne linje: $lastModified = filemtime($cache_file);

    Derefter, ved hjælp af ændringstiden for cache-filen, sender vi Sidst-ændret-headeren. Vi er nødt til at sende dette for hver side, der vises, for at tvinge browseren til at sende os en If-Modified-Since-header med hver anmodning.

    // Send HTTP-headeren Last-Modified header("Last-Modified: " . gmdate("D, d M Y H:i:s", $lastModified) . " GMT");

    Hvis man kombinerer tidens tilgang sidste ændring Med en tidsværdi, der allerede er tilgængelig i din applikation (f.eks. tidspunktet for den seneste nyhedsartikel eller udløbstiden fra serverens cachesystem, vi så i den sidste løsning), kan du drage fordel af webbrowserens cache og aflaste datalinket med muligheder for at spare informationstrafik fra dit websted og forbedre dets ydeevne.

    Vær forsigtig, når du tester enhver caching udført i denne stil; hvis du gør det forkert, kan du forårsage, at dine besøgende altid har forældede kopier af dit websted.

    Caching af dine sider i 5 trinOriginal: Udgivet i PHP / JavaScript af ibzi den 17. februar 2007
    Oversættelse: Kuzma Feskov ( [e-mail beskyttet],http://kuzma.russofile.ru)

    Caching af dine sider kan være en god og nyttig mekanisme, især hvis de er genereret ved hjælp af PHP og gør en masse ting SQL-forespørgsler. Så snart du anvender caching, vil din server øjeblikkeligt reducere belastningen og stoppe med at optage en masse hukommelse til at generere sider - den vil simpelthen indlæse dem fra cachen. Jeg vil vise dig, hvordan PHP kan cache sider, og i fremtiden kan du bruge omkring 5 minutter på at gøre det.


    Lad os se på caching-teknologi trin for trin:

  • I hjemmemappen opretter vi filerne .htaccess, start_cache.php, end_cache.php, samt en mappe kaldet cache_files.
  • Mappen cache_files skal tildeles 777 attributter.
  • Skriv inde i .htaccess-filen følgende linjer: php_value auto_prepend_file /home/username/public_html/start_cache.php php_value auto_append_file /home/username/public_html/end_cache.php String /home/brugernavn/offentlig_html/ skal erstattes med stien til din hjemmemappe.
  • Vi placerer følgende kode i start_cache.php scriptet: Glem ikke at rette stien /home/brugernavn/offentlig_html/ til stien til din hjemmemappe.
  • Og placer følgende kode i end_cache.php scriptet:
  • Alle dine sider bliver cachelagret i 3600 sekunder = 1 time. Du kan nemt ændre denne parameter i start_cache.php scriptet. Sidecachen vil blive gemt i mappen cache_files.

    Det er ret indlysende, at i I dette tilfælde 777 attributter er en klar overtrædelse af sikkerheden. I den forbindelse anbefaler jeg at flytte mappen cahce_files uden for public_html, for eksempel at placere den et niveau højere. Dette vil blokere adgangen til filerne i det for brugere af dit websted, men vil ikke påvirke systemets ydeevne på nogen måde.

    Denne metode har også en anden alvorlig ulempe: forfatteren af ​​artiklen lægger hele cachen i en mappe, som, hvis der er et tilstrækkeligt antal sider på dit websted, vil forårsage et problem, for eksempel på Unix-systemer er der en betydelig nedgang i ydeevnen, når der er mere end 1000 filer i en mappe. I den forbindelse er det nødvendigt at foretage en række ændringer i algoritmen og organisere filerne i separate undermapper inde i cache_files-mappen. For eksempel at bruge de første 3-4 tegn i md5-cachen til dette.

    Til dynamiske ressourcer Det er ganske muligt at vælge en cachingtid på flere (5-10) sekunder eller 1-2 minutter, hvilket vil reducere belastningen på serveren markant, men vil ikke skade webstedets interaktivitet.

    For sider, hvor interaktivitet er særlig vigtig, kan du introducere undtagelser i .htaccess, som vil give dem mulighed for konstant at ændre sig, og for andre sider kan du bruge caching.

    Gendannelse af indhold på farten

    Dynamisk oprettede men statisk vedligeholdte sider, dvs. sider, der skal overføres som rent statiske (læs fra filsystem og derefter transmitteret efter anmodning), men de skal være dynamisk genereret af webserveren, hvis de ikke er i filsystemet. På denne måde kan du få PHP-genererede sider, der serveres statisk, medmindre nogen (eller planlæggeren) fjerner det statiske indhold. I dette tilfælde opdateres indholdet.

    Dette gøres med følgende sæt af direktiver:

    RewriteCond %(REQUEST_FILENAME) !-s RewriteRule ^page\.html$ page.php

    Her bevirker en anmodning til page.html, at den tilsvarende page.php køres internt, hvis page.html stadig mangler eller har nul størrelse. Tricket her er, at page.php er almindelig PHP et script, der udover sit eget output, skriver sit output til page.html-filen. Når denne kører én gang, sender serveren dataene til side.html. Når webmasteren ønsker at opdatere indholdet, sletter han blot page.html (normalt ved hjælp af en cronjob).

    Der er et problem med sidecache i Internet Explorer.

    I IE, når du arbejder med "Vary"-headeren, er der en ubehagelig fejl relateret til sidecache. Problemet løses ved at tilføje følgende linjer til .htaccess:


    caching i PHP

    I de gode gamle dage, da oprettelse af hjemmesider var så simpelt som at skrive et par HTML-sider, var det at sende websider til browseren et simpelt spørgsmål om, at webserveren sendte en fil. Besøgende på webstedet kunne se disse små, kun tekst-sider næsten øjeblikkeligt (undtagen for brugere af langsomme modemer). Når siden er blevet indlæst, cacher browseren den et sted på den lokale computer, så hvis siden anmodes om igen, kan den hente den lokale version fra cachen, og sender kun en kort anmodning for at sikre, at siden på serveren ikke har blevet ændret. Anmodninger blev behandlet hurtigt og mest effektivt, og alle var tilfredse (undtagen dem, der brugte 9600 baud-modem).

    Fremkomsten af ​​dynamiske websider ændrede tingene til det værre, og bryder effektivt denne websideservermodel på grund af to problemer:

    1. Når serveren modtager en anmodning om en dynamisk webside, udføres en mellemliggende behandling, for eksempel parsing af scriptet af PHP-motoren, som skal afsluttes. Dette giver os en forsinkelse, før webserveren begynder at sende output til browseren. For et simpelt PHP-script er dette ikke væsentligt, men i tilfælde af en mere kompleks applikation kan PHP-motoren udføre mange handlinger, før siden er klar til at blive sendt. Disse yderligere trin resulterer i en mærkbar forsinkelse mellem brugeranmodninger og de sider, der rent faktisk vises i deres browsere.

    2. En typisk webserver, såsom Apache, bruger filændringstid til korrekt at fortælle browseren cachetilstanden for den anmodede side. På dynamiske websteder kan selve PHP-scriptet kun ændres lejlighedsvis, mens det indhold, det viser, muligvis i en database, ændres ofte. Webserveren har ingen mulighed for at vide om ændringer i databasen, så den sender ikke den sidste ændringsdato. Hvis klienten (browseren) ikke modtager nogen indikation af, hvor længe dataene har været korrekte, antager den, at den næste gang skal anmode om en ny side. Webserveren vil altid reagere opdateret version sider, uanset om data er ændret. For at undgå denne mangel bruger de fleste webudviklere metatags eller HTTP-headere til at instruere browseren om aldrig at bruge den cachelagrede version af siden. Dette ophæver dog webbrowserens naturlige evne til at cache websider og har nogle væsentlige ulemper. For eksempel kan indholdet af en dynamisk side ændre sig en gang om dagen, så fordelen ved at lade browseren cache siden selv i 24 timer er indlysende.

    Normalt for små PHP-applikationer er det ganske muligt at ignorere eksistensen af ​​disse problemer, men efterhånden som kompleksiteten og trafikken på dit websted stiger, kan du støde på problemer. Begge disse problemer kan dog løses: det første ved server-side caching, det andet ved at administrere klient-side caching fra din applikation. Den tilgang, du tager, afhænger af dine specifikke behov, men i denne artikel viser vi, hvordan du kan løse både problemer ved hjælp af PHP og nogle PEAR-biblioteksklasser.

    hvordan forhindrer jeg browsere i at cache en side?

    Før vi ser på klient- og server-cachingteknikker, skal vi først forstå, hvordan man forhindrer webbrowseren (og proxyservere) i at cache sider i første omgang. Den vigtigste måde at opnå dette på er at bruge HTML-metatags:

    Ved at indsætte en tidligere dato i Expires-metatagget fortæller du browseren, at den cachelagrede kopi af siden altid er forældet. Det betyder, at browseren aldrig skal cache siden. Metatag Pragma: no-cache er en ret velunderstøttet konvention, som de fleste webbrowsere følger. Når de først opdager dette tag, cacher de normalt ikke siden (selvom der ikke er nogen garanti, dette er kun en konvention). Det lyder godt, men der er to problemer med at bruge metatags:

    1. Hvis tagget ikke eksisterede, da siden først blev anmodet af browseren, men dukker op senere (f.eks. ændrede du filen pageheader.php include, der er overskriften på hver webside), vil browseren forblive lykkeligt uvidende og bruge dens cachelagrede kopi af originalen.

    2. Proxyservere, der cacher websider, vil slet ikke direkte undersøge indholdet af HTML-dokumentet. I stedet stoler de kun på den webserver, som dokumenterne kom fra, og HTTP protokol. Med andre ord kan browseren mene, at den ikke skal cache siden, men proxyen mellem browseren og webserveren ved det nok ikke – og vil fortsætte med at sende den samme side til klienten.

    En bedre tilgang er at bruge HTTP-protokollen direkte ved hjælp af PHP-headerfunktionen:


    header("Pragma: ingen cache");
    ?>

    Vi kan gå et skridt videre ved at bruge Cache-Control-headeren, som er kompatibel med browsere, der understøtter HTTP 1.1:

    header("Udløber: Man, 26. juli 1997 05:00:00 GMT");
    header("Cache-Control: no-store, no-cache, must-revalidate");
    header("Cache-kontrol: post-check=0, pre-check=0", FALSE);
    header("Pragma: ingen cache");
    ?>

    Dette sikrer, at ingen webbrowser eller mellemliggende proxyserver cacherer siden, så besøgende altid modtager den mest opdaterede version af indholdet. Faktisk bør den første sidehoved være selvstændig; dette er den bedste måde at sikre, at siden ikke er cachelagret. Cache-Control og Pragma overskrifterne er tilføjet af sikkerhedsmæssige årsager. Selvom de ikke virker i alle browsere eller proxyer, vil de fange nogle tilfælde, hvor Expires ikke fungerer som forventet (f.eks. hvis datoen på klientens computer er indstillet forkert). At undgå caching giver os naturligvis de problemer, vi diskuterede i begyndelsen af ​​dette kapitel. Vi vil nu se på at løse disse problemer.

    Internet Explorer og cachelagring af filer

    Der kan opstå problemer, når du beskæftiger dig med caching og download af filer. Hvis der ved servicering af en fildownload af et PHP-script bruges headers som Content-Disposition: attachment, filename=myFile.pdf eller Content-Disposition: inline, filename=myFile.pdf, vil du få problemer med Internet Explorer, hvis du fortæl browseren om ikke at cache siden.

    Internet Explorer håndterer downloads på en ret usædvanlig måde og sender to anmodninger til hjemmesiden. Den første anmodning downloader filen og gemmer den i cachen, indtil den anden anmodning foretages (uden at gemme svaret). Denne anmodning får processen til at overføre filen til slutbrugeren i henhold til filtypen (for eksempel starter Acrobat Reader, hvis filen er et PDF-dokument). Det betyder, at hvis du sender headers, der forhindrer browseren i at cache siden, vil Internet Explorer slette filen mellem første og anden anmodning, hvilket ikke resulterer i noget for slutbrugeren. Hvis den fil, du tjener som PHP-script, ikke ændres, er en af ​​de enkleste løsninger at fjerne de "cache-hæmmende" headere fra scriptet.

    Hvis filen, der downloades, ændrer sig regelmæssigt (dvs. du vil have browseren til at downloade den nyeste version), skal du bruge Last-Modified-headeren og sikre, at ændringstiden mellem to på hinanden følgende anmodninger ikke ændres. Du skal gøre dette på en måde, der ikke påvirker brugere af browsere, der håndterer downloads korrekt. En løsning i dette tilfælde ville være at gemme filen på din webserver og give et simpelt link til den, så webserveren kan rapportere caching-headerne for dig. Selvfølgelig er denne løsning muligvis ikke acceptabel, hvis autoriseret adgang til filen antages, da den tillader direkte indlæsning af den lagrede fil.

    hvordan kan jeg fange data på serversiden til caching?

    Det er tid til at se på, hvordan vi kan reducere latens ved hjælp af server-side output caching. Så du kan betjene siden som normalt, køre databaseforespørgsler og så videre i PHP. Men før vi sender resultatet til browseren, fanger vi det og gemmer den færdige side, for eksempel i en fil. Ved næste anmodning søger PHP-scriptet først for en cachelagret version af siden. Hvis det eksisterer, sender scriptet den cachelagrede version til browseren og eliminerer dermed forsinkelsen i genskabelse af siden.

    Et par ord om caching ved hjælp af skabeloner. Tilstedeværelsen af ​​skabelonmotorer som Smarty taler ofte om skabeloncaching. Typisk tilbyder disse motorer en indbygget mekanisme til at gemme en kompileret version af skabelonen (det vil sige generering af PHP-kilde fra skabelonen), som forhindrer os i at skulle parse skabelonen, hver gang der anmodes om en side. Dette skal ikke forveksles med output caching, som refererer til caching af den medfølgende HTML (eller andet output), som PHP sender til browseren. Du kan med succes bruge begge typer caching samtidigt på det samme websted.

    Vi vil nu se på PHPs indbyggede caching-mekanisme, der bruger outputbuffering, som du kan bruge, uanset hvordan du opretter dit indhold (med eller uden skabeloner). Overvej en situation, hvor dit script viser resultatet, ved at bruge for eksempel ekko eller print til at outputte data direkte til browseren. I dette tilfælde kan du bruge kontrolfunktionerne PHP output at gemme data i bufferhukommelse, som dit PHP-script har kontrol over.
    Her er et simpelt eksempel:


    ob_start();
    // Udskriv noget tekst (som er gemt i bufferen);
    echo "1. Udfør dette til bufferen
    ";
    // Hent indholdet af bufferen
    $buffer = ob_get_contents();
    // Stop buffering og ryd outputbufferen
    ob_end_clean();
    // Udskriv noget tekst som normalt
    ekko "2. Normal udgang
    ";
    // Udskriv bufferindhold
    echo $buffer;
    ?>

    Selve bufferen gemmer outputtet som en streng. Så i ovenstående script begynder vi at buffere med ob_start og bruge ekko til at udlæse noget. Vi bruger derefter ob_get_contents til at hente de data, der er bufferet af echo-sætningen, og gemme dem i en streng. Ob_end_clean-funktionen stopper outputbuffer og ødelægger dens indhold. Alternativt kan du bruge ob_end_flush til at udskrive indholdet af bufferen. Ovenstående script udsender:

    2. Normal udgang
    1. Udfør dette til bufferen

    Med andre ord fangede vi outputtet af det første ekko og sendte det derefter til browseren efter det andet ekko. Som det kan ses heraf simpelt eksempel, output buffering er meget kraftfuldt værktøj at formulere dit websted, giver det en caching-løsning, som vi snart vil se, og er en fantastisk måde at skjule fejl fra besøgende på dit websted. Det giver også alternativ mulighed at omdirigere browseren i situationer som f.eks. brugergodkendelse.

    HTTP-headere og outputbuffering

    Output buffering kan hjælpe med at løse det meste almindeligt problem forbundet med header-funktionen, for ikke at nævne session_start og set_cookie. Typisk, hvis du kalder nogen af ​​disse funktioner, efter at siden er begyndt at gengive, vil du få en ubehagelig fejlmeddelelse. Når outputbuffering er aktiveret, er den eneste outputtype, der undgår buffering, HTTP-headere. Ved at bruge ob_start helt i begyndelsen af ​​din applikations udførelse, kan du sende headers på et hvilket som helst tidspunkt i programmet, du kan lide, uden at støde på de sædvanlige fejl. Når du derefter er sikker på, at du ikke behøver at udskrive flere HTTP-headere, kan du udskrive sideindholdet fra bufferen med det samme.

    /* Det skal bemærkes, at sådan brug af denne funktion er uberettiget. I de fleste tilfælde er der simpelthen ikke behov for at bruge outputbuffering for at slippe af med fejl af denne type, og alt kan nemt rettes ved korrekt applikationsdesign - ca. oversætter */

    brug af outputbuffering til caching på serversiden

    Du har allerede set et grundlæggende eksempel på outputbuffering, nu er næste trin, hvor bufferen gemmes til en fil:

    // Hvis der findes en cachelagret version...
    if (fil_eksisterer("./cache/2.cache")) (
    // Læs og output filen
    readfile("./cache/2.cache");
    Afslut();
    }
    // Start buffering af output
    ob_start();
    // Udskriv resten af ​​HTML
    ?>
    >http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    >http://www.w3.org/1999/xhtml">

    Cachelagret side

    Denne side er cachelagret ved hjælp af PHP
    Funktioner>http://www.php.net/outcontrol">Outputkontrolfunktioner

    // Hent indholdet af bufferen
    $buffer = ob_get_contents();
    // Stop buffering og output bufferen
    ob_end_flush();
    // Gem en cache-fil med indhold
    $fp = fopen("./cache/2.cache", "w");
    fwrite($fp, $buffer);
    fclose($fp);
    ?>

    Først tjekker dette script for tilstedeværelsen af ​​en version af siden i cachen, og hvis den findes, læser og viser scriptet den. Ellers bruger den outputbuffering til at oprette en cachelagret version af siden. Efter at have brugt ob_end_flush til at vise siden til brugeren, gemmes den som en fil.

    blok buffering

    I en forenklet tilgang cacher vi outputbufferen som en enkelt side. Imidlertid fratager denne tilgang reelle muligheder, leveret af PHP-outputkontrolfunktioner.
    Uden tvivl ændres nogle dele af siden, du sender til din besøgende, meget sjældent, såsom sidehoved, menu og sidefod. Andre dele, såsom tabeller, der indeholder forumdiskussioner, kan dog ændre sig ret ofte. Outputbuffring kan bruges til at cache sektioner af en side ind separate filer, og opret derefter en side fra dem - en løsning, der eliminerer behovet for gentagne databaseforespørgsler, mens sløjfer etc. Du kan tildele hver sideblok en udløbsdato, hvorefter cachefilen genskabes, eller alternativt kan du inkludere en mekanisme i din applikation, der sletter cachefilen, når indholdet, der er gemt i den, ændres.
    Her er et eksempel, der demonstrerer dette princip:

    /
    * Skriv cache-fil
    * @param strengindhold – bufferindhold
    * @param string filnavn – filnavn brugt ved oprettelse af cache-filen
    * @retur ugyldig
    */
    funktion skriveCache($indhold, $filnavn) (
    $fp = fopen("./cache/" . $filnavn, "w");
    fwrite($fp, $indhold);
    fclose($fp);
    }
    * Kontrol af cache-filer
    * @param string filnavn – navnet på cachefilen, der skal kontrolleres
    * @param int udløb – maksimal "alder" for filen i sekunder
    * @return blandet cacheindhold eller falsk
    */
    funktion readCache($filnavn, $udløb) (
    if (fil_eksisterer("./cache/" . $filnavn)) (
    if ((tid() - $udløb) >filemtime("./cache/" . $filnavn))
    returner FALSK;
    $cache = fil("./cache/" . $filnavn);
    return implode("", $cache);
    }
    returner FALSK;
    }
    ?>

    De to første funktioner vi definerede - writeCache og readCache - bruges til henholdsvis at oprette cache-filer og kontrollere deres eksistens. WriteCache-funktionen tager som argumenter de data, der skal cachelagres, og filnavnet, der bruges til at oprette cachefilen. ReadCache-funktionen får navnet på cache-filen og den tid i sekunder, hvorefter cache-filen skal betragtes som forældet. Hvis den finder cache-filen gyldig, vil scriptet returnere dets indhold, ellers vil det returnere FALSE for at angive, at cache-filen ikke eksisterer eller er forældet.

    I dette eksempel brugte jeg en proceduremæssig tilgang. Jeg anbefaler dog ikke at gøre dette i praksis, da det vil ende i meget rodet kode (se efterfølgende løsninger for et bedre alternativ) og sandsynligvis vil forårsage fillåsningsproblemer (f.eks. hvad der sker, når nogen får adgang til cachen, mens den bliver opdateret?).
    Lad os fortsætte med dette eksempel. Når outputbuffering er startet, begynder behandlingen. Scriptet kalder først readCache for at se, om filen 3_header.cache eksisterer - den indeholder sidehovedet, det vil sige HTML-headeren og begyndelsen af ​​brødteksten. Vi bruger datofunktionen til at udlæse det tidspunkt, siden siden faktisk blev genereret, så du vil se de forskellige cache-filer i aktion, når siden gengives.

    // Start buffering af output
    ob_start();
    // Bearbejd overskriften
    if (!$header = readCache("3_header.cache", 604800)) (
    // Header output
    ?>
    >http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    >http://www.w3.org/1999/xhtml">

    Side cachelagret blok for blok

    Tidspunkt for oprettelse af overskrift:

    $header = ob_get_contents();
    ob_clean();
    skriveCache($header,"3_header.cache");
    }
    ?>

    Hvad sker der, når cache-filen ikke findes? Noget indhold udlæses og tildeles en variabel ved hjælp af ob_get_contents, hvorefter bufferen ryddes af ob_clean-funktionen. Dette giver os mulighed for at fange outputtet stykke for stykke og matche det til individuelle cachefiler ved hjælp af writeCache. Sidetitlen er nu gemt som en fil, der kan bruges uden vores indblanding i genopbygningen af ​​siden. Lad os gå tilbage til begyndelsen et øjeblik. betinget operatør. Da vi kaldte readCache, gav vi den en cachelevetid på 604800 sekunder (en uge), readCache bruger ændringstiden for cachefilen til at bestemme, om cachefilen stadig er gyldig.

    For indholdet (brødteksten) på siden vil vi stadig bruge den samme proces. Men denne gang, når vi kalder readCache, vil vi bruge en cachelevetid på fem sekunder, cachefilen vil blive ændret hver gang den er "ældre" end 5 sekunder:

    // Behandle sideteksten
    if (!$body = readCache("3_body.cache", 5)) (
    ekko "Kropsoprettelsestid: " . dato("H:i:s") . "
    ";
    $body = ob_get_contents();
    ob_clean();
    writeCache($body, "3_body.cache");
    }
    ?>

    Sidefoden kan effektivt ændres på samme måde som sidehovedet.
    Slutresultatet ser nogenlunde sådan ud:
    - header oprettelsestid - 17:10:42;
    - kropsskabelsestid - 18:07:40;
    - footer oprettelsestid - 17:10:42.
    Sidehoved og sidefod opdateres ugentligt, mens brødteksten ændres, når den er ældre end 5 sekunder.

    indlejrede buffere

    Du kan indlejre en buffer i en anden praktisk talt på ubestemt tid blot ved at kalde ob_start gentagne gange. Dette kan være nyttigt, hvis du har mange operationer, der bruger outputbufferen, for eksempel nogle, der fanger PHP-fejlmeddelelser, andre, der omhandler caching. Du skal sørge for at ob_end_flush eller ob_end_clean kaldes hver gang ob_start bruges.

    Hvordan kan jeg implementere et simpelt cachingsystem på serversiden?
    Nu hvor vi forstår ideerne bag outputbuffering, er det tid til at se på, hvordan vi kan sætte denne proces ud i livet på en måde, der er nem at vedligeholde. For at gøre dette bruger vi lidt hjælp fra PEAR::CacheLite.

    Som jeg sagde, for at gøre din kode nemmere at vedligeholde og have en pålidelig cachemekanisme, er det klogt at tildele ansvaret for cachelogikken til klasser, som du har tillid til. Cache_Lite er et kraftfuldt, men brugervenligt cachebibliotek, der håndterer opgaver såsom midlertidig låsning af cachefiler, oprettelse og validering af dem, styring af outputbufferen og direkte cachelagring af resultatet af en funktion eller klassemetode. Hovedårsagen til at vælge dette bibliotek er den relativt enkle integration af Cache_Lite i allerede eksisterende applikation, som kun kræver mindre ændringer af koden.

    Cache_Lite består af tre hovedklasser. Den første er basisklassen Cache_Lite, som kun er ansvarlig for at oprette og læse cachefiler og ikke buffer output. Denne klasse kan bruges alene i tilfælde, hvor der ikke er behov for at bruge outputbuffering, såsom når du gemmer resultatet af at parse en skabelon med et PHP-script. Eksemplerne vist her bruger ikke Cache_Lite-klassen direkte og demonstrerer brugen af ​​de to andre klasser. Cache_Lite_Function bruges til at kalde en funktion eller klassemetode og derefter cache resultaterne. Dette kan for eksempel være nyttigt til at cache resultatet af en MySQL-forespørgsel. Cache_Lite_Output-klassen bruger PHP's outputkontrolfunktioner til at opsnappe data genereret af et script og gemme dem i cache-filer. Dette giver dig mulighed for at udføre de samme opgaver som den tidligere løsning.

    Cache_Lite-indstillinger

    I nuværende version klasse (1.1) er følgende indstillinger tilgængelige:
    - cacheDir - mappe, hvor cache-filer vil blive placeret. Standardværdien er den mappe, hvor scriptet udføres;
    - caching - denne mulighed aktiverer eller deaktiverer Cache_Lite-funktioner. For eksempel, hvis du har mange forespørgsler til Cache_Lite, og under fejlfinding vil du deaktivere caching, skal du indstille det til FALSE. Standardværdien er TRUE.
    levetid - parameteren indeholder standardcachens levetid (i sekunder);
    - FileNameProtection - brug MD5-kodning til at generere et cache-filnavn. Dette giver dig mulighed for at bruge alle tegn i navnene på cache-filer og grupper, selv dem, der er forbudt af filsystemet;
    - fileLocking - muliggør mekanismer til at blokere en fil med en cache, mens data skrives til den;
    - writeControl - kontrollerer, at cache-filen blev skrevet korrekt umiddelbart efter endt skrivning;
    - readControl - før læsning af en cache-fil, kontrollerer den for forvrængninger;
    - readControlType - denne parameter bestemmer typen af ​​læsemekanisme for cachefil. Tilgængelige mekanismer: cyklisk redundanstjek, MD5-hash eller simpel kontrol lang Bemærk, at denne mekanisme ikke er beregnet til at beskytte cachefiler mod at blive kaldt direkte eksterne brugere. Dette er blot en måde at afgøre, om en fil er beskadiget eller ej;
    - pearErrorMode - aktiverer PEAR-metoden til at returnere fejl;
    - memoryCaching - hver gang du kalder cachen for at skrive til en fil, skrives den til Cache_Lite-arrayet. saveMemoryCachingState og
    getMemoryCachingState bruges til at få adgang til cachen, der er gemt i hukommelsen mellem anmodninger. Fordelen ved denne metode er, at cacheindholdet kan gemmes i en enkelt fil, hvilket reducerer antallet af disklæse-/skrivecyklusser. Cachen gendannes direkte til et array, som dit script har adgang til;
    memoryCachingLimit - parameteren angiver grænsen for antallet af cachefiler, der kan gemmes i et array i hukommelsen.

    ryd cache

    Cahce_Lite indeholder en vellykket mekanisme til at bestemme levetiden af ​​cache-filer, som skaber godt fundament for sikkerheden af ​​dine filer og deres rettidige opdatering. Der er dog tidspunkter, hvor du skal opdatere din cache-fil med det samme. For sådanne tilfælde er der remove() og clean() metoder. Remove()-metoden er designet til at fjerne en specifik cache-fil. det kræver cache-id'et og navnet på den gruppe, som filen tilhører. Følgende eksempel vil slette body-cache-filen fra det forrige eksempel:

    $cache->remove("body", "Dynamisk");

    Clean()-metoden giver os mulighed for at slette alle filer i vores bibliotek, hvis vi kalder det uden parametre. Hvis du sender gruppenavnet som en parameter, vil alle filer inkluderet i denne gruppe. Hvis vi ville fjerne overskriften og nederste del, så skal du udstede kommandoer, der ligner dette:

    $cache->clean("Statisk");

    Metoderne remove() og clean() skal naturligvis kaldes som svar på hændelser i applikationen. For eksempel, hvis du har et forum, bør du sandsynligvis slette cache-filen, hvis en bruger sender en ny besked. Selvom denne løsning ser pæn ud, kan den indebære nogle kodeændringer. hvis du har hovedskrift, som forbinder til hver side i applikationen, som en besøgende kan se, kan du blot holde øje med indgående hændelser, såsom $_GET["newPost"]-variablen, og fjerne de nødvendige cache-filer. Dette giver dig mulighed for at oprette en centraliseret cachestyringsmekanisme. Du kan endda inkludere denne kode i php.ini.

    cachefunktionskald

    Fordi webtjenester eksponeres over netværket, er det ofte en god idé at cache resultatet, så det kan udføres lokalt i stedet for at køre den samme langsomme forespørgsel flere gange. I det enkleste tilfælde kunne vi bruge PHP sessioner, men da denne løsning fungerer baseret på besøgendes regelmæssighed, vil det stadig være langsomt at åbne en anmodning for hver besøgende. I sådanne tilfælde kan Cache_Lite være meget praktisk.

    PEAR Web-installationsprogrammet bruger Cache_Lite til at cache XML-RPC-anmodninger sendt til PEAR-webserveren.
    Her er koden, der modtager data fra fjernserveren:

    $countries = $stationInfo->listCountries();

    $country = $stationInfo->searchByCountry($_GET["land"]);

    I begge tilfælde svarer disse opkald til en anmodning om data over netværket. Ved at bruge Cache_Lite kunne vi cache de data, der returneres af tjenesten, og være i stand til at genbruge dem. Dette ville undgå yderligere unødvendige netværksforbindelser og ville øge eksekveringshastigheden markant. Bemærk venligst, at her ser vi kun på kode, der er relevant for vores emne. Først aktiverer vi Cache_Lite_Function:

    // Inkluder PEAR::Cache_Lite_Function
    require_once "Cache/Lite/Function.php";

    // Indstil parametre for for Cache_Lite_Function
    // ADVARSEL: fileNameProtection = TRUE!
    $options = array(
    "cacheDir" =>"./cache/",
    "fileNameProtection" =>SAND,
    "writeControl" =>SAND,
    "readControl" =>SAND,
    "readControlType" => "strlen",
    "defaultGroup" =>"SÆBE"
    );
    // Opret et objekt af klassen Cache_Lite_Function
    $cache = ny Cache_Lite_Function($options);

    Det er vigtigt, at parameteren fileNameProtection er sat til TRUE. Denne værdi er standard, men jeg indstillede den specifikt manuelt for at understrege dens betydning. Hvis du indstiller denne parameter til FALSE, får du ugyldigt navn fil, så der vil ikke være nogen caching.
    Dernæst sender vi en anmodning til vores SOAP-klient:

    $countries = $cache->call("stationInfo->listCountries");
    $country = $cache->call("stationInfo->searchByCountry",
    $_GET["land"]);

    Hvis der laves en anmodning for første gang, gemmer Cache_Lite_Function resultaterne som et serialiseret array i en cache-fil (det behøver du ikke at bekymre dig om), og denne fil vil blive brugt til fremtidige anmodninger, indtil dens levetid udløber. setLifeTime kan bruges til at bestemme, hvor længe en cache-fil vil leve, før dens oplysninger opdateres. Standardværdien er 1 time (3600 sekunder).

    PEAR::Cache

    Generelt giver Cach_Lite et enkelt, brugervenligt system til at løse alle caching-relaterede problemer. Fordi næste niveau- dette er websteder med særlig høj trafik, bør du beskæftige dig med PEAR::Cache - "storebror" af Cache_Lite. Det giver også forbedrede caching-funktioner, såsom delt hukommelses-caching som et alternativ til fil-caching, eller Msession PHP-udvidelsen hjælper ved at gemme data i en afbalanceret session, hvilket er særligt nyttigt i balancerede webservere. Cache_Lite tilbyder dog mere end nok funktioner og opfylder behovene på de fleste websteder.

    hvordan håndterer man caching på klientsiden ved hjælp af PHP?

    Nu hvor vi har set på mulighederne for at tilsidesætte klient-side cache, er det tid til at se på en mekanisme, der vil tillade os at kontrollere klient-side cache ved hjælp af PHP. Denne tilgang vil kun fungere, hvis du bruger PHP sammen med Apache server da vi vil bruge getallheaders-funktionen til at få headerne sendt af browseren. Denne funktion virker kun i Apache. Hvis du bruger PHP 4.3.0 med Apache, er det muligt at arbejde med HTTP-headere ved at bruge funktionerne apache_request_headers og apache_response_headers. Getallheaders-funktionen er blevet et alias for den nye apache_request_headers-funktion.

    Mekanismen til at arbejde med webbrowserens cache er igen HTTP. Flere overskrifter er involveret i at instruere webbrowsere og proxyservere til uafhængigt at cache en side. Situationen kompliceres af, at nogle af dem kun er tilgængelige med HTTP 1.1.

    kontrollere HTTP-headere i din browser

    Et simpelt, men meget praktisk værktøj til at kontrollere anmodnings- og svarheadere er LiveHttpHeaders - en tilføjelse til Mozilla browser. Det er vigtigt at vide præcis, hvilke headere dit script sender, især når du har med HTTP-cache-headere at gøre.
    For nemheds skyld vil vi kun overveje HTTP 1.0-cache-headerne, nemlig Expires, Last-Modified og If-Modified-Since, samt HTTP 304 (Ikke ændret) statuskoden.

    Andre headere, der er tilgængelige med HTTP 1.1, såsom Cache-Control og ETag, er beregnet til at give en udvidet mekanisme, der kan bruges i forbindelse med websessionstilstand, med andre ord kan versionen af ​​den samme side, der er beregnet til en uautoriseret besøgende, variere betydeligt fra vist til den autoriserede bruger. HTTP 1.1-headere blev oprindeligt tilføjet for at tillade, at sådanne sider kan cachelagres.

    side levetid udløb

    Den nemmeste header at bruge er Expire header, som angiver datoen for, hvornår siden udløber. Indtil dette tidspunkt har webbrowseren lov til at bruge en cachelagret version af siden.
    Eksempel:


    function setExpires($expires)(
    header("Udløber: " . gmdate("D, d M Y H:i:s", time() + $expires) . "GMT");
    }
    echo "Denne side vil selvdestruere på 10 sekunder
    ";
    ekko "Nu". gmdate("H:i:s") . "GMT
    ";
    ekko "
    ";
    ?>

    Ovenstående eksempel viser den aktuelle GMT-tid og viser et link, der giver dig mulighed for at gå tilbage til siden. Ved at bruge din browsers Opdater-knap kan du fortælle browseren, at du vil opdatere sin cache.

    datoer og tidspunkter i HTTP

    Datoer i HTTP beregnes altid i forhold til Greenwich Mean Time (GMT). PHP gmdate-funktionen er nøjagtig den samme funktion som dato, bortset fra at den automatisk kompenserer for GMT baseret på systemuret og din servers regionsindstillinger. Når browseren støder på Expires-headeren, cacher den siden. Alle efterfølgende anmodninger om siden, der er lavet før det angivne TTL-tidspunkt, bruger den cachelagrede version af siden, uden at foretage nogen anmodninger til webserveren.
    Expires-headeren er i princippet enkel at implementere, men i de fleste tilfælde, medmindre du er en meget organiseret person, kan du ikke vide præcis, hvornår en given side på dit websted vil blive opdateret. Fordi browseren kommer ind for først at kontakte serveren, efter at siden er blevet forældet, er der ingen måde at fortælle browseren, at siden i dens cache er forældet.

    sideskiftetid

    Det er mere praktisk at bruge Last-Modified og If-Modified-Since headerne, der er tilgængelige i HTTP 1.0. Når du bruger denne metode, skal du sende en Last-Modified header som svar på hver anmodning til dit PHP-script. Næste gang browseren anmoder om siden, vil den sende en If-Modified-Since-header, der indeholder den tid, dit script kan bruge til at afgøre, om siden er blevet opdateret siden sidste anmodning. Hvis dette ikke er tilfældet, sender dit script en HTTP 304-statuskode for at angive, at siden ikke er ændret, uden at sidens indhold udskrives. Hvis du kombinerer den sidst ændrede tidstilgang med en tidsværdi, der allerede er tilgængelig i din applikation (f.eks. tidspunktet for den seneste nyhedsartikel), kan du drage fordel af webbrowserens cache og aflæse datalinket og gemme oplysninger trafik fra dit websted, hvor det er muligt. forbedre dets ydeevne.

    Vær forsigtig, når du tester enhver caching udført i denne stil: Hvis du gør det forkert, kan du få dine besøgende til altid at have forældede kopier af dit websted.

    Harry Fuecks, oversættelse af Sergey Mullin (SiMM) og Kuzma Feskov.

    Når du udvikler PHP-projekter fra bunden og uden brug af biblioteker, kan hastighed blive et alvorligt problem. Caching kan påvirke hastigheden på websider betydeligt. I denne tutorial vil vi vise dig en enkel og effektiv metode dynamisk caching af sider, der har brug for acceleration.

    Trin et. Opret en fil top-cache.php

    Vi skal oprette to filer. Først: Opret en fil kaldet top-cache.php og kopier følgende kode ind i den:

    Hvad sker der i denne kode? De første 5 linjer opretter cache-filnavnet iflg nuværende PHP fil. For eksempel, hvis vi bruger en fil med navnet list.php, vil cache-filen se ud som cached-list.html.

    Linje 6 opretter $cachetime-variablen, som angiver cachens levetid.

    Linje 9 til 13 definerer et betinget udtryk, der kontrollerer tilstedeværelsen af ​​en fil med navnet defineret i variablen $cachefile. Hvis filen eksisterer, indsættes en kommentar sammen med filen defineret i $cachefile-variablen. Exit-sætningen afbryder derefter scriptet, og filen sendes til klientbrowseren. Det vil sige, at hvis der findes en statisk fil, vil PHP-koden ikke blive eksekveret af serveren.

    Linje 14 opretter en buffer, hvis filen specificeret af $cachefile ikke findes.

    Trin to. Opret en fil bottom-cache.php

    Lad os nu oprette den anden PHP fil med navnet bottom-cache.php og kopier følgende kode ind i den:

    Hvis en fil med navnet defineret i $cachefile-variablen ikke findes på serveren, udføres denne kode, og filen oprettes. Næste gang siden åbnes, vil den statiske $cachefile tjene klientbrowseren i stedet for at udføre al PHP-scriptkoden.

    Trin tre. Inklusive cache-filer i sidekoden

    Nu har vi to påkrævet fil. Vi inkluderer dem bare PHP side, som skal cachelagres. Top-cache.php-filen skal inkluderes øverst på siden, og bottom-cache.php-filen i slutningen:

    Nu, hvis du tjekker cachen kl langsomme sider, så kan du se, hvor meget hurtigere de indlæses.

    Moderne browsere bruger ret ofte en lokal cache i deres arbejde. Hvad betyder det? Dette betyder, at browseren, efter at have modtaget et HTML-dokument, billede eller anden ressource fra serveren, placerer det i sin lokale cache (med andre ord skriver den modtagne ressource til HDD brugermaskine) og under efterfølgende anmodninger til en sådan ressource ikke får adgang til serveren, men henter ressourcen fra den lokale cache.

    Denne browseralgoritme øger indlæsningshastigheden af ​​HTML-dokumenter dramatisk. Da hvis ressourcen allerede er downloadet og som følge heraf er placeret i den lokale cache, bestemmes adgangstiden ikke af kommunikationskanalens båndbredde (for eksempel en modemforbindelse), men af ​​harddiskens hastighed .

    Men sammen med fordelene denne metode giver også anledning til en række problemer. Især de fleste nybegyndere web-programmører, når de udvikler dynamiske websteder, står over for det samme problem. Essensen af ​​dette problem er, at i stedet for gentagne gange at kontakte serveren for en side, der kører et script på serveren, der ændrer nogle oplysninger, får browseren adgang til den lokale cache. Og som følge af f.eks. tre anmodninger er der ikke tre ændringer af informationen på serveren, men kun én.

    For at tvinge browseren til at anmode om en side fra serveren hver gang, skal du forbyde browseren at komme ind denne ressource at cache. Nedenfor er de mest almindelige metoder til at deaktivere eller omgå caching.

    Generering af en ny URL

    Lad os antage, at den anmodede ressource har følgende url: test.html?id=7. Som du kan se fra url'en, sendes en parameter til den. Lad os f.eks. tilføje hvornår JavaScript hjælp, der er endnu en parameter i url'en, og vi vil gøre den til dens værdi tilfældigt tal. Som et resultat vil webadressen se sådan ud: test.html?id=7&rnd=0.6700820127538827. Den tilfældige parameter vil blive genereret på ny hver gang. Nedenfor er en liste, der viser denne tilgang:

    Generering af en ny URL document.write(""); test link

    Hver gang vil resultatet af en sådan anmodning blive cachelagret, men da caching udføres over hele url'en, vil en ny url blive opnået hver gang, og browseren vil være tvunget til at anmode om en ressource fra serveren, da url'erne på to anmodninger vil ikke matche nøjagtigt.
    Overskriftsfelter

    Du kan også administrere caching fra serversiden. For at opnå dette er den ressource, der sendes til browseren, ledsaget af overskriftsfelter. En detaljeret beskrivelse af overskriftsfelterne kan findes i Rfc 2068-standarden, som beskriver HTTP 1.1-protokollen.

    Udløber overskriftsfelt

    Værdien af ​​denne overskrift er den dato, hvorefter indholdet af ressourcen bliver forældet. Hvis en bruger får adgang til en ressource efter denne dato, skal browseren anmode om ressourcen fra serveren i stedet for fra den lokale cache.

    Hvis feltet >Udløber< содержит дату, прошедшую, по отношению к текущей, то при следующем обращении к ресурсу браузер будет вынужден снова обратиться к серверу. Это произойдет вследствие того, что либо документ не будет занесен в кэш — как уже устаревший, либо при обращении к кэшу браузер определит, что документ уже устарел. Следующий листинг на PHP демонстрирует использование заголовка Expires:

    Sidst ændret overskriftsfelt

    Værdien af ​​denne overskrift er den dato, hvor ressourcen sidst blev opdateret. Flertal moderne browsere brug følgende algoritme, hvis ressourcen allerede er i den lokale cache:

    * anmoder serveren om datoen for den sidste ressourceopdatering
    * sammenligner den modtagne dato og ressourcedatoen i den lokale cache
    * hvis ressourcen på serveren er nyere end ressourcen i cachen, anmodes ressourcen fra serveren

    Hvis en ressource placeret på serveren indeholder i dette felt nuværende dato, så vil browseren anmode om ressourcen fra serveren hver gang og ikke fra den lokale cache. Følgende liste viser brugen af ​​feltet Last-Modified header:

    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");

    Felter Cache-Control header og Pragma

    Og endelig overskriftsfelterne, som er direkte ansvarlige for ressourcecache. Feltet blev defineret i RFC 1945-standarden, der beskriver HTTP 1.0-protokollen. Dette felt anses for at være forældet, men i nogle tilfælde er det nødvendigt at bruge det. Især behandler nogle proxyservere ikke anmodninger om konstant skiftende ressourcer korrekt, hvis dette overskriftsfelt ikke sendes sammen med ressourcen.

    Det andet felt er defineret i RFC 2068-standarden, som beskriver HTTP 1.1-protokollen. Dette overskriftsfelt giver dig mulighed for at deaktivere caching og anmode om en ressource fra serveren hver gang. Følgende liste viser brugen af ​​Cache-Control- og Pragma-headerfelterne til at deaktivere caching:

    header("Cache-kontrol: ingen cache, skal genvalideres"); header("Pragma: ingen cache");

    God dårlig