feat(proxy,config): 代理层集成 stale 缓存回退逻辑
上游请求失败时,根据错误类型(超时/其他)调用 GetStale 尝试返回 过期缓存。配置文件示例补充 stale_if_error 和 stale_if_timeout 字段。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
8deda73b24
commit
be974b2e18
@ -409,6 +409,8 @@ func GenerateConfigYAML(cfg *Config) ([]byte, error) {
|
|||||||
buf.WriteString(" # cache_lock: true # 防止缓存击穿\n")
|
buf.WriteString(" # cache_lock: true # 防止缓存击穿\n")
|
||||||
buf.WriteString(" # cache_lock_timeout: 5s # 缓存锁超时时间(默认 5s)\n")
|
buf.WriteString(" # cache_lock_timeout: 5s # 缓存锁超时时间(默认 5s)\n")
|
||||||
buf.WriteString(" # stale_while_revalidate: 30s\n")
|
buf.WriteString(" # stale_while_revalidate: 30s\n")
|
||||||
|
buf.WriteString(" # stale_if_error: 1m # 上游错误时使用过期缓存的时间窗口\n")
|
||||||
|
buf.WriteString(" # stale_if_timeout: 30s # 上游超时时使用过期缓存的时间窗口\n")
|
||||||
buf.WriteString(" # background_update_disable: false # 禁用后台更新(默认启用)\n")
|
buf.WriteString(" # background_update_disable: false # 禁用后台更新(默认启用)\n")
|
||||||
buf.WriteString(" # cache_ignore_headers: [] # 缓存时忽略的响应头\n")
|
buf.WriteString(" # cache_ignore_headers: [] # 缓存时忽略的响应头\n")
|
||||||
buf.WriteString(" # revalidate: false # 启用条件请求(默认关闭)\n")
|
buf.WriteString(" # revalidate: false # 启用条件请求(默认关闭)\n")
|
||||||
|
|||||||
@ -181,7 +181,7 @@ func NewProxy(cfg *config.ProxyConfig, targets []*loadbalance.Target, transportC
|
|||||||
MaxAge: cfg.Cache.MaxAge,
|
MaxAge: cfg.Cache.MaxAge,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
p.cache = cache.NewProxyCache(rules, cfg.Cache.CacheLock, cfg.Cache.StaleWhileRevalidate)
|
p.cache = cache.NewProxyCache(rules, cfg.Cache.CacheLock, cfg.Cache.StaleWhileRevalidate, cfg.Cache.StaleIfError, cfg.Cache.StaleIfTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化重定向改写器
|
// 初始化重定向改写器
|
||||||
@ -683,6 +683,19 @@ func (p *Proxy) ServeHTTP(ctx *fasthttp.RequestCtx) {
|
|||||||
p.healthChecker.MarkUnhealthy(target)
|
p.healthChecker.MarkUnhealthy(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 尝试使用 stale 缓存
|
||||||
|
if p.cache != nil {
|
||||||
|
hashKey, origKey := p.buildCacheKeyHash(ctx)
|
||||||
|
isTimeout := errors.Is(err, fasthttp.ErrTimeout)
|
||||||
|
if staleEntry, ok := p.cache.GetStale(hashKey, origKey, isTimeout); ok {
|
||||||
|
logging.Info().Msgf("[PROXY] 使用 stale 缓存: key=%s, isTimeout=%v", origKey, isTimeout)
|
||||||
|
p.writeCachedResponse(ctx, staleEntry)
|
||||||
|
upstreamStatus = staleEntry.Status
|
||||||
|
upstreamAddr = upstreamCache
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 释放缓存锁
|
// 释放缓存锁
|
||||||
if p.cache != nil && attempt == 0 {
|
if p.cache != nil && attempt == 0 {
|
||||||
hashKey := p.buildCacheKeyHashValue(ctx)
|
hashKey := p.buildCacheKeyHashValue(ctx)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user