2015-10-15 10 views
5

Sto lavorando a un progetto di test che coinvolge il web server integrato di PHP e sto testando alcune idee.problema di caching del webserver integrato in php

Desidero implementare il mio meccanismo di caching per le risorse di uso comune (png, jpg, json, txt, ecc.) Per ridurre il carico sul server integrato in php.

comincio il costruito nel server in questo modo:

php -S 127.0.0.1:80 router.php pubblico -t

Così, la radice del documento del server incorporato è impostato su public ed esegue lo router.php (poiché sto pensando di implementare anche una semplice funzione di riscrittura).

Ecco il contenuto del mio file router.php:

<?php 

// Register request uri 
$requestUri = isset($_SERVER['REQUEST_URI']) 
    ? $_SERVER['REQUEST_URI'] 
    : '/'; 

// Handle app resources with caching 
if (preg_match('/\.(?:png|jpg|jpeg|gif|xml|json|css|eot|svg|otf|ttf|woff|woff2|scss|less|txt|ico)$/', $requestUri)) 
{ 
    // Generate file name 
    $fileName = __DIR__ .'/public'. $requestUri; 

    // Parse file data 
    $lastModified = filemtime($fileName); 
    $etagFile = md5_file($fileName); 
    $ifModifiedSince = (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false); 
    $etagHeader = (isset($_SERVER['HTTP_IF_NONE_MATCH']) ? trim($_SERVER['HTTP_IF_NONE_MATCH']) : false); 

    // Set caching header 
    header('Last-Modified: '. gmdate('D, d M Y H:i:s', $lastModified) .' GMT'); 
    header('Etag: '. $etagFile); 
    header('Cache-Control: public'); 

    // Check if the requested resource has changed 
    if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $lastModified || $etagHeader == $etagFile) 
    { 
     // File has not changed 
     header('HTTP/1.1 304 Not Modified'); 
     exit; 
    } 
    else 
    { 
     // Parse requested resource's mime type 
     $finfo = new finfo(FILEINFO_MIME); 
     $mime_type = $finfo->buffer(
      file_get_contents($fileName, false, null, -1, 64), 
      FILEINFO_MIME_TYPE 
     ); 

     // Serve requested resource 
     header('Content-Type: '. $mime_type); 
     header('Content-Length: '. filesize($fileName)); 
     @readfile($fileName); 
     $finfo = null; 
     exit; 
    } 
} 

// Parse requested page & action 
list ($page, $action) = 
    array_pad(array_values(array_filter(explode('/', $requestUri, 3), 'strlen')), 2, 'index'); 
if ($page == 'index') $page = 'server'; 

// Test - to do rest of routing 
var_dump('page = '. $page); 
var_dump('action = '. $action); 
// include 'app/'. $page .'/'. $action .'.php'; 

?> 

Ho testato il reource (immagine png) caching visitando il seguente URL: http://localhost/apple-icon-120x120.png

Quindi, questo è il primo carico della risorsa, in modo da servire ritorna la risorsa con HTTP 200 risposta come previsto, prende circa 307ms: enter image description here

Ora, se io pres s il F5 a ricaricare la pagina, il server restituisce HTTP 304 (non modificati) come previsto e la richiesta sono voluti circa 5ms (grande !!): enter image description here

Se premo F5 per la terza volta, il server restituisce ancora HTTP 304 (non modificati) come previsto, ma questa volta la richiesta sono voluti circa 306ms di nuovo (come se la risorsa non è stata memorizzata nella cache): enter image description here

Se continuo premendo F5, il tempo per elaborare la richiesta è alternativing casualmente tra 5m e circa 307ms.

Qualche idea sul perché si comporta in questo modo? Una volta che la risorsa è stata memorizzata nella cache, non dovrebbe restituire costantemente 304 ed elaborare la richiesta circa 5ms? Perché il comportamento è sporadico?

Vedo che la dimensione del contenuto restituito è 225 bytes (quando sa che i dati sono cahced), non riesco proprio a capire dove si trova il collo di bottiglia con il tempo di elaborazione della richiesta. Il mio computer host esegue windows con CPU Intel i7, 6 GB di RAM & unità SSD.

risposta

0

Il file del router funziona correttamente. L'ho testato localmente e si comporta come previsto: la prima volta l'HTTP 200 con download, quindi un HTTP 304 con solo intestazioni.

Guardando la timeline ci vogliono 307 ms per servire una risposta di 11,9 KB che è ovviamente troppo lenta.

Si riceve HTTP 304 in modo che lo script debba essere uscito senza inviare il file. Tuttavia, per inviare il codice di stato 304 in prima istanza, PHP deve ancora trovare lo mtime e calcolare l'hash md5 del file. L'accesso al file è probabilmente il collo a bottiglia.

Il tempo di risposta alternato tra 5ms e 300ms potrebbe essere causato dalla memorizzazione nella cache del disco. Forse hai un disco rigido o un'unità ibrida?

Perché non echo il microtime() all'inizio, prima del mtime e dopo il calcolo dell'hash?