我正在设计一个 REST API,最近我考虑了如何为动态内容进行大部分缓存(在我对这个主题的响应之后),同时尊重 HTTP(以及 REST)的原则。
显然,规范的解决方案(至少在我的理解中)是使用 etags,但这不会以任何方式减少请求的数量,只会减少大小。
我正在考虑在 URL 中嵌入一个版本(它将是服务器生成的,基于实际内容 - 无论是序列号还是一些哈希)。我将解释该方案和用户场景以及我认为它将如何提供帮助,然后提出我的问题。
设置
GET /entity/{id}/
Run Code Online (Sandbox Code Playgroud)
返回临时重定向到/entity/{id}/{current_version}无缓存标头。
GET /entity/{latest_version}/
Run Code Online (Sandbox Code Playgroud)
永远返回带有缓存的 OK 响应。
GET /entity/{old_version}/
Run Code Online (Sandbox Code Playgroud)
返回 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 当然,主要问题是使用 URLs 而不是 etags 进行缓存(希望浏览器缓存)。如果有人在高负载下(相对于服务器功能,咳)有实际经验,我将很感激分享。
补充说明
经过更多研究,版本化资源存在问题,它是链接资源更新的传播。有两种选择:
链接资源的特定版本。这意味着服务器端逻辑将是繁重和繁琐的,因为更新必须通过反向链接传播给链接资源;
链接 /latest/ 版本。这意味着即使资源和链接资源的具体版本都在本地缓存,客户端(浏览器)也必须向 /latest/ 发出请求,以便“检查”链接资源的最新版本。当然,这是一个小请求(仅重定向),如果资源没有更改位置,则已经缓存。一个问题可能是经常从这些链接中提取资源(与特定版本的查询结果相反)。另一个(更糟糕的)问题是,旧版本的资源实际上正在链接另一个最新版本的资源 - 这可能是数据不一致(即有人编辑了文档并更改了链接的附件 - 客户端将拥有旧版本的文档和新版本的文档)为附件)。
两种选择都不令人满意。在这种情况下,动态数据的缓存仅适用于“叶”级资源 - 不链接到任何其他资源的资源,胸围只有直接属性值。
最后的笔记
经过研究和讨论,版本化资源并不是通用架构中最聪明的想法。经过测量并有机会,可以在规范 API 中对“普通”资源进行改造。我会接受 Roysvork 的评论('我认为这很困难的原因是它不是一个很好的主意。')作为解决方案,如果它是一个单独的答案:)
| 归档时间: |
|
| 查看次数: |
898 次 |
| 最近记录: |