Feature: implemented a strategy similar to optimistic DNS (#647)

This commit is contained in:
Comzyh
2020-05-07 15:10:14 +08:00
committed by GitHub
parent b085addbb0
commit b979ff0bc2
4 changed files with 121 additions and 45 deletions

View File

@ -42,7 +42,7 @@ type Resolver struct {
fallback []dnsClient
fallbackFilters []fallbackFilter
group singleflight.Group
cache *cache.Cache
lruCache *cache.LruCache
}
// ResolveIP request with TypeA and TypeAAAA, priority return TypeA
@ -96,22 +96,35 @@ func (r *Resolver) Exchange(m *D.Msg) (msg *D.Msg, err error) {
}
q := m.Question[0]
cache, expireTime := r.cache.GetWithExpire(q.String())
if cache != nil {
cache, expireTime, hit := r.lruCache.GetWithExpire(q.String())
if hit {
now := time.Now()
msg = cache.(*D.Msg).Copy()
setMsgTTL(msg, uint32(expireTime.Sub(time.Now()).Seconds()))
if expireTime.Before(now) {
setMsgTTL(msg, uint32(1)) // Continue fetch
go r.exchangeWithoutCache(m)
} else {
setMsgTTL(msg, uint32(expireTime.Sub(time.Now()).Seconds()))
}
return
}
return r.exchangeWithoutCache(m)
}
// ExchangeWithoutCache a batch of dns request, and it do NOT GET from cache
func (r *Resolver) exchangeWithoutCache(m *D.Msg) (msg *D.Msg, err error) {
q := m.Question[0]
defer func() {
if msg == nil {
return
}
putMsgToCache(r.cache, q.String(), msg)
putMsgToCache(r.lruCache, q.String(), msg)
if r.mapping {
ips := r.msgToIP(msg)
for _, ip := range ips {
putMsgToCache(r.cache, ip.String(), msg)
putMsgToCache(r.lruCache, ip.String(), msg)
}
}
}()
@ -141,7 +154,7 @@ func (r *Resolver) IPToHost(ip net.IP) (string, bool) {
return r.pool.LookBack(ip)
}
cache := r.cache.Get(ip.String())
cache, _ := r.lruCache.Get(ip.String())
if cache == nil {
return "", false
}
@ -294,17 +307,17 @@ type Config struct {
func New(config Config) *Resolver {
defaultResolver := &Resolver{
main: transform(config.Default, nil),
cache: cache.New(time.Second * 60),
main: transform(config.Default, nil),
lruCache: cache.NewLRUCache(cache.WithSize(4096), cache.WithStale(true)),
}
r := &Resolver{
ipv6: config.IPv6,
main: transform(config.Main, defaultResolver),
cache: cache.New(time.Second * 60),
mapping: config.EnhancedMode == MAPPING,
fakeip: config.EnhancedMode == FAKEIP,
pool: config.Pool,
ipv6: config.IPv6,
main: transform(config.Main, defaultResolver),
lruCache: cache.NewLRUCache(cache.WithSize(4096), cache.WithStale(true)),
mapping: config.EnhancedMode == MAPPING,
fakeip: config.EnhancedMode == FAKEIP,
pool: config.Pool,
}
if len(config.Fallback) != 0 {

View File

@ -79,21 +79,21 @@ func (e EnhancedMode) String() string {
}
}
func putMsgToCache(c *cache.Cache, key string, msg *D.Msg) {
var ttl time.Duration
func putMsgToCache(c *cache.LruCache, key string, msg *D.Msg) {
var ttl uint32
switch {
case len(msg.Answer) != 0:
ttl = time.Duration(msg.Answer[0].Header().Ttl) * time.Second
ttl = msg.Answer[0].Header().Ttl
case len(msg.Ns) != 0:
ttl = time.Duration(msg.Ns[0].Header().Ttl) * time.Second
ttl = msg.Ns[0].Header().Ttl
case len(msg.Extra) != 0:
ttl = time.Duration(msg.Extra[0].Header().Ttl) * time.Second
ttl = msg.Extra[0].Header().Ttl
default:
log.Debugln("[DNS] response msg error: %#v", msg)
return
}
c.Put(key, msg.Copy(), ttl)
c.SetWithExpire(key, msg.Copy(), time.Now().Add(time.Second*time.Duration(ttl)))
}
func setMsgTTL(msg *D.Msg, ttl uint32) {