diff options
author | 2019-11-29 11:17:50 -0400 | |
---|---|---|
committer | 2019-11-29 15:17:50 +0000 | |
commit | b4df2d0d4c2d2014b113f9f8caf1f1b2ed6dc192 (patch) | |
tree | 090781b18a8b384c7b5005fba9d23df8e8caa938 /plugin/cache/handler.go | |
parent | 24176a97e65e65a768e4e06b192f38da511d1025 (diff) | |
download | coredns-b4df2d0d4c2d2014b113f9f8caf1f1b2ed6dc192.tar.gz coredns-b4df2d0d4c2d2014b113f9f8caf1f1b2ed6dc192.tar.zst coredns-b4df2d0d4c2d2014b113f9f8caf1f1b2ed6dc192.zip |
Add a serve_stale option for plugin/cache (#3468)
Automatically submitted.
Diffstat (limited to 'plugin/cache/handler.go')
-rw-r--r-- | plugin/cache/handler.go | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/plugin/cache/handler.go b/plugin/cache/handler.go index 4dc29167a..905a98ef4 100644 --- a/plugin/cache/handler.go +++ b/plugin/cache/handler.go @@ -26,19 +26,32 @@ func (c *Cache) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) server := metrics.WithServer(ctx) - i, found := c.get(now, state, server) - if i != nil && found { - resp := i.toMsg(r, now) - w.WriteMsg(resp) - - if c.shouldPrefetch(i, now) { - go c.doPrefetch(ctx, state, server, i, now) - } - return dns.RcodeSuccess, nil + ttl := 0 + i := c.getIgnoreTTL(now, state, server) + if i != nil { + ttl = i.ttl(now) + } + if i == nil || -ttl >= int(c.staleUpTo.Seconds()) { + crr := &ResponseWriter{ResponseWriter: w, Cache: c, state: state, server: server} + return plugin.NextOrFailure(c.Name(), c.Next, ctx, crr, r) } + if ttl < 0 { + servedStale.WithLabelValues(server).Inc() + // Adjust the time to get a 0 TTL in the reply built from a stale item. + now = now.Add(time.Duration(ttl) * time.Second) + go func() { + r := r.Copy() + crr := &ResponseWriter{Cache: c, state: state, server: server, prefetch: true, remoteAddr: w.LocalAddr()} + plugin.NextOrFailure(c.Name(), c.Next, ctx, crr, r) + }() + } + resp := i.toMsg(r, now) + w.WriteMsg(resp) - crr := &ResponseWriter{ResponseWriter: w, Cache: c, state: state, server: server} - return plugin.NextOrFailure(c.Name(), c.Next, ctx, crr, r) + if c.shouldPrefetch(i, now) { + go c.doPrefetch(ctx, state, server, i, now) + } + return dns.RcodeSuccess, nil } func (c *Cache) doPrefetch(ctx context.Context, state request.Request, server string, i *item, now time.Time) { @@ -83,6 +96,27 @@ func (c *Cache) get(now time.Time, state request.Request, server string) (*item, return nil, false } +// getIgnoreTTL unconditionally returns an item if it exists in the cache. +func (c *Cache) getIgnoreTTL(now time.Time, state request.Request, server string) *item { + k := hash(state.Name(), state.QType(), state.Do()) + + if i, ok := c.ncache.Get(k); ok { + ttl := i.(*item).ttl(now) + if ttl > 0 || (c.staleUpTo > 0 && -ttl < int(c.staleUpTo.Seconds())) { + cacheHits.WithLabelValues(server, Denial).Inc() + } + return i.(*item) + } + if i, ok := c.pcache.Get(k); ok { + ttl := i.(*item).ttl(now) + if ttl > 0 || (c.staleUpTo > 0 && -ttl < int(c.staleUpTo.Seconds())) { + cacheHits.WithLabelValues(server, Success).Inc() + } + return i.(*item) + } + return nil +} + func (c *Cache) exists(state request.Request) *item { k := hash(state.Name(), state.QType(), state.Do()) if i, ok := c.ncache.Get(k); ok { @@ -129,4 +163,11 @@ var ( Name: "drops_total", Help: "The number responses that are not cached, because the reply is malformed.", }, []string{"server"}) + + servedStale = prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: plugin.Namespace, + Subsystem: "cache", + Name: "served_stale_total", + Help: "The number of requests served from stale cache entries.", + }, []string{"server"}) ) |