2015-10-15 20 views
5

Pracuję nad projektem testowym z wbudowanym serwerem PHP i testuję kilka pomysłów.wbudowany serwer php wbudowany buforowanie numer

Chcę zaimplementować własny mechanizm buforowania dla powszechnie używanych zasobów (png, jpg, json, txt, etc ...), aby zmniejszyć obciążenie wbudowanego serwera w php.

zacznę wbudowanego serwera tak:

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

Więc korzeń Dokument wbudowany serwer jest ustawiony na public i działa pod numerem router.php (co też myślę o implementacji prostej funkcji przepisywania).

Oto zawartość mojego pliku 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'; 

?> 

testowałem (PNG) buforowanie reource odwiedzając następujący adres URL: http://localhost/apple-icon-120x120.png

tak, to jest pierwszy ładunek zasobu, więc służyć zwraca zasób z HTTP 200 odpowiedzi zgodnie z oczekiwaniami, trwa ok 307ms: enter image description here

teraz, gdybym pres S F5 aby odświeżyć stronę, serwer zwraca HTTP 304 (niemodyfikowane), jak oczekiwano, a żądanie wzięło ok 5ms (świetne !!): enter image description here

Gdybym naciśnij F5 po raz trzeci, serwer nadal zwraca HTTP 304 (niemodyfikowane) zgodnie z oczekiwaniami, jednak tym razem prośba zajęło ok 306ms znowu (jakby zasób nie buforowane): enter image description here

Gdybym naciskaj F5, czas przetwarzania żądania jest alternativing losowo pomiędzy 5m i ok. 307ms.

Jakieś pomysły, dlaczego tak się zachowuje? Gdy zasób jest buforowany, czy nie powinien on stale zwracać 304 i przetwarzać żądanie ok. 5ms? Dlaczego zachowanie jest sporadyczne?

Widzę, że zwracany rozmiar treści to 225 bytes (gdy wiadomo, że dane są sprawdzane), po prostu nie mogę określić, gdzie jest wąskie gardło z czasem przetwarzania żądania. Mój komputer hosta ma zainstalowane okna z procesorem Intel i7, dyskami SSD 6GB RAM &.

Odpowiedz

0

Twój router działa poprawnie. Przetestowałem go lokalnie i działa on zgodnie z oczekiwaniami: po raz pierwszy HTTP 200 z pobieraniem, a następnie HTTP 304 z tylko nagłówkami.

Patrząc na swoją linię czasową zajmuje 307 ms, aby obsłużyć odpowiedź 11,9 KB, która jest oczywiście zbyt powolna.

Otrzymujesz HTTP 304, więc Twój skrypt musiał zostać zakończony bez wysyłania pliku. Jednak, aby wysłać kod stanu 304 w pierwszej instancji PHP nadal musi znaleźć numer mtime i obliczyć skrót mieszania md5 pliku. Uzyskanie dostępu do pliku to prawdopodobnie szyjka butelki.

Czas odpowiedzi na przemian między 5ms a 300ms może być spowodowany przez buforowanie dysku. Może masz dysk twardy lub napęd hybrydowy?

Dlaczego nie echo microtime() na początku, przed mtime i po obliczeniu skrótu?

Powiązane problemy