http缓存不生效主因是未介入writeheader/write阶段且未包装responsewriter;groupcache不适合作为web响应缓存;etag协商需前置校验;http.transport是客户端连接复用机制,与服务端响应缓存无关。
为什么 http.Handler 套一层 cache.Handler 通常不生效
因为 Go 标准库的 http.ServeMux 不会自动识别或透传缓存相关头(如 Cache-Control),更不会拦截响应体做缓存写入。直接包装 handler 只是“看起来有缓存逻辑”,实际没触发存储或复用。
真正起效的前提是:你得自己控制响应写出时机,并在 WriteHeader 和 Write 阶段介入。常见错误是只实现了 http.Handler 接口,却没重写 ResponseWriter。
- 必须用自定义
responseWriter包裹原始http.ResponseWriter,捕获状态码和响应体 - 缓存键应包含
method + uri + accept-encoding + query string,忽略无关 header(如User-Agent) - 对
POST/PUT/DELETE默认不缓存,除非业务明确允许(比如幂等查询接口用了 POST) - 注意
Content-Length头可能被缓存层覆盖,需在写入后重新计算或删掉
用 groupcache 替代本地 map 做分布式缓存是否合理
不合理——groupcache 是为 RPC 场景设计的 LRU+一致性哈希库,它没有内置过期机制,也不支持 TTL 或主动失效,且要求所有节点共享相同 key 空间。Web 缓存需要的是带过期、可清理、支持 vary 的响应级缓存。
如果你只是单机部署,用 sync.Map + 定时清理更轻量;如果要跨进程,优先考虑 redis 或 memcached,它们原生支持 EXPIRE、VARY 头解析、以及 stale-while-revalidate 这类高级语义。