使用PHP输出缓冲和ETag实现浏览器缓存动态内容

3

我一直在研究优化网站应用程序的策略,特别是与浏览器缓存和动态数据有关。因为同一动态内容可能会在一个会话中被多次加载,所以我想出了以下方法,使用PHP的输出缓冲区和内容的哈希作为ETag。

我意识到这种方法真正节省的只是将数据传输回用户,因为PHP脚本仍然需要完全运行,但我很好奇是否有人做过类似的事情,以及是否有任何想法或问题我应该注意,或者其他更好的方法。

这是我在每个页面顶部包含的代码:

<?php
function hash_buffer($content) {
    $buffer_hash = crc32($content);
    if ($_SERVER['HTTP_IF_NONE_MATCH'] == $buffer_hash) {
        header('HTTP/1.1 304 Not Modified');
        header("ETag: $buffer_hash");
        return '';
    }
    header('Cache-Control: private, no-cache');
    header("ETag: $buffer_hash");
    return $content;
}

ob_start('hash_buffer');
?>

"唯一的事情" - 数据传输是一个相当重要的事情,因此值得进行优化。 - MrWhite
使用ob_start("ob_gzhandler")压缩输出也是一个不错的主意,尽管它不是问题的一部分。http://www.research.ibm.com/people/f/fdouglis/papers/sigcomm97.pdf - MTJ
1个回答

0

使用一些快速的东西来创建哈希,crc32很快但可能比md5产生更多冲突(尽管文件名已经解决了一些问题)。

<?php
function hash_buffer($content) {
    $buffer_hash = crc32($content);

    // You could add expire time so the check is not made every time.
    // Or force it to happen always
    header('Expires:');//.date('r',strtotime('+1 hour')));

    // Add vary header so client knows to usee ETag
    // Without overwriting existing vary headers
    header('Vary: If-None-Match',false);

    if ($_SERVER['HTTP_IF_NONE_MATCH'] == $buffer_hash) {
        header('HTTP/1.1 304 Not Modified');
        header("ETag: $buffer_hash");
        return '';
    }
    header('Cache-Control: private, no-cache');
    header("ETag: $buffer_hash");
    return $content;
}

ob_start('hash_buffer');
?>

尝试更快地将内容缓存到缓冲区

为了更快地生成缓冲区中的内容,您可以使用文件缓存。例如,将生成的导航/博客列表/新闻列表写入文件中,并在文件修改时间(缓存生命周期内的10分钟-1小时等)内从文件中读取,否则将其写入文件并像往常一样处理。

您需要编写锁定以防止冲突等,请参见ZendFramework上的实现https://github.com/zendframework/zf2/blob/master/library/Zend/Cache/Storage/Adapter/Filesystem.php#L1489

记住

用户权限可能会影响文件缓存,就像任何缓存一样,您不希望其他人的购物车出现在您的结账页面上等。通常,将经过身份验证的用户排除在文件缓存之外是安全的做法。

在文件缓存时,必须保护缓存文件免受Web和其他公共读写访问。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接