高并发排盘架构:异步队列 + 缓存处理紫微斗数排盘请求
# 高并发排盘架构:异步队列 + 缓存处理紫微斗数排盘请求
> 接口/接入点:紫微斗数排盘(apiCode=1647,接入点 1) · 免费(设档次限制) · 同步单条返回 · 适用人群:日均请求量大的平台架构师 · 阅读时间约 9 分钟
## 核心要点
- 接口是**同步单条**排盘:一次请求返回一张命盘,无批量、无订阅/回调能力。
- 高并发下不要阻塞式同步直连:用「消息队列削峰 + 缓存命中 + 异步结果写入」解耦,前端轮询或 WebSocket 取结果。
- 结合 [缓存策略](https://www.showapi.com/guides/ziwei-doushu-cache-cost-1647),绝大多数重复请求可在缓存层消化,真正打到接口的只是新增出生信息。
## Why:为什么同步直连扛不住高并发
当你的网站/活动带来突发流量(如节日、营销),大量请求同时同步调用接口会:① 瞬间打满免费档位限制;② 线程/连接阻塞堆积,拖垮整体可用性;③ 重复生日反复消耗额度。正确做法是把「用户请求」与「接口调用」解耦——先快速响应、异步排盘、结果缓存、按需取回。
## What:架构速览
| 组件 | 作用 |
|------|------|
| API 网关 / Web 层 | 接收 `(time, gender)`,先查缓存,未命中则入队并返回任务 ID |
| 缓存层(Redis) | 命中度直接返回,省接口调用 |
| 消息队列(如 Redis Stream / RabbitMQ) | 削峰,异步消费排盘任务 |
| 排盘 Worker | 调易源接口,写结果回缓存/数据库 |
| 结果取回 | 前端轮询任务 ID 或 WebSocket 推送 |
## How:异步队列 + 缓存骨架
**Python:入队与 Worker(示意,用 Redis 作为队列与缓存)**
```python
import hashlib, json, redis, requests
r = redis.Redis(host="localhost", port=6379, db=0)
API_URL = "https://route.showapi.com/1647-1"
def enqueue(time: str, gender: str) -> str:
key = "ziwei:" + hashlib.sha256(f"{time}|{gender}".encode()).hexdigest()
if r.exists(key):
return key # 已排盘,直接返回缓存键
task_id = f"task:{key}"
r.rpush("ziwei_queue", json.dumps({"time": time, "gender": gender, "key": key}))
return task_id
def worker():
while True:
_, raw = r.blpop("ziwei_queue")
job = json.loads(raw)
resp = requests.post(API_URL, params={"appKey": "YOUR_APPKEY"},
data={"time": job["time"], "gender": job["gender"]}, timeout=10).json()
res = resp["showapi_res_body"]
if res.get("ret_code") == 0:
r.set(job["key"], json.dumps(res), ex=86400 * 365) # 结果回写缓存
```
**前端取回(轮询示例)**
```javascript
async function poll(key) {
for (let i = 0; i < 20; i++) {
const v = await (await fetch(`/api/ziwei/result?key=${key}`)).json();
if (v.ready) return v.result;
await new Promise(r => setTimeout(r, 500));
}
throw new Error("排盘超时,请稍后重试");
}
```
**cURL(仅验证单条调用)**
```bash
curl -X POST "https://route.showapi.com/1647-1?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
-d "time=1993-10-27%2006&gender=m"
```
## 返回示例与解析
Worker 调通后,结果写入缓存,结构与 [返回字段全解](https://www.showapi.com/guides/ziwei-doushu-response-fields-1647) 一致(`result` 含 `wx`/`pan` 等)。前端轮询拿到即渲染。
## 进阶 / 边界
- **指数退避调用接口**:Worker 调易源失败时用指数退避重试,避免雪崩式重试放大压力。
- **并发度受档位约束**:免费档位的实际并发/日调用上限以 [官方说明](https://www.showapi.com/free-api) 为准,本文不编造数字;Worker 并发数应与之匹配,超出部分排队。
- **缓存是首要优化**:相比堆 Worker,先把缓存做扎实,重复请求根本不进队列,成本最低。
- **无批量能力**:接口一次只排一张盘,多用户需循环入队/循环调用,不要假设存在批量端点。
## FAQ
**Q1:能不能用多线程同步直连扛并发?**
A:不推荐。同步直连在突发流量下会阻塞堆积、打满免费档位。用队列削峰 + 缓存命中 + 异步回写更稳。
**Q2:结果怎么给用户?**
A:两种:前端按任务 ID 轮询;或 Worker 完成后通过 WebSocket 主动推送。轮询实现简单,适合大多数场景。
**Q3:免费档位限制具体是多少?**
A:以 [免费 API 档位说明](https://www.showapi.com/free-api) 为准,本文不杜撰具体数字;架构上把 Worker 并发与队列长度按档位留余量即可。
**Q4:队列堆积怎么办?**
A:先确认缓存命中率是否够高(多数重复请求应被缓存消化);再横向扩 Worker,并给队列设最大长度与丢弃策略,保护接口不被冲垮。
## 相关能力 / 下一步阅读
- [免费档位限制下,如何设计缓存策略节省紫微斗数排盘调用成本?](https://www.showapi.com/guides/ziwei-doushu-cache-cost-1647)
- [紫微斗数排盘API如何集成到传统文化网站?从出生表单到命盘可视化](https://www.showapi.com/guides/ziwei-doushu-website-integration-1647)
- [传统文化研究平台方案:多用户命盘如何统一管理?](https://www.showapi.com/guides/ziwei-doushu-research-platform-1647)
- **本系列共 12 篇**:查看[紫微斗数排盘 API 指南总目录](https://www.showapi.com/guides/ziwei-doushu-guides-1647)