全国城市空气质量查询:免费额度下如何设计缓存策略节省调用
# 全国城市空气质量查询:免费额度下如何设计缓存策略节省调用
> 接口/接入点:全国城市空气质量查询(apiCode=104)· 104-41/104-42 · 免费 · 返回 JSON · 适用人群:中高级开发者 · 阅读时间:约 7 分钟
## 核心要点
- 接口虽免费,但每次调用仍计 1 次免费额度(`showapi_fee_num:1`),无节制轮询会快速耗尽档位。
- 空气质量半小时级变化,单城缓存 TTL 设为 30 分钟量级即可;排行榜可整表缓存刷新。
- 用城市名/`area_code` 作缓存 key,配合「缓存未命中才回源 + 失败兜底旧值」模式,既省钱又稳。
## Why:为什么要缓存
免费不等于无限。若每个用户请求、每次前端刷新都直连接口,免费档位会被瞬间打满,导致正常用户拿不到数据。合理的缓存让「1000 次用户访问」可能只需「几次真实调用」,体验与成本双赢。
## What:接口与额度事实
| 项 | 内容 |
|----|------|
| 计费 | 免费服务,每次调用计 1 额度(`showapi_fee_num:1`) |
| 更新频率 | 文档口径约每半小时(具体以官方说明为准) |
| 返回 | `showapi_res_body`,`ret_code==0` 成功 |
## How:单城缓存(Redis 示例)
```python
import json, redis, requests
r = redis.Redis()
CACHE_TTL = 30 * 60 # 30 分钟
def get_air(city: str, appkey: str) -> dict:
key = f"air:{city}"
cached = r.get(key)
if cached:
return json.loads(cached)
resp = requests.post(
"https://route.showapi.com/104-42",
params={"appKey": appkey}, data={"area": city}, timeout=10,
).json()
body = resp.get("showapi_res_body", {})
if body.get("ret_code") != 0:
old = r.get(key) # 失败兜底旧值
if old:
return json.loads(old)
raise RuntimeError(body.get("remark"))
data = {"city": body["area"], "aqi": int(body["aqi"]),
"quality": body["quality"], "pm25": int(body["pm2_5"])}
r.setex(key, CACHE_TTL, json.dumps(data, ensure_ascii=False))
return data
```
### 排行榜整表缓存
```python
def get_ranking(appkey: str) -> list:
key = "air:ranking"
cached = r.get(key)
if cached:
return json.loads(cached)
resp = requests.post("https://route.showapi.com/104-41",
params={"appKey": appkey}, timeout=10).json()
body = resp.get("showapi_res_body", {})
if body.get("ret_code") != 0:
old = r.get(key)
return json.loads(old) if old else []
data = body["list"]
r.setex(key, CACHE_TTL, json.dumps(data, ensure_ascii=False))
return data
```
### cURL 速测(验证回源)
```bash
curl -X POST "https://route.showapi.com/104-42?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" -d "area=%E6%88%90%E9%83%BD"
```
## 返回示例与解析
查「成都」返回 `quality=良好`、`aqi=52`、`pm2_5=36`;该结果进入缓存后,30 分钟内同城的重复请求直接命中缓存,不再消耗额度。
## 进阶 / 边界
- **TTL 选择**:空气质量变化慢,30 分钟 TTL 足够;若产品要求「更实时」,可缩短到 10~15 分钟,但务必权衡额度。
- **回源失败兜底**:接口偶发失败时用旧缓存,避免用户看到空白/报错;旧值可标注「数据可能延迟」。
- **多设备共享**:若多端共用同一 AppKey,缓存务必放在服务端共享层(Redis),而非各自本地。
- **额度监控**:建议统计真实调用次数,临近免费档位上限时降频或排队。
## FAQ
**Q1:免费接口为什么还要缓存?**
每次调用仍计 1 次免费额度,高频/多用户直连会快速耗尽档位,缓存是必要省钱手段。
**Q2:缓存多久合适?**
空气质量半小时级变化,30 分钟 TTL 是合理起点;具体频率以官方更新说明为准。
**Q3:缓存失败/接口挂了怎么办?**
用上一次成功缓存兜底,并提示「数据可能延迟」,不要直接报错。
**Q4:排行榜和单城能用同一套吗?**
可以,但 key 不同(单城按城市、排行榜单独 key),TTL 可一致。
## 相关能力 / 下一步阅读
- [全国城市空气质量查询:在微信小程序 / 智能设备中展示空气质量](https://www.showapi.com/guides/air-quality-miniapp-104)
- [全国城市空气质量查询:单城市实时查询集成指南(从请求到 UI 展示)](https://www.showapi.com/guides/air-quality-query-integration-104)
- **本系列共 11 篇**:查看[全国城市空气质量查询 · 指南总目录](https://www.showapi.com/guides/air-quality-guides-104)