不能用 iris.Cache 做 API 缓存,因其仅适配静态文件,不解析查询参数、Header 和认证信息,无法生成语义化缓存键,也不支持 TTL 或主动失效,易导致缓存污染或失效。

直接用 iris.Cache 不行,它只缓存静态文件;API 数据缓存必须自己控制生命周期和键生成逻辑。
为什么不能用 iris.Cache 做 API 缓存
iris.Cache 是为 HandleDir 和静态资源设计的,内部基于文件修改时间 + ETag,对 JSON 接口完全无效:它不解析请求参数、不区分 GET /users?id=1 和 GET /users?id=2,也不支持 TTL 或主动失效。强行套用会导致所有用户看到同一份缓存结果,或根本不起作用。
常见错误现象:
- 缓存键固定为路径字符串(如
/api/v1/users),忽略查询参数、Header(如Accept-Language)、认证信息 - 响应体是 JSON,但缓存中间件误判为二进制流,返回乱码或空响应
- 上游数据更新后,缓存永不刷新,只能靠过期时间硬等
手动实现带语义的缓存键生成
缓存是否有效,80% 取决于键是否真正反映“这个请求的唯一性”。你得把影响响应结果的所有变量都揉进去:
- 请求路径(
c.Request().URL.Path) - 标准化后的查询参数(按 key 字典序排序并拼接,避免
?a=1&b=2和?b=2&a=1产生不同键) - 关键 Header(如
Authorization的 token 前缀、Accept类型) - 用户上下文(如
c.Values().Get("user_id"),用于个性化接口)
示例片段:
func cacheKey(c iris.Context) string {
path := c.Request().URL.Path
queries := c.Request().URL.Query()
var parts []string
for k := range queries {
parts = append(parts, k)
}
sort.Strings(parts)
for _, k := range parts {
parts = append(parts, k+"="+queries.Get(k))
}
if auth := c.GetHeader("Authorization"); auth != "" {
parts = append(parts, "auth="+strings.Split(auth, " ")[0])
}
return fmt.Sprintf("%x", md5.Sum([]byte(strings.Join(parts, "|"))))
}
用 Redis 做后端时的三个关键控制点
Iris 本身不绑定缓存后端,推荐直接集成 redis.Client,但要注意:
- 缓存值必须序列化为字节(
json.Marshal),不能直接存 struct;反序列化时注意类型匹配,避免interface{}导致字段丢失 - TTL 不能全靠
SETEX:高频接口(如商品详情)建议用滑动过期(GET + EXPIRE组合),避免雪崩;低频接口(如配置项)可用固定 TTL + 主动更新 - 缓存穿透防护要前置:对
id=0、负数、超长字符串等非法参数,先校验再查缓存,否则恶意请求会穿透到 DB
典型流程:
key := cacheKey(c)
var data []byte
if err := rdb.Get(ctx, key).Scan(&data); err == nil {
c.ResponseWriter().Header().Set("X-Cache", "HIT")
c.Write(data) // 注意:不是 ctx.JSON,因为 data 已是完整响应体字节
return
}
// 查询 DB 或调第三方
result, _ := fetchFromDB(c)
data, _ = json.Marshal(result)
rdb.Set(ctx, key, data, 5*time.Minute)
c.Write(data)
缓存与版本路由、中间件的协作陷阱
如果你用了 app.Party("/v2"),缓存键里必须包含版本前缀,否则 /v1/user/1 和 /v2/user/1 可能共用一个缓存——而它们的响应结构很可能不兼容。
同样,中间件顺序会影响缓存时机:
- 权限中间件(如 JWT 验证)必须在缓存读取之前执行,否则未授权请求也会被缓存
- 响应包装中间件(如统一加
{"code":0,"data":...})必须在缓存写入之后执行,否则缓存里存的是包装后的结构,下次读取就重复包装 - 日志中间件里记录缓存命中率时,别只看
X-CacheHeader——它可能被下游代理覆盖,应以实际是否跳过 DB 查询为准
最易被忽略的一点:缓存键里没包含 Accept 头,导致 application/json 和 application/xml 请求互相污染。API 缓存不是“快一点”,而是“快且准”。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











