2015-10-15 25 views
5

PHP'nin yerleşik web sunucusunu içeren bir test projesi üzerinde çalışıyorum ve bazı fikirleri test ediyorum.php yerleşik web sunucusu önbellekleme sorunu

Yaygın olarak kullanılan kaynaklar (png, jpg, json, txt, vb.) Için kendi önbelleğe alma mekanizmamı uygulamak ve php içindeki yerleşik sunucudaki yükü azaltmak istiyorum.

böyle sunucuda inşa başlatın:

php Yani 127.0.0.1:80 -t kamu router.php

, belge kökünü -S yerleşik sunucuya public olarak ayarlanmış ve router.php (aynı zamanda basit bir yeniden yazma özelliğini de uygulamayı düşündüğümden) çalışır. , http://localhost/apple-icon-120x120.png

Yani, bu kaynağın ilk yüküdür:

<?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'; 

?> 

aşağıdaki url ziyaret ederek reource (png resim) önbelleğe test:

İşte benim router.php dosyasının içeriği var böylece beklendiği gibi HTTP 200 yanıtı ile döndürür kaynağı sunar, yaklaşık 307ms alır: enter image description here

Şimdi, pres eğer sayfayı yeniden F5 s beklendiği gibi sunucu (değiştirilmemiş) HTTP 304 döner ve isteği (!! harika) yaklaşık 5ms aldı: enter image description here

üçüncü kez F5 basarsanız, sunucu hala HTTP 304 döndürür beklendiği gibi, (kaynak önbelleğe sanki) isteği tekrar yaklaşık 306ms aldı ancak bu sefer (değiştirilmemiş): Ben F5 basmaya devam ederse, isteği işlemek için zaman 5m arasında rastgele alternativing edilir enter image description here

yaklaşık 307ms.

Neden böyle davrandığına dair bir fikrin var mı? Kaynak önbelleğe alındığında, sürekli olarak 304 döndürüp, yaklaşık olarak 5ms isteğini işleme almamalı mı? Davranış neden sporadik?

İade edilen içerik boyutunun 225 bytes olduğunu (verilerin uygun olduğunu bildiğinde), istek darlığının, istek işleme süresiyle nerede olduğunu anlayamıyorum. Ana makinem Intel i7 CPU, 6GB RAM & SSD sürücüler ile windows çalışıyor.

cevap

0

Yönlendirici dosyanız çalışıyor. Yerel olarak test ettim ve beklendiği gibi davranıyor: ilk kez karşıdan yüklenen HTTP 200, daha sonra sadece başlıklarla bir HTTP 304.

Zaman çizelgenize baktığımızda, 11,9 KB'lik bir yanıt vermek için 307 msn geçmesi gerekir;

HTTP 304'ü alıyorsunuz, böylece betiğiniz dosyayı göndermeden çıkmış olmalı. Ancak, ilk durumda 304 durum kodunu göndermek için PHP hala mtime'u bulmalı ve dosyanın md5 karmasını hesaplamalıdır. Dosyaya erişim muhtemelen şişe boynudur.

5ms ila 300ms arasında değişen yanıt süresi, disk önbelleğe alma işleminden kaynaklanabilir. Belki sabit sürücünüz veya hibrit sürücünüz var mı?

Neden mtime'dan önce ve karma hesaptan sonra microtime()'u yankılanmıyorsunuz?