许多 HTTP 304 响应导致较少的 GET 请求

Many HTTP 304 responses results in fewer GET requests

我有一个 Django 开发服务器托管一个网页,该网页实时(ish)显示从我监视的众多服务器收集的信息。这个网页仍在开发中,所以我目前正在使用 Django 提供的内置网络主机,在 Ubuntu 主机上启动:

python3 manage.py runserver IP:Port

在同一个 ubuntu 主机上有一个 python 脚本不断地连接到受监控的服务器并将响应格式化为 .html 文件,客户端在 <div> 每分钟。客户端访问页面的大致功能如下:

<div id="status" style="width:100%; height: 1000"></div>
<script>
    $('#status').load("{% static 'alerts/status.html' %}");
    setInterval(function() {
        $('#status').load("{% static 'alerts/status.html' %}");
    }, 60000);
</script>

...因此页面在页面加载时加载分区内的 status.html 文件,然后每分钟重新加载一次。这一直很好用,但是,我注意到查看 Django 日志,如果 status.html 在 10 个状态 304(未修改)响应后没有改变,则请求之间等待的时间开始减少。也就是说,不是等待1分钟,而是等待2分钟,然后等待5分钟,以此类推(大致,我忘记了实际滚降率)。

现在我面临的问题是我的服务器在周末宕机了(无关),但是我打开网页的显示屏仍然处于活动状态,所以它滚动得太多了,看起来已经完全崩溃,拒绝下载最新的 status.html,即使我强制 Chrome 重新加载所有内容并且不使用缓存(ctrl + Rshift + F5)。

我试着研究了这个滚降,但找不到任何关于它的信息。我假设这是内置于 Google Chrome(我正在使用的浏览器)中的东西,当页面没有变化但我的状态页面最多只有几千字节并且 304 响应已经如果有一种方法可以完全禁用这种理想的生产滚降,那么可以节省很少的带宽。

无论如何,如果我能找到任何关于我为什么会看到这种行为/它来自哪里的信息,我将不胜感激,因为我似乎找不到任何关于它的文档。我找到的最接近的东西来自 Google 关于缓存的开发者文档 here。它提到了定义最大年龄和无缓存行为的能力,因此我可以强制客户端每 status.html 分钟重新下载一次,但这看起来很混乱。虽然这在我的特定情况下可行,因为 status.html 最多为几千字节,但仅禁用此滚降行为就可以解决问题 会减少不必要的带宽。

试试这个:

// Page reload every 60 seconds
setInterval(function(){
    location.reload();
}, 60000);

这里的问题是 status.html 的响应没有明确的缓存过期 header。如果没有这样的 header,浏览器可以自由使用自己的算法(例如您看到的 roll-off)来选择过期时间。来自 RFC 7234:

Since origin servers do not always provide explicit expiration times, a cache MAY assign a heuristic expiration time when an explicit time is not specified.... This specification does not provide specific algorithms.

所以解决方案很简单:指定一个明确的缓存过期时间。

不幸的是,使用 Django 的静态文件应用程序实施此解决方案并非易事。此应用程序更好的默认设置是根本不缓存结果,但该解决方案 was deferred pending a merger with whitenoise.

解决方案包括使用不同的服务器(如 nginx);使用不同的应用程序(如 whitenoise);或直接使用静态视图而不是静态文件应用程序(请参阅 this question 了解一些方法)。