使用 HTTP 标头实现更快的响应
简介
有这样一种情况:你因为某个 API 路由速度慢而收到了工单,而你的工作就是修复这个问题。听起来很熟悉,对吧?你首先想到的是让那里的任何操作都快起来,但在这种情况下,这是不可能的。第二个选择是给服务提供更多资源,但这听起来不像是一个真正的解决方案。第三个选择是使用 Redis/memcached 进行缓存,以避免为每个请求支付惩罚。但是,如果我告诉你一个“免费”的解决方案,它就像在响应中添加一些标头一样简单,你会怎么想?
解决方案本身与服务器托管位置(或至少与域名所在位置)相关。每个平台都有各自的实现方式。为了简单起见,我们将使用 Cloudflare 作为示例。
概括
设置
对于我们的例子,我们需要:
- Cloudflare 帐户
- Hono 项目
- 三条路线
/
渲染 HTML 页面/no-cache
返回不带缓存的数据/cached
返回缓存数据
克隆项目后,运行npm run deploy
将项目部署到cloudflare workers。
如果不看代码,你可能会觉得这是一个非常复杂且具体的设置。其实不然。以下是缓存 API 响应所需的代码。
return new Response(new Date().toISOString(), {
headers: {
'Cache-Control': 'public, max-age=10' // keep the cache for 10 seconds
}
})
就这样,我们使用 http 而不是 redis 进行缓存。
解释
Cloudflare 具有缓存标头,因此它可以缓存对其自身域发出的获取请求,就我而言:https://[project].stneto.dev
。这些标头不与特定提供商绑定,因此每个提供商都可以有自己的版本,例如:Netlify、Vercel、AWS Api Gateway,等等。
代码示例确实显示了一些 JavaScript 代码,但缓存本身并不与语言或框架绑定,因此也可以执行类似的操作:
Go(原生 http 处理程序)
func handler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "max-age=3600") // Cache for 1 hour (in seconds)
w.Header().Set("Expires", "Tue, 01 Jan 2024 00:00:00 GMT") // Cache expiration date and time
w.Header().Set("ETag", "123456") // ETag for conditional requests
w.Write([]byte("Hello 🤠"))
}
拉斯特(阿克苏姆)
async fn handler(_req: Request<Body>) -> Response<Body> {
// Set Cache-Control header to enable caching for 1 hour
Response::builder()
.header("Cache-Control", "max-age=3600")
.body(Body::from("Hello 🤠"))
.unwrap()
}
总结
更好地利用平台的诀窍可以为您带来意想不到的益处,因为解决方案是“免费的”,您只需要知道如何使用它。使用平台提供的服务和使用平台的特定功能之间是有区别的。在平台之间使用响应头非常简单,因为您只需替换它们就可以了。但是,如果您需要离开某个平台,使用与该平台绑定的某些特定行为可能会非常危险。这关乎收益递减;保持“无平台”可能很好,因为您可以更灵活地选择服务的运行位置,但与此同时,您将无法完全使用平台提供的功能。