php内置的webserver缓存问题

Lat*_*san 5 php caching php-5.6 php-builtin-server

我正在开发一个涉及PHP内置Web服务器的测试项目,我正在测试一些想法.

我想为常用资源(png,jpg,json,txt等)实现我自己的缓存机制,以减少php中内置服务器的负载.

我像这样启动内置服务器:

php -S 127.0.0.1:80 -t public 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';

?>
Run Code Online (Sandbox Code Playgroud)

我通过访问以下网址来测试资源(png图像)缓存:http://localhost/apple-icon-120x120.png

所以,这是资源的第一次加载,所以serve HTTP 200按预期返回带有响应的资源,取大约307ms: 在此输入图像描述

现在,如果我按下F5重新加载页面,服务器HTTP 304将按预期返回(未修改)并且请求大约5ms(很棒!!): 在此输入图像描述

如果我F5第三次按,服务器仍然HTTP 304按预期返回(未修改),但是这次请求306ms再次大概(就好像资源没有被缓存): 在此输入图像描述

如果我一直按下F5,处理请求的时间是在5m大约和大约之间随机交替307ms.

任何想法为什么它的行为像这样?资源缓存后,是否应该不断返回304并处理请求5ms?为什么这种行为是零星的?

我确实看到返回的内容大小是225 bytes(当它知道数据被加入时),我只是无法弄清楚瓶颈与请求处理时间的关系.我的主机运行的是带有Intel i7 CPU,6GB RAM和SSD驱动器的Windows.

Tom*_*Tom 0

您的路由器文件工作正常。我已经在本地测试了它,它的行为符合预期:第一次是带下载的 HTTP 200,然后是仅带有标头的 HTTP 304。

查看您的时间线,需要 307 毫秒才能提供 11.9 KB 的响应,这显然太慢了。

您确实收到了 HTTP 304,因此您的脚本一定已退出而未发送文件。然而,要在第一个实例中发送 304 状态代码,PHP 仍然必须找到mtime并计算md5文件的哈希值。访问文件可能是瓶颈。

响应时间在 5 毫秒和 300 毫秒之间交替变化可能是由磁盘缓存引起的。也许您有硬盘驱动器或混合驱动器?

为什么不在哈希计算microtime()开始时、之前和之后回显?mtime