aboutsummaryrefslogtreecommitdiff
path: root/plugin/cache/handler.go
diff options
context:
space:
mode:
authorGravatar Gonzalo Paniagua Javier <gonzalo.mono@gmail.com> 2019-11-29 11:17:50 -0400
committerGravatar corbot[bot] <39114087+corbot[bot]@users.noreply.github.com> 2019-11-29 15:17:50 +0000
commitb4df2d0d4c2d2014b113f9f8caf1f1b2ed6dc192 (patch)
tree090781b18a8b384c7b5005fba9d23df8e8caa938 /plugin/cache/handler.go
parent24176a97e65e65a768e4e06b192f38da511d1025 (diff)
downloadcoredns-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.go63
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"})
)