国际原油价格查询:免费档位下如何设计缓存节省调用成本?
国际原油价格查询原油价格APIWTI原油布伦特原油免费接口 # 国际原油价格查询:免费档位下如何设计缓存节省调用成本?
> 接口:国际原油价格查询(apiCode=1108,接入点 1108-1)| 免费(有档位限制)| 请求方式 POST/GET | 返回 JSON | 适用人群:中高级开发者、架构师 | 阅读时间:约 7 分钟
## 核心要点
- 接口免费但有使用档次限制,无脑高频调用会很快耗尽额度。
- 数据每小时整点更新,缓存 TTL 设为 55~60 分钟即可,绝大多数读请求命中缓存。
- 多实例用共享缓存(Redis)统一拉取,避免重复消耗;配合错峰与限流更进一步。
## Why
免费意味着"额度有限"。如果你的看板、监控、推送都直接打接口,很容易在一天内把档位额度用光,导致后续调用失败。好在数据每小时才更新一次——只要把"读"和"拉"分开(读走缓存、拉按整点),就能把一天的调用量从几十万次压到 24 次(每种 `code` 各一次)。本文给出生产级缓存设计。
## What
| 项目 | 说明 |
|------|------|
| 成本来源 | 按次调用,免费档位有上限 |
| 最优拉取频率 | 每小时一次(对齐整点更新) |
| 缓存目标 | 让 99% 以上的读请求不触达接口 |
## How
### 生产级缓存设计(Redis + 单飞)
```python
import redis, requests, time
APP_KEY = "YOUR_APPKEY"
URL = "https://route.showapi.com/1108-1"
rds = redis.Redis(host="localhost", port=6379, db=0)
TTL = 55 * 60 # 秒
def get_quote(code="wti"):
key = f"oil:{code}"
cached = rds.get(key)
if cached:
return cached.decode("utf-8") # 命中缓存
# 缓存未命中:拉接口(生产环境建议加"单飞"避免并发击穿)
resp = requests.get(URL, params={"appKey": APP_KEY, "code": code}, timeout=10).json()
body = resp["showapi_res_body"]
if body["ret_code"] != 0:
raise SystemExit("失败")
payload = str(body)
rds.setex(key, TTL, payload)
return payload
```
### 令牌桶限流(防止突发打爆)
```python
import time
class TokenBucket:
def __init__(self, rate, capacity):
self.rate, self.capacity = rate, capacity
self.tokens = capacity
self.ts = time.time()
def allow(self):
now = time.time()
self.tokens = min(self.capacity, self.tokens + (now - self.ts) * self.rate)
self.ts = now
if self.tokens >= 1:
self.tokens -= 1
return True
return False
bucket = TokenBucket(rate=1/3600, capacity=2) # 每小时约 1 次,突发上限 2
```
**Node.js(fetch + 内存缓存)**
```javascript
const APP_KEY = "YOUR_APPKEY";
const cache = new Map();
async function getQuote(code = "wti") {
const hit = cache.get(code);
if (hit && hit.expire > Date.now()) return hit.value;
const r = await fetch(
"https://route.showapi.com/1108-1?appKey=" + APP_KEY,
{
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
body: "code=" + code,
signal: AbortSignal.timeout(10000),
}
).then((x) => x.json());
if (r.showapi_res_body.ret_code !== 0) throw new Error("失败");
cache.set(code, { value: r.showapi_res_body, expire: Date.now() + 55 * 60 * 1000 });
return cache.get(code).value;
}
```
## 返回示例与解析
缓存的内容即 `showapi_res_body` 整个对象(含 `nowPrice`/`diff_rate`/`time` 等)。每次整点后缓存过期,下一次读触发重新拉取并刷新。
## 进阶 / 边界
- **共享缓存优先**:多实例部署务必用 Redis 等共享缓存,否则每台机器各自拉取会成倍消耗额度。
- **错峰拉取**:若拉多种 `code`,可在整点后错开几秒分别拉,降低瞬时压力。
- **额度告警**:建议监控每日调用量,接近档位上限时降级(如只保留核心 `code`)。
- **档位数字以官方为准**:具体免费档位阈值文档未给出,请见 [免费档位说明](https://www.showapi.com/free-api)。
## FAQ
**Q:免费额度用完了会怎样?**
按文档说明,超出使用档次限制后调用会受限制;具体表现以接口/控制台提示为准,建议提前用缓存压低调用量。
**Q:缓存 TTL 设多少最省?**
对齐整点更新,设 55~60 分钟;过短会多调接口、过长会延迟拿到新值。
**Q:单实例和多实例缓存有区别吗?**
有。多实例各自缓存会重复拉取,应用 Redis 等共享缓存统一拉取。
**Q:WTI 和布伦特要算两次额度吗?**
是,两种 `code` 各一次请求;都在整点拉取,一天各 24 次。
## 相关能力 / 下一步阅读
- [国际原油价格查询:整点更新意味着什么?数据时效与缓存设计](https://www.showapi.com/guides/crude-oil-price-update-frequency-1108)
- [国际原油价格查询:如何用数据搭建实时油价看板?从拉取到可视化](https://www.showapi.com/guides/crude-oil-price-dashboard-1108)
- [国际原油价格查询:原油涨跌监控与趋势预警搭建指南](https://www.showapi.com/guides/crude-oil-price-alert-1108)
- **本系列共 12 篇**:查看[国际原油价格查询官方指南总目录](https://www.showapi.com/guides/crude-oil-price-guides-1108)