学习

使用 Redis 和 Express 中间件进行缓存

Simon Prickett
作者
Simon Prickett, Redis 首席开发者布道师

我们希望为我们的用户提供其每个位置的最新天气信息……因此我们与一家提供天气 API 的公司合作。

我们对该 API 的使用是计量的和速率限制的,因此理想情况下我们不想重复进行相同的请求。 这很浪费,可能会让我们损失金钱,还会减慢对用户的响应速度。

Redis 可以用作缓存来帮助解决此问题。Redis 中的键可以指定一个过期时间,之后 Redis 将删除它们。 我们将使用此功能将天气 API 调用的结果缓存为 Redis 字符串,并将它们保留一个小时,以在用户看到位置的最新天气报告和我们对 API 提供商服务器的负载之间取得平衡。

我们将使用一个额外的 Express 中间件函数来检查 Redis 缓存中是否已存在位置的天气信息,并且仅在必要时才从 API 提供商获取天气信息。

动手练习#

在本练习中,您将使用 Postman 来了解使用 Redis 进行缓存如何使 API 调用更快,同时也能避免我们因使用第三方服务而产生的成本。

您将在本练习中使用 "/location/:locationId/weather" 路由。 此路由的代码接受一个位置 ID,从其 Redis 哈希中检索该位置的纬度和经度,然后使用这些坐标调用 OpenWeather API 以检索天气数据作为 JSON 文档。

此文档将返回给用户,并在 Redis 中缓存一个小时。 对同一位置的天气的后续请求将在一个小时内由位于此路由逻辑之前的中间件函数处理。 它将返回缓存的值,而不会向 OpenWeather 服务器发出请求。

要使用 OpenWeather 的 API,您首先需要 在其网站上注册一个免费的 API 密钥.

获得 API 密钥后,停止 API 服务器组件(Ctrl-C),并设置一个包含您密钥的环境变量,如下所示

$ export WEATHER_API_KEY=my_api_key

然后启动服务器

$ npm run dev

现在启动 Postman,然后单击“+”按钮以创建一个新的请求

将 URL 设置为 https://localhost:8081/api/location/99/weather,并确保您从可用 HTTP 动词的下拉列表中选择了 GET 请求

单击“发送”,您应该会在“响应”面板中看到位置 99 的天气报告 JSON。 记下 Postman 报告的此请求的总响应时间(此处为 509 毫秒)

查看终端窗口中 API 服务器的输出,您应该会看到在缓存中没有找到位置 99 的值,因此数据是从 OpenWeather 请求的,然后添加到 Redis 中的缓存中

debug: Cache miss for location 99 weather.

再次单击 Postman 中的“发送”以重复请求……这次响应将从 Redis 提供,并且速度明显更快。 没有向 OpenWeather API 发出任何调用。 请注意结果来自缓存时的响应时间的差异(此处仅为 6 毫秒!)

查看 API 服务器终端窗口的输出表明此请求是从缓存中提供的

debug: Cache hit for location 99 weather.

最后,查看 Redis 中的缓存数据。 使用 RedisInsight 或 redis-cli 查看键 ncc:weather:99TTL 命令显示 Redis 从缓存中删除此键之前剩余的秒数

$ redis-cli
127.0.0.1:6379> GET ncc:weather:99
127.0.0.1:6379> TTL ncc:weather:99

如果您使用的是 RedisInsight,则可以在浏览器视图中看到剩余的 TTL(以秒为单位)

ncc:weather:99 将在最初写入 Redis 后一个小时被删除,导致此删除后的下一个对位置 99 的天气信息请求将是一个缓存未命中。 如果您想加快此过程,请使用 RedisInsight 中的垃圾桶图标或 redis-cli 中的 DEL 命令删除键 ncc:weather:99

127.0.0.1:6379> DEL ncc:weather:99

然后在 Postman 中再次尝试您的请求,看看会发生什么。

外部资源#

如果您想了解有关使用 Redis 在 Node.js 应用程序中缓存 API 响应的更多信息,请查看 Justin 的精彩视频