5

我正在设计一个 REST API,最近我考虑了如何充分利用动态内容的缓存(在我得到关于这个主题的响应之后),同时尊重 HTTP(以及因此 REST)的原则。

显然,规范的解决方案(至少在我的理解中)是使用 etags,但这不会以任何方式减少请求的数量,只会减少大小。

我正在考虑在 URL 中嵌入一个版本(它将由服务器生成,基于实际内容 - 无论是序列号还是一些哈希)。我将解释该方案和用户场景以及我认为它会如何帮助,然后提出我的问题。

设置

GET /entity/{id}/

返回临时重定向/entity/{id}/{current_version}和无缓存标头。

GET /entity/{latest_version}/

永远返回带有缓存的 OK 响应。

GET /entity/{old_version}/

返回 410 Gone (我不想真正保留旧版本)。

GET /entity/?[查询]

是一些搜索,它返回指向当前结果实体版本的链接列表。没有缓存。

使用场景以及我认为它会如何帮助

用户应用程序 (AJAX) 总是从某种查询开始,然后它必须提取实体的描述。由于预计单个客户端结果集的更改不会非常动态,因此使用上述方案和客户端每次都从查询中提取新结果似乎是个好主意,但如果大多数实体自上次访问以来没有更改,它们将已经缓存在浏览器中。如果这个假设成立,这将导致请求数量和总大小显着减少。

使用 etags 将导致更简单的 URI 方案,但可能更复杂和繁重的服务器端实现。

笔记和问题

1 我知道有人会建议/entity/{id}/应该是一个返回列表版本的集合,但版本实际上并没有存储、有用或需要。它更像是最新的同义词。我的问题是,除了一般原则之外,是否有人对此有任何问题。这是受保护的 API,在这种情况下我不关心 SEO,它对客户端是透明的。实际上,由于 API 或多或少会被超链接,因此通常不会直接调用 /entity/{id}/,而是使用返回的任何结果。例如,它可以用于上下文无关链接。

2 我对旧版本的 410 Gone 有一些疑问。一方面,这个版本不再可用,客户也不应该访问它。另一方面,如果客户端最终要求它(无论出于何种原因),将永久重定向返回到 /entity/{id}/ 可能是有意义的(可能比临时重定向到当前版本更好)。

3 说到重定向。301 固定用于永久重定向,但 302 是临时重定向的最佳选择吗?最重要的是浏览器支持(它将是 AJAX)。

4 当然,主要问题是使用 URL 而不是 etag 进行缓存(希望浏览器缓存)。如果有人在高负载下有真正的经验(相对于服务器功能,咳咳),我将不胜感激。

补充说明

经过更多研究后,版本化资源存在问题,它是链接资源的更新传播。有两种选择:

  1. 链接资源的特定版本。这意味着服务器端逻辑将很繁琐,因为必须通过反向链接为链接资源传播更新;

  2. 链接 /latest/ 版本。这意味着即使资源和链接资源的具体版本都在本地缓存,客户端(浏览器)也必须向 /latest/ 发出请求,以便“检查”链接资源的最新版本。当然,这是一个小请求(仅重定向),如果资源没有更改位置,则已缓存。一个问题可能是经常从此类链接中提取资源(与特定版本的查询结果相反)。另一个(更糟糕的)问题是,实际上旧版本的资源正在链接另一个的最新版本 - 它可能是数据不一致(即有人编辑了文档并更改了链接的附件 - 客户端将拥有旧版本的文档和新版本用于附件)。

两种选择都不令人满意。在这种情况下,动态数据的缓存仅适用于“叶”级资源 - 不链接到任何其他资源的资源,胸围仅具有直接属性值。

最后的笔记

经过研究和讨论,版本化资源并不是通用架构中最聪明的想法。经过测量并有机会,可以在规范 API 中为“普通”资源进行改造。我会接受 Roysvork 的评论('我认为这很困难的原因是这不是一个非常好的主意。')作为解决方案,如果它是一个单独的答案:)

4

0 回答 0