前段时间问怎么办Incremental updates using browser cache .
在这里,我对问题进行了简短的总结 - 有关更多背景信息,尤其是我想要这样做的原因,请参阅旧问题。
我希望您审查并改进我的解决方案想法(只是一个想法,所以不要将我发送到 code review :D)。
问题
客户端(单页应用程序)从服务器获取相当大的列表。
这工作正常,实际上节省了服务器资源
这些列表中的一些是特定于用户的,另一些是一组用户共有的,另一些是全局的。
所有这些列表都可能随时更改,我们永远不想提供过时的数据(
Cache-Control
和 Expires
HTTP header 在这里没有直接用处)。我们正在使用
304 NOT MODIFIED
,这在没有任何变化的情况下会有所帮助。当有任何变化时,变化通常很小,但是 HTTP 根本不支持这种情况,因此我们必须发送整个列表,包括未更改的部分。
我们可以改为发送增量,但是没有明显的方法可以通过浏览器有效地缓存它(缓存在
localStorage
或类似的地方远不如我在链接问题中解释的那么好)。我们列表的一个重要属性是每个项目都有唯一的
id
和最后修改 timestamp
.timestamp
允许我们通过查找最近更改的项目轻松计算增量。id
允许我们简单地通过替换相应的项目来应用增量(列表在内部是一个 Map<Id, Item>
)。这对删除不起作用,但让我们暂时忽略它们。
想法
我建议使用不同大小的多个列表(任何数量都可以),更大的列表可以长时间缓存。
让我们假设,一天是一个合适的时间单位,让我们使用以下三个列表:
WEEK
这是包含所有项目的基本列表,因为它们在本周的某个任意时间存在。 DAY
包含本周更改的所有项目的列表,除了今天,因为它们在当天的某个任意时间存在。今天更改的项目可能包括也可能不包括在内。
CURRENT
一个包含所有今天更改的项目的列表,因为它们现在存在。 客户端获取所有三个列表。它以
WEEK
开头, 适用 DAY
(即插入新项目并替换旧项目)并最终应用 CURRENT
.一个例子
假设列表中有 1000 个项目,每天更改 10 个项目。
WEEK
列表包含所有 1000 个项目,但它可以缓存到周末。它的确切内容没有指定,不同的客户端可能有不同的版本(只要上述项目中的条件成立)。
这允许服务器将数据缓存一整周,但它也允许它删除它们,因为服务当前状态也很好。
DAY
列表最多包含 70 个项目,可以缓存到一天结束。CURRENT
列表最多包含 10 个项目,并且只能缓存直到发生任何变化。沟通
客户端应该对使用的时间尺度一无所知,但它需要知道要请求的列表数量。一个“经典”的请求,如
GET /api/order/123 // get the whole list with up to date content
将被三个请求取代
GET /api/0,order/123 // get the WEEK list
GET /api/1,order/123 // get the DAY list
GET /api/2,order/123 // get the CURRENT list
问题
通常更改确实如所描述的那样,但有时所有项目都会同时更改。
发生这种情况时,所有三个列表都包含所有项目,这意味着我们必须提供三倍的数据。
幸运的是,此类事件非常罕见(例如,当我们添加属性时),但我想看到一种方法可以让我们避免此类突发事件?
你认为这个想法还有其他问题吗?
除了将项目标记为已删除并将物理删除推迟到缓存过期(即,在我的示例中直到周末)之外,是否有任何删除解决方案。
有什么改进吗?
最佳答案
是的,我看到了这方面的大问题。这是一个很大的列表意味着客户端有很多工作要做来提取它需要的资源。这对性能有很大的影响。
All these lists may change anytime and we never want to serve stale data
所以你应该使用长缓存时间和 cache-busting urls .
We're using 304 NOT MODIFIED
这是解决问题的最糟糕的方法。检索的大部分成本是延迟。如果您使用 304 响应进行回复,那么您已经承担了大部分成本 - 当您处理小块数据时,这一点尤其明显。 HTTP/2 有帮助(与 1.0 和 1.1 相比)但并没有消除成本。
我还会质疑您在原始问题中所做的许多假设。
关于http - 一种使用浏览器缓存进行增量更新的解决思路,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50165585/