2015-10-15 4 views
5

Я работаю над тестовым проектом с использованием встроенного веб-сервера PHP, и я тестирую некоторые идеи.php встроенная проблема кэширования веб-сервера

Я хочу реализовать свой собственный механизм кеширования для широко используемых ресурсов (png, jpg, json, txt и т. Д.), Чтобы уменьшить нагрузку на встроенный сервер в php.

Я начинаю встроенный сервер, как это:

PHP -S 127.0.0.1:80 -t общественного router.php

Итак, корень документа из встроенного сервера установлен в public, и он запускает router.php (так как я думаю о реализации простой функции перезаписи).

Вот содержимое моего 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'; 

?> 

Я протестировал reource (PNG изображения) кэширования по следующему адресу: http://localhost/apple-icon-120x120.png

Итак, это первая нагрузка ресурса, так служить возвращает ресурс с HTTP 200 ответ, как ожидается, займет около 307ms: enter image description here

Теперь, если прес I вляется F5 перезагрузить страницу, сервер возвращает HTTP 304 (не изменяется), как и ожидалось, и запрос занял около 5ms (здорово !!): enter image description here

Если я нажимаю F5 в третий раз, сервер по-прежнему возвращает HTTP 304 (не изменяется), как и ожидалось, однако на этот раз запрос занял около 306ms снова (как если ресурс не кэшируются): enter image description here

Если я продолжать нажимать F5, время обработки запроса является alternativing случайным между 5m и приблизительно 307ms.

Любые идеи, почему это так? Как только ресурс будет кэширован, он должен постоянно возвращать 304 и обрабатывать запрос приблизительно 5ms? Почему поведение спорадическое?

Я вижу, что размер возвращаемого содержимого равен 225 bytes (когда он знает, что данные привязаны), я просто не могу понять, где узкое место с временем обработки запроса. Мой хост-компьютер работает с окнами с процессором Intel i7, 6 ГБ оперативной памяти & SSD-накопителями.

ответ

0

Ваш файл маршрутизатора работает нормально. Я тестировал его локально, и он ведет себя как ожидалось: первый раз HTTP 200 с загрузкой, а затем HTTP 304 с только заголовками.

Глядя на свою временную шкалу, для ответа от 11,9 КБ требуется 307 мс, что явно слишком медленно.

Вы получаете HTTP 304, поэтому ваш скрипт должен быть выведен без отправки файла. Однако, чтобы отправить код статуса 304 в первом экземпляре PHP, необходимо найти mtime и вычислить хэш-файл md5. Доступ к файлу - это, вероятно, бутылочная шее.

Время отклика в диапазоне от 5 мс до 300 мс может быть вызвано кешированием диска. Может быть, у вас есть жесткий диск или гибридный диск?

Почему бы не повторить microtime() в начале, перед mtime и после расчета хэша?