Et enkelt og effektivt PHP-cachingsystem. WordPress Super Cache, en må-ha WP-plugin

Bufring av mellomdata er den mest primitive og samtidig den mest nyttige måten å optimalisere på, hvor du ikke trenger å bry deg med noen komplekse algoritmer eller forhåndsoptimalisering. Hvis du skal jobbe med PHP, må du være klar over de utprøvde metodene og verktøyene som trengs for å få nettstedet ditt til å fly.

Statiske lokale variabler

En rask og effektiv måte å cache resultatene av en funksjon/metode på er å bruke statiske lokale variabler. La oss se på et eksempel som utfører komplekse beregninger:

Nå, hver gang du bruker en funksjon i kode, uavhengig av antall anrop, vil funksjonen utføre beregninger kun én gang.

Denne bufringsteknikken er uavhengig av eksterne utvidelser og støttes på språknivå. Fordi statiske lokale variabler kun er tilgjengelige innenfor funksjonen de er definert i, kan det være problematisk å oppdatere cachen. Vanligvis krever dette å sende en slags boolsk variabel til $use_cache eller bruke statiske klassevariabler i stedet.

Statiske variabler deles ikke mellom PHP-prosesser og kan bare cache i kort tid - som dekker utførelsestiden til skriptet. En god kandidat er en metode som kalles mange ganger fra flere steder, for eksempel for å lagre brukerstatus eller et resultat som krever stort volum matematiske beregninger.

Den samme funksjonaliteten kan implementeres ved hjelp av globale variabler, men dette vil forurense det globale navneområdet og anbefales ikke.

APC delte minnefunksjoner

PHP er et semi-kompilert språk, noe som betyr at hvert skript ikke kompileres direkte inn i maskinkode, men til mellomkode kjent som et sett med opkoder (bytekode). Dette trinnet kompilering bruker mye CPU-ressurser og må kjøres hver gang skriptet kjøres. APC (Alternativ PHP Cache) er en utvidelse som hopper over dette kompileringstrinnet ved å bufre opkoder i minnet.

Selv om hovedformålet med APC vanligvis anses å være opcode-bufringsfunksjonalitet, inkluderer utvidelsen også noen ekstra minnetilgangsfunksjoner.

Nå er fordelen med denne tilnærmingen åpenbar - det er bruken av delt minne. Denne typen minne deles på tvers av forskjellige prosesser/tråder, og i motsetning til statiske variabler, vil data som bufres på denne måten eksistere på tvers av flere forespørsler.

For å ugyldiggjøre en cache, kan du bruke time to live (TTL) verdier som i eksemplet ovenfor, eller følgende funksjoner:

Andre merknader om støtte for delt minne i APC:

Det er et direktiv i INI-konfigurasjonsfilen for å begrense cachestørrelsen. Med passende TTL-verdier gir dette muligheten til å prioritere hurtigbufrede data der, hvis minnegrensen er nådd, vil utløpte/gamle verdier bli kastet ut av hurtigbufferen.

Fra et ytelsesperspektiv vil statiske variabler alltid være raskere enn apc_fetch/apc_store-funksjoner, siden tilgang til delt minne må låses og synkroniseres for å forhindre konflikter.

APC er en ganske populær utvidelse, og støttes av major PHP utviklere og (svært sannsynlig) vil bli buntet med PHP 5.4.

Memcachert for store distribuerte cacher

Når et nettsted begynner å motta mange treff, blir det til slutt en oppgave å fordele belastningen mellom forskjellige maskiner. Som et resultat må du vanligvis flytte PHP over flere applikasjonsservere. Hvis du har brukt APC-caching før - har hver applikasjonsserver nå en separat og redundant cache.

Memcached på den annen side er en distribuert tjeneste for lagring av nøkkelverdidata. Utvidelsen kan distribueres på en separat dedikert server eller i samme PHP-applikasjonsstabel. Det er viktig å forstå at det ikke er noen synkronisering/replikering mellom flere Memcached-servere, og de vet ikke noe i det hele tatt om hverandre. Den faktiske serveren som skal brukes til lagring velges på klientsiden ved hjelp av en hashing-algoritme basert på de oppgitte "nøkkel"-dataene. Dette er grunnen til at, i motsetning til APC, blir hurtigbufrede data ikke duplisert mellom forskjellige maskiner, og minnet brukes bedre for store distribuerte applikasjoner.

API-en er veldig lik funksjonaliteten for delt minne i APC. Samme eksempel med valutaveksling, implementert med bruker PHP Memcache-utvidelser:

Cache-oppdatering er den samme som i APC - ved å bruke TTL-funksjonalitet eller et sett med funksjoner.

Lokal APC-cache vil alltid være større rask metode sammenlignet med Memcached.

Det er alltid forsinkelser i nettverket når klienten trenger å kommunisere med backend-tjenesten via en dedikert tekstprotokoll.

Databasetabeller i tilfeldig tilgangsminne

Selv om det ikke er spesifikt for PHP, har mange databasebehandlingssystemer en tabellimplementering i minnet. Data som er lagret i slike tabeller beholdes ikke mellom server-omstarter, er garantert inneholdt i minnet, og blir aldri sendt ut til disk. Dette betyr raskere tilgang til poster, noe som gjør dem egnet for databufring.

MySQL gir tabeller i minnet i lagringsundersystemet MEMORY. Selv om dataene vil bli slettet etter at serveren er startet på nytt, vil tabellskjemaene bli bevart:

CREATE TABLE test (...) MOTOR = MINNE

PostgreSQL har midlertidige tabeller som bare eksisterer under en økt; for å bufre data i en midlertidig tabell, må en vedvarende tilkobling til databasen opprettholdes.

OPPRETT MIDLERTIDIG TABELL-test (...)

I SQLite kan du lage en hel database i minnet, men med de samme restriksjonene som i PostgreSQL - dataene vil kun eksistere under varigheten av økten, og du må bruke vedvarende forbindelserå opprettholde dem mellom flere forespørsler.

Så hva kan du gjøre med en tabell i RAM? Selv om et slikt bord aldri vil eksistere raskere tilgang til nøkkelverdidata i APC/Memcached får du kraften til SQL. Bufret data kan filtreres, sorteres, grupperes og til og med slås sammen med andre data i tabeller.

Enkel filbuffer

Flat filbuffer bør være et alternativ til metodene nevnt ovenfor og bør kun brukes når systemet ikke har de nødvendige utvidelsene eller de aktuelle dataene ikke kan lagres i minnet (f.eks. på grunn av størrelse)

Fordi caching gjøres for å forbedre ytelsen, og ytelsesoptimaliseringer er et resultat av høy samtidighet – bør fillåsing alltid brukes for å forhindre lese/skrive løpsforhold:

I de gode gamle dager var det så enkelt å lage nettsider som å skrive noen få HTML-sider, var å sende nettsider til nettleseren ganske enkelt å sende en fil av webserveren. Besøkende på nettstedet kunne se disse små, bare tekstsider nesten umiddelbart (bortsett fra brukere av trege modemer). Når siden er lastet inn, bufrer nettleseren den et sted på lokal datamaskin slik at hvis siden blir bedt om igjen, kan du ta den lokal versjon fra hurtigbufferen, kun sending kort forespørsel for å sikre at siden på serveren ikke er endret. Forespørsler ble behandlet raskt og så effektivt som mulig, og alle var fornøyde (unntatt de som brukte 9600 baud-modem).

Utseende dynamiske nettsider endret ting til det verre, og effektivt "bryte" denne modellen for visning av nettsider på grunn av tilstedeværelsen av to problemer:

  • Når serveren mottar en forespørsel om en dynamisk nettside, utføres noe mellombehandling, for eksempel parsing av skriptet av motoren PHP som må fullføres. Takket være dette får vi en forsinkelse før webserveren begynner å sende utdata til nettleseren. For enkelt PHP-skript dette er ikke nødvendig, men for mer kompleks applikasjon motor PHP kan ta mange skritt før siden er klar til å sendes. Disse ytterligere handlinger føre til en merkbar forsinkelse mellom brukerforespørsler og faktisk visning av sider i deres nettlesere.
  • En typisk nettserver, for eksempel Apache, bruker filendringstid for å fortelle nettleseren korrekt buffertilstanden til den forespurte siden. For dynamiske nettsider, faktisk PHP-et skript kan endres bare av og til, mens innholdet det viser, muligens plassert i en database, endres ofte. Webserveren har ingen mulighet til å vite at det har vært endringer i databasen, men den sender ikke siste endringsdato. Dersom klienten (nettleseren) ikke får noen indikasjon på hvor lenge dataene har vært korrekte, antar den at den må be om en ny side neste gang. Nettserveren vil alltid svare med en oppdatert versjon av siden, uavhengig av om dataene er endret. For å unngå denne ulempen bruker de fleste nettutviklere metakoder eller HTTP- overskrifter for å fortelle nettleseren å aldri bruke den hurtigbufrede versjonen av siden. Dette opphever imidlertid nettleserens naturlige evne til å bufre nettsider og har noen betydelige mangler. For eksempel kan innholdet på en dynamisk side endres én gang om dagen, så fordelen som oppnås ved å ha nettleseren til å bufre siden selv i 24 timer er åpenbar.
  • Vanligvis for små PHP-applikasjoner er det fullt mulig å ignorere eksistensen av disse problemene, men ettersom kompleksiteten og trafikken til nettstedet ditt øker, kan du støte på problemer. Imidlertid kan begge disse problemene løses, det første ved caching på serversiden, det andre ved å administrere caching på klientsiden fra applikasjonen din. Tilnærmingen du tar for å løse problemene vil avhenge av applikasjonen din, men i dette kapittelet vil vi se hvordan du kan løse både problemer ved hjelp av PHP og noen bibliotekklasser PÆRE.

    Hvordan forhindrer jeg nettlesere fra å bufre en side?

    Før vi ser på teknikker for klient- og serverbufring, må vi først forstå hvordan vi forhindrer nettlesere (og proxy-servere) fra å bufre sider i utgangspunktet. Den viktigste måten å oppnå dette på er å bruke HTML-metakoder:

    Ved å sette inn en tidligere dato i Expires-metakoden, forteller du nettleseren at den hurtigbufrede kopien av siden alltid er utdatert. Dette betyr at nettleseren aldri skal bufre siden. Metatag Pragma: no-cache er en ganske godt støttet konvensjon som de fleste nettlesere følger. Når de oppdager denne taggen, cacher de vanligvis ikke siden (selv om det ikke er noen garanti, dette er bare en konvensjon).

    Dette høres bra ut, men det er to problemer med å bruke metakoder:

  • Hvis taggen ikke eksisterte da siden først ble bedt om av nettleseren, men dukker opp senere (du endret for eksempel filen pageheader.php include som er overskriften på hver nettside), vil nettleseren forbli lykkelig uvitende og bruke sin bufret kopi av originalen.
  • Proxy-servere som cacher nettsider, for eksempel delte ISP, vil ikke undersøke innholdet direkte i det hele tatt HTML-dokument. I stedet stoler de kun på webserveren som dokumentene kom fra og protokollen HTTP. Med andre ord kan nettleseren tenke at den ikke skal bufre siden, men proxy-serveren mellom nettleseren og nettserveren din vet sannsynligvis ikke dette - og vil fortsette å sende den samme, nå foreldede siden til klienten .
  • Den beste tilnærmingen er å bruke protokollen direkte HTTP ved å bruke PHP header()-funksjonen, tilsvarende de to metakodene ovenfor:

    Vi kan gå ett skritt videre ved å bruke Cache-Control-overskriften, som er kompatibel med nettlesere som støtter HTTP 1.1:

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

    Dette sikrer at ingen nettleser eller mellomliggende proxy-server cacher siden, slik at besøkende alltid får den best mulige opplevelsen. siste versjon innhold. Faktisk burde den første overskriften være selvstendig, dette Den beste måten sørg for at siden ikke er bufret. Cache-Control- og Pragma-hodene ble lagt til for å være på den sikre siden. Selv om de ikke fungerer i alle nettlesere eller proxyer, vil de fange opp noen tilfeller der Expires ikke fungerer som forventet (for eksempel hvis datoen på klientens datamaskin er feil angitt).

    Å unngå caching gir oss selvfølgelig problemene vi diskuterte i begynnelsen av dette kapittelet. Vi skal nå se på å løse disse problemene.

    Internet Explorer og filnedlastingsbufring

    Hvis når du betjener en filnedlasting PHP-skriptet bruker overskrifter som Content-Disposition: attachment, filename=myFile.pdf eller Content-Disposition: inline, filename=myFile.pdf du vil ha problemer med Internet Explorer'om hvis du ber nettleseren om ikke å bufre siden.

    Internet Explorer håndterer nedlastinger på en ganske uvanlig måte, og sender to forespørsler til nettstedet. Den første forespørselen laster ned filen og lagrer den i hurtigbufferen til den andre forespørselen gjøres (uten å lagre svaret). Denne forespørselen fører til at prosessen overfører filen til sluttbrukeren i henhold til filtypen (for eksempel starter Acrobat Reader hvis filen er PDF-dokument). Dette betyr at hvis du sendte overskrifter som hindrer nettleseren i å bufre siden, Internet Explorer vil slette filen mellom første og andre forespørsel, noe som resulterer i slutt bruker vil ikke få noe. Hvis filen du gir PHP-script endres ikke, en av de enkleste løsningene ville være å fjerne de "caching-forbudte" overskriftene fra skriptet.

    Hvis filen som lastes ned endres regelmessig (dvs. du vil at nettleseren skal laste ned den nyeste versjonen), bør du bruke overskriften Last-Modified, som vil bli dekket senere i dette kapittelet, og sørge for at endringstiden mellom to påfølgende forespørsler ikke endring. Du må gjøre dette på en måte som ikke påvirker brukere av nettlesere som håndterer nedlastinger riktig. En løsning i dette tilfellet vil være å lagre filen på webserveren din og gi en enkel lenke til den, slik at webserveren kan rapportere cachinghodene for deg. Selvfølgelig kan denne løsningen ikke være akseptabel hvis autorisert tilgang til filen antas; denne løsningen tillater direkte lasting av den lagrede filen.

    Hvordan kan jeg fange data på serversiden for caching?

    Det er på tide å se på hvordan vi kan redusere ventetiden ved å bruke server-side output caching. Den generelle tilnærmingen er å begynne å gjengi siden som vanlig, kjøre databasespørringer og så videre PHP. Men før vi sender resultatet til nettleseren, fanger vi det opp og lagrer det klar side, for eksempel i filen. Ved neste forespørsel, PHP-skriptet sjekker først for tilstedeværelsen av en bufret versjon av siden. Hvis det eksisterer, sender skriptet den hurtigbufrede versjonen til nettleseren, og eliminerer dermed forsinkelsen med å gjenopprette siden.

    Noen få ord om bufring ved hjelp av maler Hvordan administrerer jeg hurtigbufring på klientsiden? bruker PHP?

    Det er på tide å se på en mekanisme som vil tillate oss å kontrollere hurtigbufferen på klientsiden med midler PHP. Denne tilnærmingen vil bare fungere hvis du bruker PHP i forbindelse med serveren Apache siden vi skal bruke getallheaders()-funksjonen for å få overskriftene sendt av nettleseren. Denne funksjonen fungerer kun i Apache.

    Nye funksjonsnavn

    Hvis du bruker PHP 4.3.0 s Apache HTTP-hoder får tilgang til funksjonene apache_request_headers() og apache_response_headers(). Getallheaders()-funksjonen har blitt et alias for den nye apache_request_headers()-funksjonen.

    Mekanismen for å jobbe med nettleserbufferen er igjen HTTP. Mange overskrifter er involvert i å instruere nettlesere og proxy-servere om å bufre en side uavhengig, en situasjon komplisert av det faktum at noen av dem kun er tilgjengelige fra HTTP 1.1.

    Sjekker HTTP-hoder i nettleseren din

    Enkelt, men veldig praktisk verktøy for å sjekke forespørsels- og svarhodene er LiveHttpHeaders– nettlesertillegg Mozilla. Det er nødvendig å vite nøyaktig hvilke overskrifter skriptet ditt sender, spesielt når du har å gjøre med bufringshoder HTTP.

    For enkelhets skyld vil vi kun vurdere HTTP 1.0-bufringshodene, nemlig Expires, Last-Modified og If-Modified-Since, samt HTTP 304 (Not Modified) statuskoden.

    Andre titler tilgjengelig fra HTTP 1.1, slik som Cache-Control og ETag, er ment å gi en avansert mekanisme som kan brukes i forbindelse med nettøktstatus, med andre ord kan versjonen av en gitt side som vises til en uautorisert besøkende være vesentlig forskjellig fra den som vises til en autorisert bruker. Overskrifter HTTP 1.1 ble opprinnelig lagt til for å tillate at slike sider kan bufres.

    Side levetid utløper

    Den enkleste overskriften å bruke er Expire-overskriften, som angir en dato (muligens i fremtiden) når siden skal utløpe. Inntil dette har nettleseren lov til å bruke den hurtigbufrede versjonen av siden.

    Eksempel 7. 6.php

    SetExpires-funksjonen sender overskriften HTTP Utløper med en fremtidig tid spesifisert i sekunder. Eksempelet ovenfor viser nåværende tid GMT og viser en lenke som lar deg gå til siden igjen. Ved å bruke nettleserens Oppdater-knapp kan du fortelle nettleseren at du vil oppdatere bufferen. Ved å bruke lenken vil du se at tiden kun endres en gang hvert 10. sekund.

    Datoer og klokkeslett i HTTP

    Datoer i HTTP beregnes alltid i forhold til Greenwich Mean Time (GMT). PHP funksjon gmdate() er nøyaktig samme funksjon som date() , bortsett fra at den automatisk kompenserer for GMT-tid basert på systemklokken og serverens regioninnstillinger.

    Når nettleseren støter på Expires-overskriften, bufrer den siden. Alle påfølgende forespørsler for siden gjort før den angitte utløpstiden bruker den hurtigbufrede versjonen av siden, og ingen forespørsler sendes til webserveren.

    Expires-overskriften er stort sett enkel å implementere, men i de fleste tilfeller, med mindre du er en svært organisert person, har du ingen mulighet til å vite nøyaktig når en gitt side på nettstedet ditt er oppdatert. Siden nettleseren bare vil kontakte serveren etter at siden har blitt foreldet, er det ingen måte å fortelle nettleseren at en side i cachen er foreldet. Du mister også noe trafikk til nettstedet ditt fordi nettleseren ikke kontakter serveren når du ber om en bufret side.

    Sidebyttetid

    Det er mer praktisk å bruke overskriftene Last-Modified og If-Modified-Since, tilgjengelig i HTTP 1.0. Teknisk kjent som å lage en betinget GET-forespørsel, returnerer du alt innhold basert på forespørselshodebetingelsen If-Modified-Since.

    Når du bruker denne metoden, må du sende en Last-Modified header hver gang PHP-skriptet åpnes. Neste gang nettleseren ber om siden, vil den sende en If-Modified-Since-overskrift som inneholder klokkeslettet, som skriptet ditt kan bruke til å avgjøre om siden har blitt oppdatert siden siste forespørsel. Hvis dette ikke er tilfelle, sender skriptet en HTTP 304-statuskode for å indikere at siden ikke er endret, uten å skrive ut sideinnholdet.

    Still inn endringstiden for cachefilen med denne linjen: $lastModified = filemtime($cache_file);

    Deretter, ved å bruke endringstiden til hurtigbufferfilen, sender vi Last-Modified-overskriften. Vi må sende dette for hver side som vises for å tvinge nettleseren til å sende oss en If-Modified-Since-overskrift med hver forespørsel.

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

    Hvis du kombinerer tilnærmingen til tid siste endring Med en tidsverdi som allerede er tilgjengelig i applikasjonen din (for eksempel tidspunktet for den siste nyhetsartikkelen, eller utløpstiden fra serverens hurtigbuffersystem vi så i forrige løsning), kan du dra nytte av nettleserens hurtigbuffer og avlaste datakoblingen med muligheter for å lagre informasjonstrafikk fra nettstedet ditt og forbedre ytelsen.

    Vær forsiktig når du tester caching utført i denne stilen; hvis du gjør det feil, kan du føre til at de besøkende alltid har utdaterte kopier av nettstedet ditt.

    Bufre sidene dine i 5 trinn Opprinnelig: Skrevet i PHP / JavaScript av ibzi den 17. februar 2007
    Oversettelse: Kuzma Feskov ( [e-postbeskyttet],http://kuzma.russofile.ru)

    Å bufre sidene dine kan være en fin og nyttig mekanisme, spesielt hvis de er generert ved hjelp av PHP og gjør mange ting SQL-spørringer. Så snart du bruker caching, vil serveren umiddelbart redusere belastningen og slutte å spise opp mye minne for å generere sider - den vil ganske enkelt laste dem fra cachen. Jeg skal vise deg hvordan PHP kan bufre sider, og i fremtiden kan du bruke omtrent 5 minutter på å gjøre det.


    La oss se på hurtigbufferteknologi trinn for trinn:

  • I hjemmekatalogen lager vi filene .htaccess, start_cache.php, end_cache.php, samt en mappe kalt cache_files.
  • Cache_files-mappen må tildeles 777 attributter.
  • Skriv inne 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/brukernavn/public_html/ må erstattes med banen til hjemmekatalogen din.
  • Vi legger inn følgende kode i start_cache.php-skriptet: Ikke glem å korrigere banen /home/brukernavn/public_html/ til banen til hjemmekatalogen din.
  • Og plasser følgende kode i end_cache.php-skriptet:
  • Alle sidene dine vil bli bufret i 3600 sekunder = 1 time. Du kan enkelt endre denne parameteren i start_cache.php-skriptet. Sidebufferen vil bli lagret i cache_files-mappen.

    Det er ganske åpenbart at i i dette tilfellet 777 attributter er et klart sikkerhetsbrudd. I denne forbindelse anbefaler jeg å flytte cahce_files-mappen utenfor public_html, for eksempel å plassere den ett nivå høyere. Dette vil blokkere tilgangen til filene i den for brukere av nettstedet ditt, men vil ikke påvirke ytelsen til systemet på noen måte.

    Denne metoden har også en annen alvorlig ulempe: forfatteren av artikkelen legger hele cachen i én mappe, som, hvis det er et tilstrekkelig antall sider på nettstedet ditt, vil forårsake et problem, for eksempel på Unix-systemer er det en betydelig nedgang i ytelsen når det er mer enn 1000 filer i en mappe. I den forbindelse er det nødvendig å gjøre en rekke endringer i algoritmen og organisere filene i separate undermapper inne i cache_files-mappen. For eksempel å bruke de første 3-4 tegnene i md5-cachen for dette.

    Til dynamiske ressurser Det er fullt mulig å velge en caching-tid på flere (5-10) sekunder eller 1-2 minutter, noe som vil redusere belastningen på serveren betydelig, men vil ikke skade nettstedets interaktivitet.

    For sider der interaktivitet er spesielt viktig, kan du introdusere unntak i .htaccess, som vil tillate dem å endre seg hele tiden, og for andre sider kan du bruke caching.

    Regenerering av innhold på farten

    Dynamisk opprettede, men statisk vedlikeholdte sider, dvs. sider som skal overføres som rent statiske (les fra filsystem og deretter overført på forespørsel), men de må genereres dynamisk av webserveren hvis de ikke er i filsystemet. På denne måten kan du få PHP-genererte sider som serveres statisk med mindre noen (eller planleggeren) fjerner det statiske innholdet. I dette tilfellet oppdateres innholdet.

    Dette gjøres med følgende sett med direktiver:

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

    Her fører en forespørsel til page.html til at tilsvarende page.php kjøres internt hvis page.html fortsatt mangler eller har null størrelse. Trikset her er at page.php er vanlig PHP et skript som, i tillegg til sin egen utgang, skriver sin utgang til side.html-filen. Ved å kjøre dette én gang sender serveren dataene til page.html. Når webmasteren ønsker å oppdatere innholdet, sletter han ganske enkelt page.html (vanligvis ved hjelp av en cronjob).

    Det er et problem med sidebufring i Internet Explorer.

    I IE, når du arbeider med "Vary"-overskriften, er det en ubehagelig feil relatert til sidebufring. Problemet løses ved å legge til følgende linjer i .htaccess:


    caching i PHP

    I de gode gamle dager, da det å lage nettsider var så enkelt som å skrive opp noen få HTML-sider, var det å sende nettsider til nettleseren en enkel sak om at webserveren sendte en fil. Besøkende på nettstedet kunne se disse små, bare tekstsider nesten umiddelbart (bortsett fra brukere av trege modemer). Når siden er lastet, bufrer nettleseren den et sted på den lokale datamaskinen slik at hvis siden blir bedt om igjen, kan den hente den lokale versjonen fra hurtigbufferen, og sender bare en kort forespørsel for å sikre at siden på serveren ikke har blitt modifisert. Forespørsler ble behandlet raskt og effektivt, og alle var fornøyde (unntatt de som brukte 9600 baud-modem).

    Fremkomsten av dynamiske nettsider endret ting til det verre, og brøt effektivt denne nettsideserveringsmodellen på grunn av to problemer:

    1. Når serveren mottar en forespørsel om en dynamisk nettside, utføres noe mellombehandling, for eksempel parsing av skriptet av PHP-motoren, som må fullføres. Dette gir oss en forsinkelse før webserveren begynner å sende utdata til nettleseren. For et enkelt PHP-skript er ikke dette vesentlig, men i tilfelle en mer kompleks applikasjon kan PHP-motoren utføre mange handlinger før siden er klar til å sendes. Disse ekstra trinnene resulterer i en merkbar forsinkelse mellom brukerforespørsler og sidene som faktisk vises i deres nettlesere.

    2. En typisk nettserver, for eksempel Apache, bruker filendringstid for å fortelle nettleseren korrekt buffertilstanden til den forespurte siden. På dynamiske nettsteder kan selve PHP-skriptet bare endres av og til, mens innholdet det viser, muligens i en database, endres ofte. Nettserveren har ingen mulighet til å vite om endringer i databasen, så den sender ikke siste endringsdato. Dersom klienten (nettleseren) ikke får noen indikasjon på hvor lenge dataene har vært korrekte, antar den at den må be om en ny side neste gang. Nettserveren vil alltid svare oppdatert versjon sider, uavhengig av om dataene er endret. For å unngå denne mangelen bruker de fleste nettutviklere metakoder eller HTTP-overskrifter for å instruere nettleseren til aldri å bruke den bufrede versjonen av siden. Dette opphever imidlertid nettleserens naturlige evne til å bufre nettsider og har noen betydelige ulemper. For eksempel kan innholdet på en dynamisk side endres én gang om dagen, så fordelen som oppnås ved å ha nettleseren til å bufre siden selv i 24 timer er åpenbar.

    Vanligvis for små PHP-applikasjoner er det fullt mulig å ignorere eksistensen av disse problemene, men ettersom kompleksiteten og trafikken til nettstedet ditt øker, kan du støte på problemer. Imidlertid kan begge disse problemene løses: det første ved caching på serversiden, det andre ved å administrere caching på klientsiden fra applikasjonen din. Tilnærmingen du tar vil avhenge av dine spesifikke behov, men i denne artikkelen viser vi hvordan du kan løse både problemer ved å bruke PHP og noen PEAR-bibliotekklasser.

    hvordan forhindrer jeg nettlesere fra å bufre en side?

    Før vi ser på teknikker for klient- og serverbufring, må vi først forstå hvordan vi forhindrer nettleseren (og proxy-servere) fra å bufre sider i utgangspunktet. Den viktigste måten å oppnå dette på er å bruke HTML-metakoder:

    Ved å sette inn en tidligere dato i Expires-metakoden, forteller du nettleseren at den hurtigbufrede kopien av siden alltid er utdatert. Dette betyr at nettleseren aldri skal bufre siden. Metatag Pragma: no-cache er en ganske godt støttet konvensjon som de fleste nettlesere følger. Når de oppdager denne taggen, cacher de vanligvis ikke siden (selv om det ikke er noen garanti, dette er bare en konvensjon). Dette høres bra ut, men det er to problemer med å bruke metakoder:

    1. Hvis taggen ikke eksisterte da siden først ble forespurt av nettleseren, men vises senere (du endret for eksempel filen pageheader.php include som er overskriften på hver nettside), vil nettleseren forbli lykkelig uvitende og bruke sin hurtigbufrede kopi av originalen.

    2. Proxy-servere som cacher nettsider vil ikke direkte undersøke innholdet i HTML-dokumentet i det hele tatt. I stedet stoler de kun på webserveren som dokumentene kom fra, og HTTP-protokoll. Med andre ord kan nettleseren tenke at den ikke skal bufre siden, men proxyen mellom nettleseren og nettserveren vet sannsynligvis ikke dette – og vil fortsette å sende den samme siden til klienten.

    En bedre tilnærming er å bruke HTTP-protokollen direkte ved å bruke PHP-header-funksjonen:


    header("Pragma: no-cache");
    ?>

    Vi kan gå ett skritt videre ved å bruke Cache-Control-overskriften, som er kompatibel med nettlesere som støtter HTTP 1.1:

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

    Dette sikrer at ingen nettleser eller mellomliggende proxy-server bufrer siden, slik at besøkende alltid mottar den mest oppdaterte versjonen av innholdet. Faktisk bør den første overskriften være selvstendig; dette er den beste måten å sikre at siden ikke er bufret. Cache-Control- og Pragma-hodene er lagt til av sikkerhetshensyn. Selv om de ikke fungerer i alle nettlesere eller proxyer, vil de fange opp noen tilfeller der Expires ikke fungerer som forventet (for eksempel hvis datoen på klientens datamaskin er feil angitt). Å unngå caching gir oss selvfølgelig problemene vi diskuterte i begynnelsen av dette kapittelet. Vi skal nå se på å løse disse problemene.

    Internet Explorer og filnedlastingsbufring

    Det kan oppstå problemer når du håndterer hurtigbufring og nedlasting av filer. Hvis du bruker overskrifter som Content-Disposition: attachment, filename=myFile.pdf eller Content-Disposition: inline, filename=myFile.pdf når du betjener en filnedlasting med et PHP-skript, vil du få problemer med Internet Explorer hvis du be nettleseren om ikke å bufre siden.

    Internet Explorer håndterer nedlastinger på en ganske uvanlig måte, og sender to forespørsler til nettstedet. Den første forespørselen laster ned filen og lagrer den i hurtigbufferen til den andre forespørselen gjøres (uten å lagre svaret). Denne forespørselen fører til at prosessen overfører filen til sluttbrukeren i henhold til filtypen (for eksempel starter Acrobat Reader, hvis filen er et PDF-dokument). Dette betyr at hvis du sender overskrifter som hindrer nettleseren i å bufre siden, vil Internet Explorer slette filen mellom første og andre forespørsel, noe som ikke resulterer i noe for sluttbrukeren. Hvis filen du tjener som et PHP-skript ikke endres, er en av de enkleste løsningene å fjerne de "caching-hemmende" overskriftene fra skriptet.

    Hvis filen som lastes ned endres regelmessig (det vil si at nettleseren skal laste ned den nyeste versjonen), bør du bruke overskriften Last-Modified og sørge for at endringstiden mellom to påfølgende forespørsler ikke endres. Du må gjøre dette på en måte som ikke påvirker brukere av nettlesere som håndterer nedlastinger riktig. En løsning i dette tilfellet vil være å lagre filen på webserveren din og gi en enkel lenke til den, slik at webserveren kan rapportere cachinghodene for deg. Selvfølgelig kan denne løsningen ikke være akseptabel hvis autorisert tilgang til filen antas, siden den tillater direkte lasting av den lagrede filen.

    hvordan kan jeg fange data på serversiden for caching?

    Det er på tide å se på hvordan vi kan redusere ventetiden ved å bruke server-side output caching. Så du kan betjene siden som vanlig, kjøre databasespørringer og så videre i PHP. Men før vi sender resultatet til nettleseren, fanger vi det og lagrer den ferdige siden, for eksempel i en fil. Ved neste forespørsel ser PHP-skriptet først etter en bufret versjon av siden. Hvis det eksisterer, sender skriptet den hurtigbufrede versjonen til nettleseren, og eliminerer dermed forsinkelsen med å gjenopprette siden.

    Noen få ord om bufring ved hjelp av maler. Tilstedeværelsen av malmotorer som Smarty snakker ofte om malbufring. Vanligvis tilbyr disse motorene en innebygd mekanisme for å lagre en kompilert versjon av malen (det vil si å generere PHP-kilde fra malen), som hindrer oss i å måtte analysere malen hver gang en side blir forespurt. Dette må ikke forveksles med utgangsbufring, som refererer til bufring av den medfølgende HTML-en (eller annen utgang) som PHP sender til nettleseren. Du kan bruke begge typer hurtigbufring samtidig på samme nettsted.

    Vi skal nå se på PHPs innebygde hurtigbuffermekanisme som bruker utdatabuffring, som du kan bruke uavhengig av hvordan du lager innholdet ditt (med eller uten maler). Tenk på en situasjon der skriptet ditt viser resultatet, ved å bruke for eksempel ekko eller utskrift for å sende ut data direkte til nettleseren. I dette tilfellet kan du bruke kontrollfunksjonene PHP-utgangå lagre data i bufferminne, som PHP-skriptet ditt har kontroll over.
    Her er et enkelt eksempel:


    ob_start();
    // Skriv ut litt tekst (som er lagret i bufferen);
    echo "1. Send dette til bufferen
    ";
    // Få innholdet i bufferen
    $buffer = ob_get_contents();
    // Stopp bufring og tøm utdatabufferen
    ob_end_clean();
    // Skriv ut litt tekst som vanlig
    ekko "2. Normal utgang
    ";
    // Skriv ut bufferinnhold
    ekko $buffer;
    ?>

    Selve bufferen lagrer utdataene som en streng. Så i skriptet ovenfor begynner vi å bufre med ob_start og bruker ekko for å sende ut noe. Vi bruker deretter ob_get_contents for å hente dataene som er bufret av ekkosetningen og lagre dem i en streng. Ob_end_clean-funksjonen stopper utgangsbuffring og ødelegger innholdet. Alternativt kan du bruke ob_end_flush til å skrive ut innholdet i bufferen. Skriptet ovenfor vil gi ut:

    2. Normal utgang
    1. Send denne ut til bufferen

    Med andre ord fanget vi utdataene fra det første ekkoet, og sendte det til nettleseren etter det andre ekkoet. Som man kan se av dette enkelt eksempel, utgangsbuffring er veldig kraftig verktøy for å formulere nettstedet ditt, gir det en hurtigbufferløsning, som vi snart vil se, og er en fin måte å skjule feil fra besøkende til nettstedet ditt. Det gir også alternativ mulighet for å omdirigere nettleseren i situasjoner som brukerautentisering.

    HTTP-hoder og utgangsbuffring

    Output buffering kan bidra til å løse det meste vanlig problem knyttet til header-funksjonen, for ikke å snakke om session_start og set_cookie. Vanligvis, hvis du kaller noen av disse funksjonene etter at siden har begynt å gjengi, vil du få en ekkel feilmelding. Når utgangsbuffring er aktivert, er den eneste utdatatypen som unngår bufring HTTP-hoder. Ved å bruke ob_start helt i begynnelsen av programmets kjøring, kan du sende overskrifter når som helst i programmet du liker uten å støte på de vanlige feilene. Så, når du er sikker på at du ikke trenger å skrive ut flere HTTP-hoder, kan du skrive ut sideinnholdet fra bufferen med en gang.

    /* Det skal bemerkes at slik bruk av denne funksjonen er uberettiget. I de fleste tilfeller er det rett og slett ikke nødvendig å bruke utgangsbuffring for å bli kvitt feil av denne typen, og alt kan enkelt rettes ved riktig applikasjonsdesign - ca. oversetter */

    ved å bruke utgangsbuffring for caching på serversiden

    Du har allerede sett et grunnleggende eksempel på utdatabuffring, nå er neste trinn hvor bufferen lagres i en fil:

    // Hvis det finnes en bufret versjon...
    if (fil_eksisterer("./cache/2.cache")) (
    // Les og skriv ut filen
    readfile("./cache/2.cache");
    exit();
    }
    // Start bufring av utdata
    ob_start();
    // Skriv ut resten av HTML-en
    ?>
    >http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    >http://www.w3.org/1999/xhtml">

    Bufret side

    Denne siden er bufret med PHP
    Funksjoner>http://www.php.net/outcontrol">Utgangskontrollfunksjoner

    // Få innholdet i bufferen
    $buffer = ob_get_contents();
    // Stopp bufring og skriv ut bufferen
    ob_end_flush();
    // Lagre en hurtigbufferfil med innhold
    $fp = fopen("./cache/2.cache", "w");
    fwrite($fp, $buffer);
    fclose($fp);
    ?>

    Først sjekker dette skriptet om det finnes en versjon av siden i hurtigbufferen, og hvis den eksisterer, leser og viser skriptet den. Ellers bruker den utdatabuffring for å lage en bufret versjon av siden. Etter å ha brukt ob_end_flush for å vise siden til brukeren, lagres den som en fil.

    blokk bufring

    I en forenklet tilnærming bufrer vi utdatabufferen som en enkelt side. Imidlertid fratar denne tilnærmingen reelle muligheter, levert av PHP-utgangskontrollfunksjoner.
    Uten tvil endres enkelte deler av siden du sender til besøkende svært sjelden, for eksempel topptekst, meny og bunntekst. Imidlertid kan andre deler, for eksempel tabeller som inneholder forumdiskusjoner, endres ganske ofte. Utdatabuffring kan brukes til å bufre deler av en side inn separate filer, og lag deretter en side fra dem - en løsning som eliminerer behovet for gjentatte databasespørringer, mens looper etc. Du kan tilordne hver sideblokk en utløpsdato som hurtigbufferfilen gjenskapes etter, eller alternativt kan du inkludere en mekanisme i programmet som sletter hurtigbufferfilen hver gang innholdet som er lagret i den endres.
    Her er et eksempel som viser dette prinsippet:

    /
    * Skriv cache-fil
    * @param strenginnhold – bufferinnhold
    * @param string filnavn – filnavn som brukes når du oppretter hurtigbufferfilen
    * @retur ugyldig
    */
    funksjon skriveCache($innhold, $filnavn) (
    $fp = fopen("./cache/" . $filnavn, "w");
    fwrite($fp, $innhold);
    fclose($fp);
    }
    * Sjekker cache-filer
    * @param string filnavn – navnet på cache-filen som skal sjekkes
    * @param int utløp – maksimal "alder" på filen i sekunder
    * @return blandet cache-innhold eller falsk
    */
    funksjon readCache($filnavn, $utløp) (
    if (fil_eksisterer("./cache/" . $filnavn)) (
    if ((tid() - $expiry) >filemtime("./cache/" . $filnavn))
    return FALSE;
    $cache = fil("./cache/" . $filnavn);
    return implode("", $cache);
    }
    return FALSE;
    }
    ?>

    De to første funksjonene vi definerte - writeCache og readCache - brukes til å lage henholdsvis cache-filer og sjekke deres eksistens. WriteCache-funksjonen tar som argumenter dataene som skal bufres og filnavnet som brukes til å lage cache-filen. ReadCache-funksjonen får navnet på cache-filen og tiden i sekunder etter at cache-filen skal anses som gammel. Hvis den finner cache-filen gyldig, vil skriptet returnere innholdet, ellers vil det returnere FALSE for å indikere at cache-filen ikke eksisterer eller er utdatert.

    I dette eksemplet brukte jeg en prosedyremessig tilnærming. Jeg anbefaler imidlertid ikke å gjøre dette i praksis, siden det vil ende opp i veldig rotete kode (se påfølgende løsninger for et bedre alternativ) og sannsynligvis vil føre til fillåseproblemer (f.eks. hva som skjer når noen får tilgang til hurtigbufferen mens den er på oppdatert?).
    La oss fortsette med dette eksemplet. Når utgangsbuffring har startet, begynner behandlingen. Skriptet kaller først readCache for å se om filen 3_header.cache eksisterer – den inneholder sidehodet, det vil si HTML-hodet og begynnelsen av brødteksten. Vi bruker datofunksjonen til å skrive ut tidspunktet siden faktisk ble generert, slik at du vil se de forskjellige cache-filene i aksjon når siden gjengis.

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

    Side bufret blokk for blokk

    Tidspunkt for opprettelse av topptekst:

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

    Hva skjer når cache-filen ikke blir funnet? Noe innhold sendes ut og tilordnes til en variabel ved å bruke ob_get_contents, hvoretter bufferen tømmes av ob_clean-funksjonen. Dette lar oss fange opp utdataene stykke for stykke og matche det til individuelle cache-filer ved å bruke writeCache. Sidetittelen er nå lagret som en fil som kan brukes uten at vi griper inn i gjenoppbyggingen av siden. La oss gå tilbake til begynnelsen et sekund. betinget operatør. Da vi kalte readCache, ga vi den en cache-levetid på 604800 sekunder (en uke), readCache bruker endringstiden til cache-filen for å avgjøre om cache-filen fortsatt er gyldig.

    For innholdet (kroppen) på siden vil vi fortsatt bruke den samme prosessen. Men denne gangen når vi kaller readCache vil vi bruke en cache-levetid på fem sekunder, cache-filen vil bli endret hver gang den er "eldre" enn 5 sekunder:

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

    Bunnteksten kan effektivt endres på samme måte som toppteksten.
    Sluttresultatet ser omtrent slik ut:
    - opprettingstid for header - 17:10:42;
    - kroppsopprettingstid - 18:07:40;
    - bunntekst opprettelsestid - 17:10:42.
    Topptekst og bunntekst oppdateres ukentlig, mens brødteksten endres når den er eldre enn 5 sekunder.

    nestede buffere

    Du kan legge en buffer i en annen praktisk talt på ubestemt tid ved å ringe ob_start gjentatte ganger. Dette kan være nyttig hvis du har mange operasjoner som bruker utdatabufferen, for eksempel noen som fanger opp PHP-feilmeldinger, andre som omhandler caching. Du må sørge for at ob_end_flush eller ob_end_clean kalles hver gang ob_start brukes.

    Hvordan kan jeg implementere et enkelt buffersystem på serversiden?
    Nå som vi forstår ideene bak output bufring, er det på tide å se på hvordan vi kan sette denne prosessen ut i livet på en måte som er enkel å vedlikeholde. For å gjøre dette, bruker vi litt hjelp fra PEAR::CacheLite.

    Som jeg sa, for å gjøre koden din enklere å vedlikeholde og ha en pålitelig hurtigbuffermekanisme, er det lurt å tildele ansvar for hurtigbufferlogikken til klasser du stoler på. Cache_Lite er et kraftig, men likevel brukervennlig hurtigbufferbibliotek som håndterer oppgaver som midlertidig låsing av cache-filer, opprettelse og validering av dem, administrering av utdatabufferen og direkte bufring av resultatet av en funksjon eller klassemetode. Hovedgrunnen til å velge dette biblioteket er den relativt enkle integrasjonen av Cache_Lite i allerede eksisterende applikasjon, som bare krever mindre endringer i koden.

    Cache_Lite består av tre hovedklasser. Den første er basisklassen Cache_Lite, som kun er ansvarlig for å lage og lese hurtigbufferfiler og ikke buffer utdata. Denne klassen kan brukes alene i tilfeller der det ikke er behov for å bruke utdatabuffring, for eksempel når du lagrer resultatet av å analysere en mal med et PHP-skript. Eksemplene vist her bruker ikke Cache_Lite-klassen direkte og demonstrerer bruken av de to andre klassene. Cache_Lite_Function brukes til å kalle en funksjon eller klassemetode og deretter cache resultatene. Dette kan for eksempel være nyttig for å bufre resultatet av en MySQL-spørring. Cache_Lite_Output-klassen bruker PHPs utdatakontrollfunksjoner for å fange opp data generert av et skript og lagre det i cache-filer. Dette lar deg utføre de samme oppgavene som den forrige løsningen.

    Cache_Lite-innstillinger

    I gjeldende versjon klasse (1.1) er følgende innstillinger tilgjengelige:
    - cacheDir - katalog der cache-filer vil bli plassert. Standardverdien er katalogen der skriptet kjøres;
    - caching - dette alternativet aktiverer eller deaktiverer Cache_Lite-funksjoner. For eksempel, hvis du har mange forespørsler til Cache_Lite, og under feilsøking vil du slå av caching, sett den til FALSE. Standardverdien er TRUE.
    levetid - parameteren inneholder standard cache-levetid (i sekunder);
    - fileNameProtection - bruk MD5-koding for å generere et cache-filnavn. Dette lar deg bruke alle tegn i navnene på cache-filer og grupper, også de som er forbudt av filsystemet;
    - fileLocking - muliggjør mekanismer for å blokkere en fil med en cache mens data skrives til den;
    - writeControl - sjekker at cache-filen ble skrevet riktig umiddelbart etter slutten av skrivingen;
    - readControl - før du leser en cache-fil, sjekker den for forvrengninger;
    - readControlType - denne parameteren bestemmer typen cache-fillesemekanisme. Tilgjengelige mekanismer: syklisk redundanssjekk, MD5-hash eller enkel sjekk lang Merk at denne mekanismen ikke er ment å beskytte cache-filer fra å bli kalt direkte eksterne brukere. Dette er bare en måte å finne ut om en fil er ødelagt eller ikke;
    - pearErrorMode - aktiverer PEAR-metoden for å returnere feil;
    - memoryCaching - hver gang du kaller cachen for å skrive til en fil, skrives den til Cache_Lite-arrayen. saveMemoryCachingState og
    getMemoryCachingState brukes til å få tilgang til hurtigbufferen som er lagret i minnet mellom forespørsler. Fordelen med denne metoden er at cache-innholdet kan lagres i en enkelt fil, noe som reduserer antall lese-/skrivesykluser på disken. Bufferen gjenopprettes direkte til en matrise som skriptet ditt har tilgang til;
    memoryCachingLimit - parameteren spesifiserer grensen for antall hurtigbufferfiler som kan lagres i en matrise i minnet.

    Tøm cache

    Cahce_Lite inneholder en vellykket mekanisme for å bestemme levetiden til cache-filer, som skaper godt grunnlag for sikkerheten til filene dine og deres rettidig oppdatering. Det er imidlertid tider når du trenger å oppdatere hurtigbufferfilen umiddelbart. For slike tilfeller er det remove() og clean() metoder. Remove()-metoden er laget for å fjerne en spesifikk hurtigbufferfil. det krever cache-ID og navnet på gruppen som filen tilhører. Følgende eksempel vil slette body cache-filen fra forrige eksempel:

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

    Clean()-metoden lar oss slette alle filer i katalogen vår hvis vi kaller den uten parametere. Hvis du sender gruppenavnet som en parameter, vil alle filene som er inkludert i denne gruppen. Hvis vi ønsket å fjerne overskriften og Nedre del, så må du utstede kommandoer som ligner på dette:

    $cache->clean("Statisk");

    Metodene remove() og clean() må åpenbart kalles som svar på hendelser i applikasjonen. For eksempel, hvis du har et forum, bør du sannsynligvis slette cache-filen hvis noen bruker legger inn en ny melding. Selv om denne løsningen ser fin ut, kan den innebære noen kodeendringer. hvis du har hovedmanus, som kobles til hver side i programmet som en besøkende kan se, kan du ganske enkelt se etter innkommende hendelser, for eksempel $_GET["newPost"]-variabelen, og fjerne de nødvendige hurtigbufferfilene. Dette vil tillate deg å lage en sentralisertisme. Du kan til og med inkludere denne koden i php.ini.

    caching funksjon anrop

    Fordi nettjenester er eksponert over nettverket, er det ofte en god idé å cache resultatet slik at det kan kjøres lokalt i stedet for å kjøre den samme sakte spørringen flere ganger. I det enkleste tilfellet kunne vi bruke PHP-økter, men siden denne løsningen fungerer basert på besøksregularitet, vil det fortsatt gå tregt å åpne en forespørsel for hver besøkende. I slike tilfeller kan Cache_Lite være veldig nyttig.

    PEAR Web-installasjonsprogram bruker Cache_Lite til å bufre XML-RPC-forespørsler sendt til PEAR-webserveren.
    Her er koden som mottar data fra den eksterne serveren:

    $countries = $stationInfo->listCountries();

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

    I begge tilfeller tilsvarer disse samtalene en forespørsel om data over nettverket. Ved å bruke Cache_Lite kunne vi hurtigbufre dataene som returneres av tjenesten og kunne gjenbruke dem. Dette vil unngå ekstra unødvendig nettverkstilkoblinger og vil øke utførelseshastigheten betydelig. Vær oppmerksom på at her ser vi kun på kode som er relevant for vårt emne. Først aktiverer vi Cache_Lite_Function:

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

    // Sett parametere for for Cache_Lite_Function
    // ADVARSEL: fileNameProtection = TRUE!
    $options = array(
    "cacheDir" =>"./cache/",
    "fileNameProtection" =>SANT,
    "writeControl" =>SANT,
    "readControl" =>SANT,
    "readControlType" => "strlen",
    "defaultGroup" =>"SÅPE"
    );
    // Lag et objekt av klassen Cache_Lite_Function
    $cache = new Cache_Lite_Function($options);

    Det er viktig at parameteren fileNameProtection er satt til TRUE. Denne verdien er standard, men jeg har spesifikt satt den manuelt for å understreke betydningen. Hvis du setter denne parameteren til FALSE, får du ugyldig navn fil, så det blir ingen caching.
    Deretter sender vi en forespørsel til SOAP-klienten vår:

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

    Hvis en forespørsel sendes for første gang, lagrer Cache_Lite_Function resultatene som en serialisert matrise i en hurtigbufferfil (du trenger ikke å bekymre deg for det), og denne filen vil bli brukt til fremtidige forespørsler til levetiden utløper. setLifeTime kan brukes til å bestemme hvor lenge en hurtigbufferfil skal leve før den oppdaterer informasjonen. Standardverdien er 1 time (3600 sekunder).

    PEAR::Cache

    Generelt gir Cach_Lite et enkelt, lett-å-bruke system for å løse eventuelle caching-relaterte problemer. Fordi det neste nivå- Dette er nettsteder med spesielt høy trafikk, du bør forholde deg til PEAR::Cache - "storebroren" til Cache_Lite. Det gir også forbedrede hurtigbufringsmuligheter, for eksempel bufring av delt minne som et alternativ til filbufring, eller Msession PHP-utvidelsen hjelper ved å lagre data i en balansert økt, noe som er spesielt nyttig i balanserte webservere. Cache_Lite tilbyr imidlertid mer enn nok funksjoner og oppfyller behovene til de fleste nettsteder.

    hvordan administrere caching på klientsiden ved å bruke PHP?

    Nå som vi har sett på alternativer for å overstyre caching på klientsiden, er det på tide å se på en mekanisme som lar oss kontrollere cache på klientsiden ved hjelp av PHP. Denne tilnærmingen vil bare fungere hvis du bruker PHP sammen med Apache server siden vi skal bruke getallheaders-funksjonen for å få overskriftene sendt av nettleseren. Denne funksjonen fungerer kun i Apache. Hvis du bruker PHP 4.3.0 med Apache, er det mulig å jobbe med HTTP-hoder ved å bruke funksjonene apache_request_headers og apache_response_headers. Getallheaders-funksjonen har blitt et alias for den nye apache_request_headers-funksjonen.

    Mekanismen for å jobbe med nettleserbufferen er igjen HTTP. Flere overskrifter er involvert i å instruere nettlesere og proxy-servere om å bufre en side uavhengig. Situasjonen kompliseres av det faktum at noen av dem kun er tilgjengelige med HTTP 1.1.

    sjekke HTTP-hoder i nettleseren din

    Et enkelt, men veldig praktisk verktøy for å sjekke forespørsels- og svarhoder er LiveHttpHeaders – et tillegg for Mozilla nettleser. Det er viktig å vite nøyaktig hvilke overskrifter skriptet ditt sender, spesielt når du har å gjøre med HTTP-bufringshoder.
    For enkelhets skyld vil vi kun vurdere HTTP 1.0-bufringshodene, nemlig Expires, Last-Modified og If-Modified-Since, samt HTTP 304 (Not Modified) statuskoden.

    Andre overskrifter tilgjengelig med HTTP 1.1, for eksempel Cache-Control og ETag, er ment å gi en utvidet mekanisme som kan brukes i forbindelse med nettøktstatus, med andre ord, versjonen av samme side beregnet på en uautorisert besøkende kan variere betydelig fra vist til den autoriserte brukeren. HTTP 1.1-overskrifter ble opprinnelig lagt til for å la slike sider bufres.

    side levetid utløp

    Den enkleste overskriften å bruke er Expire-overskriften, som angir datoen når siden skal utløpe. Inntil dette har nettleseren lov til å bruke en bufret versjon av siden.
    Eksempel:


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

    Eksemplet ovenfor viser gjeldende GMT-tid og viser en lenke som lar deg gå tilbake til siden. Ved å bruke nettleserens Oppdater-knapp kan du fortelle nettleseren at du vil oppdatere bufferen.

    datoer og klokkeslett i HTTP

    Datoer i HTTP beregnes alltid i forhold til Greenwich Mean Time (GMT). PHP gmdate-funksjonen er nøyaktig den samme funksjonen som dato, bortsett fra at den automatisk kompenserer for GMT basert på systemklokken og serverens regioninnstillinger. Når nettleseren støter på Expires-overskriften, bufrer den siden. Alle påfølgende forespørsler for siden gjort før den angitte TTL-tiden bruker den bufrede versjonen av siden, uten å sende noen forespørsler til webserveren.
    Expires-overskriften er i prinsippet enkel å implementere, men i de fleste tilfeller, med mindre du er en svært organisert person, kan du ikke vite nøyaktig når en gitt side på nettstedet ditt vil bli oppdatert. Fordi det nettleseren kommer inn for å kontakte serveren først etter at siden har blitt foreldet, er det ingen måte å fortelle nettleseren at siden i bufferen er foreldet.

    sideskiftetid

    Det er mer praktisk å bruke overskriftene Last-Modified og If-Modified-Since som er tilgjengelige i HTTP 1.0. Når du bruker denne metoden, må du sende en Last-Modified header som svar på hver forespørsel til PHP-skriptet ditt. Neste gang nettleseren ber om siden, vil den sende en If-Modified-Since-overskrift som inneholder tiden skriptet ditt kan bruke til å avgjøre om siden har blitt oppdatert siden siste forespørsel. Hvis dette ikke er tilfelle, sender skriptet en HTTP 304-statuskode for å indikere at siden ikke er endret, uten å skrive ut sidens innhold. Hvis du kombinerer den siste endrede tidstilnærmingen med en tidsverdi som allerede er tilgjengelig i applikasjonen din (for eksempel tidspunktet for den siste nyhetsartikkelen), kan du dra nytte av nettleserens hurtigbuffer og laste ned datakoblingen, og lagre informasjon trafikk fra nettstedet ditt der det er mulig. forbedre ytelsen.

    Vær forsiktig når du tester caching utført i denne stilen: Hvis du gjør det feil, kan du føre til at de besøkende alltid har utdaterte kopier av nettstedet ditt.

    Harry Fuecks, oversettelse av Sergey Mullin (SiMM) og Kuzma Feskov.

    Når du utvikler PHP-prosjekter fra bunnen av og uten å bruke biblioteker, kan hastighet bli et alvorlig problem. Bufring kan påvirke hastigheten på nettsider betydelig. I denne opplæringen vil vi vise deg en enkel og effektiv metode dynamisk caching av sider som trenger akselerasjon.

    Steg en. Lag en fil top-cache.php

    Vi må lage to filer. Først: lag en fil kalt top-cache.php og kopier følgende kode inn i den:

    Hva skjer i denne koden? De første 5 linjene lager cache-filnavnet iht gjeldende PHP fil. For eksempel, hvis vi bruker en fil som heter list.php, vil cache-filen se ut som cached-list.html.

    Linje 6 lager $cachetime-variabelen, som spesifiserer cachens levetid.

    Linje 9 til 13 definerer et betinget uttrykk som sjekker for tilstedeværelsen av en fil med navnet definert i $cachefile-variabelen. Hvis filen eksisterer, settes en kommentar inn sammen med filen som er definert i $cachefile-variabelen. Exit-setningen avbryter deretter skriptet og filen sendes til klientnettleseren. Det vil si at hvis en statisk fil blir funnet, vil ikke PHP-koden bli utført av serveren.

    Linje 14 oppretter en buffer hvis filen spesifisert av $cachefile ikke blir funnet.

    Trinn to. Lag en fil bottom-cache.php

    La oss nå lage den andre PHP-fil med navnet bottom-cache.php og kopier følgende kode inn i den:

    Hvis en fil med navnet definert i $cachefile-variabelen ikke eksisterer på serveren, kjøres denne koden og filen opprettes. Neste gang siden åpnes, vil den statiske $cachefile betjene klientnettleseren i stedet for å kjøre all PHP-skriptkoden.

    Trinn tre. Inkludert cache-filer i sidekoden

    Nå har vi to nødvendig fil. Vi inkluderer dem bare PHP-side, som må bufres. Top-cache.php-filen bør inkluderes øverst på siden, og bottom-cache.php-filen på slutten:

    Nå, hvis du sjekker cachingen på trege sider, så kan du se hvor mye raskere de laster inn.

    Moderne nettlesere bruker ganske ofte en lokal cache i arbeidet sitt. Hva betyr dette? Dette betyr at nettleseren, etter å ha mottatt et HTML-dokument, bilde eller annen ressurs fra serveren, plasserer den i sin lokale cache (med andre ord skriver den mottatte ressursen til HDD brukermaskin) og under påfølgende forespørsler til en slik ressurs får ikke tilgang til serveren, men mottar ressursen fra den lokale hurtigbufferen.

    Denne nettleseralgoritmen øker lastehastigheten til HTML-dokumenter dramatisk. Siden hvis ressursen allerede er lastet ned, og som et resultat er lokalisert i den lokale hurtigbufferen, bestemmes tilgangstiden ikke av båndbredden til kommunikasjonskanalen (for eksempel en modemtilkobling), men av hastigheten på harddisken .

    Men sammen med fordelene denne metoden gir også opphav til en rekke problemer. Spesielt de fleste nybegynnere webprogrammerere, når de utvikler dynamiske nettsteder, står overfor det samme problemet. Essensen av dette problemet er at i stedet for gjentatte ganger å kontakte serveren for en side som kjører et skript på serveren som endrer noe informasjon, får nettleseren tilgang til den lokale cachen. Og som et resultat av for eksempel tre forespørsler, er det ikke tre modifikasjoner av informasjonen som ligger på serveren, men bare én.

    For å tvinge nettleseren til å be om en side fra serveren hver gang, må du forby nettleseren å gå inn denne ressursenå cache. Nedenfor er de vanligste metodene for å deaktivere eller omgå caching.

    Genererer en ny URL

    La oss anta at den forespurte ressursen har følgende url: test.html?id=7. Som du kan se fra url-en, sendes en parameter til den. La oss legge til for eksempel når JavaScript-hjelp, det er en parameter til i nettadressen, og vi gjør den til verdien tilfeldig tall. Som et resultat vil nettadressen se slik ut: test.html?id=7&rnd=0.6700820127538827. Den tilfeldige parameteren vil bli generert på nytt hver gang. Nedenfor er en liste som viser denne tilnærmingen:

    Genererer en ny URL document.write(""); testlink

    Hver gang blir resultatet av en slik forespørsel bufret, men siden caching utføres over hele url-en, vil en ny url bli hentet hver gang og nettleseren vil bli tvunget til å be om en ressurs fra serveren, siden url-ene til to forespørsler vil ikke samsvare nøyaktig.
    Overskriftsfelt

    Du kan også administrere caching fra serversiden. For å oppnå dette, er ressursen som sendes til nettleseren ledsaget av overskriftsfelt. En detaljert beskrivelse av overskriftsfeltene finnes i Rfc 2068-standarden, som beskriver HTTP 1.1-protokollen.

    Utløper overskriftsfelt

    Verdien av denne overskriften er datoen etter hvilken innholdet i ressursen blir foreldet. Hvis en bruker får tilgang til en ressurs etter denne datoen, må nettleseren be om ressursen fra serveren i stedet for fra den lokale hurtigbufferen.

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

    Sist endret overskriftsfelt

    Verdien av denne overskriften er datoen ressursen sist ble oppdatert. Flertall moderne nettlesere bruk følgende algoritme hvis ressursen allerede er i den lokale hurtigbufferen:

    * ber serveren om datoen for siste ressursoppdatering
    * sammenligner mottatt dato og ressursdato i den lokale cachen
    * hvis ressursen på serveren er nyere enn ressursen i hurtigbufferen, blir ressursen forespurt fra serveren

    Hvis en ressurs som ligger på serveren inneholder i dette feltet dagens dato, så vil nettleseren be om ressursen fra serveren hver gang, og ikke fra den lokale hurtigbufferen. Følgende liste viser bruken av feltet Last-Modified header:

    header("Sist endret: ". gmdate("D, d M Y H:i:s") . " GMT");

    Enger Cache-Control-overskrift og Pragma

    Og til slutt, overskriftsfeltene, som er direkte ansvarlige for ressursbufring. Feltet ble definert i RFC 1945-standarden som beskriver HTTP 1.0-protokollen. Dette feltet anses som foreldet, men i noen tilfeller er det nødvendig å bruke det. Spesielt behandler noen proxy-servere ikke forespørsler om ressurser i stadig endring hvis dette overskriftsfeltet ikke sendes sammen med ressursen.

    Det andre feltet er definert i RFC 2068-standarden, som beskriver HTTP 1.1-protokollen. Dette overskriftsfeltet lar deg deaktivere caching og be om en ressurs fra serveren hver gang. Følgende liste viser bruken av Cache-Control- og Pragma-overskriftsfeltene for å deaktivere caching:

    header("Cache-Control: no-cache, must-revalidate"); header("Pragma: no-cache");

    Bra dårlig