学习

使用 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 设置为 http://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 中尝试您的请求,看看会发生什么。

外部资源#

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