feat: support ARC for DNS cache

This commit is contained in:
Larvan2
2023-12-02 17:07:36 +08:00
committed by wwqgtxx
parent bc74c943b8
commit 1a0932c210
24 changed files with 416 additions and 156 deletions

View File

@@ -3,7 +3,7 @@ package dns
import (
"net/netip"
"github.com/metacubex/mihomo/common/cache"
"github.com/metacubex/mihomo/common/lru"
"github.com/metacubex/mihomo/component/fakeip"
C "github.com/metacubex/mihomo/constant"
)
@@ -11,7 +11,7 @@ import (
type ResolverEnhancer struct {
mode C.DNSMode
fakePool *fakeip.Pool
mapping *cache.LruCache[netip.Addr, string]
mapping *lru.LruCache[netip.Addr, string]
}
func (h *ResolverEnhancer) FakeIPEnabled() bool {
@@ -105,11 +105,11 @@ func (h *ResolverEnhancer) StoreFakePoolState() {
func NewEnhancer(cfg Config) *ResolverEnhancer {
var fakePool *fakeip.Pool
var mapping *cache.LruCache[netip.Addr, string]
var mapping *lru.LruCache[netip.Addr, string]
if cfg.EnhancedMode != C.DNSNormal {
fakePool = cfg.Pool
mapping = cache.New(cache.WithSize[netip.Addr, string](4096))
mapping = lru.New(lru.WithSize[netip.Addr, string](4096))
}
return &ResolverEnhancer{

View File

@@ -5,7 +5,7 @@ import (
"strings"
"time"
"github.com/metacubex/mihomo/common/cache"
"github.com/metacubex/mihomo/common/lru"
"github.com/metacubex/mihomo/common/nnip"
"github.com/metacubex/mihomo/component/fakeip"
R "github.com/metacubex/mihomo/component/resolver"
@@ -21,7 +21,7 @@ type (
middleware func(next handler) handler
)
func withHosts(hosts R.Hosts, mapping *cache.LruCache[netip.Addr, string]) middleware {
func withHosts(hosts R.Hosts, mapping *lru.LruCache[netip.Addr, string]) middleware {
return func(next handler) handler {
return func(ctx *context.DNSContext, r *D.Msg) (*D.Msg, error) {
q := r.Question[0]
@@ -98,7 +98,7 @@ func withHosts(hosts R.Hosts, mapping *cache.LruCache[netip.Addr, string]) middl
}
}
func withMapping(mapping *cache.LruCache[netip.Addr, string]) middleware {
func withMapping(mapping *lru.LruCache[netip.Addr, string]) middleware {
return func(next handler) handler {
return func(ctx *context.DNSContext, r *D.Msg) (*D.Msg, error) {
q := r.Question[0]

View File

@@ -7,7 +7,7 @@ import (
D "github.com/miekg/dns"
"github.com/metacubex/mihomo/common/cache"
"github.com/metacubex/mihomo/common/lru"
"github.com/metacubex/mihomo/component/dhcp"
"github.com/metacubex/mihomo/component/resolver"
)
@@ -49,7 +49,7 @@ func ServeDNSWithDefaultServer(msg *D.Msg) (*D.Msg, error) {
func FlushCacheWithDefaultResolver() {
if r := resolver.DefaultResolver; r != nil {
r.(*Resolver).lruCache = cache.New[string, *D.Msg](cache.WithSize[string, *D.Msg](4096), cache.WithStale[string, *D.Msg](true))
r.(*Resolver).lruCache = lru.New[string, *D.Msg](lru.WithSize[string, *D.Msg](4096), lru.WithStale[string, *D.Msg](true))
}
}

View File

@@ -7,7 +7,8 @@ import (
"strings"
"time"
"github.com/metacubex/mihomo/common/cache"
"github.com/metacubex/mihomo/common/arc"
"github.com/metacubex/mihomo/common/lru"
"github.com/metacubex/mihomo/component/fakeip"
"github.com/metacubex/mihomo/component/geodata/router"
"github.com/metacubex/mihomo/component/resolver"
@@ -28,6 +29,11 @@ type dnsClient interface {
Address() string
}
type dnsCache interface {
GetWithExpire(key string) (*D.Msg, time.Time, bool)
SetWithExpire(key string, value *D.Msg, expire time.Time)
}
type result struct {
Msg *D.Msg
Error error
@@ -42,7 +48,7 @@ type Resolver struct {
fallbackDomainFilters []fallbackDomainFilter
fallbackIPFilters []fallbackIPFilter
group singleflight.Group
lruCache *cache.LruCache[string, *D.Msg]
cache dnsCache
policy []dnsPolicy
proxyServer []dnsClient
}
@@ -140,8 +146,9 @@ func (r *Resolver) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, e
}()
q := m.Question[0]
cacheM, expireTime, hit := r.lruCache.GetWithExpire(q.String())
cacheM, expireTime, hit := r.cache.GetWithExpire(q.String())
if hit {
log.Debugln("[DNS] cache hit for %s, expire at %s", q.Name, expireTime.Format("2006-01-02 15:04:05"))
now := time.Now()
msg = cacheM.Copy()
if expireTime.Before(now) {
@@ -181,7 +188,7 @@ func (r *Resolver) exchangeWithoutCache(ctx context.Context, m *D.Msg) (msg *D.M
msg.Extra = lo.Filter(msg.Extra, func(rr D.RR, index int) bool {
return rr.Header().Rrtype != D.TypeOPT
})
putMsgToCache(r.lruCache, q.String(), q, msg)
putMsgToCache(r.cache, q.String(), q, msg)
}
}()
@@ -408,12 +415,19 @@ type Config struct {
Hosts *trie.DomainTrie[resolver.HostValue]
Policy *orderedmap.OrderedMap[string, []NameServer]
RuleProviders map[string]provider.RuleProvider
CacheAlgorithm string
}
func NewResolver(config Config) *Resolver {
var cache dnsCache
if config.CacheAlgorithm == "lru" {
cache = lru.New(lru.WithSize[string, *D.Msg](4096), lru.WithStale[string, *D.Msg](true))
} else {
cache = arc.New(arc.WithSize[string, *D.Msg](4096))
}
defaultResolver := &Resolver{
main: transform(config.Default, nil),
lruCache: cache.New(cache.WithSize[string, *D.Msg](4096), cache.WithStale[string, *D.Msg](true)),
cache: cache,
ipv6Timeout: time.Duration(config.IPv6Timeout) * time.Millisecond,
}
@@ -444,10 +458,15 @@ func NewResolver(config Config) *Resolver {
return
}
if config.CacheAlgorithm == "" || config.CacheAlgorithm == "lru" {
cache = lru.New(lru.WithSize[string, *D.Msg](4096), lru.WithStale[string, *D.Msg](true))
} else {
cache = arc.New(arc.WithSize[string, *D.Msg](4096))
}
r := &Resolver{
ipv6: config.IPv6,
main: cacheTransform(config.Main),
lruCache: cache.New(cache.WithSize[string, *D.Msg](4096), cache.WithStale[string, *D.Msg](true)),
cache: cache,
hosts: config.Hosts,
ipv6Timeout: time.Duration(config.IPv6Timeout) * time.Millisecond,
}
@@ -550,7 +569,7 @@ func NewProxyServerHostResolver(old *Resolver) *Resolver {
r := &Resolver{
ipv6: old.ipv6,
main: old.proxyServer,
lruCache: old.lruCache,
cache: old.cache,
hosts: old.hosts,
ipv6Timeout: old.ipv6Timeout,
}

View File

@@ -11,7 +11,6 @@ import (
"strings"
"time"
"github.com/metacubex/mihomo/common/cache"
N "github.com/metacubex/mihomo/common/net"
"github.com/metacubex/mihomo/common/nnip"
"github.com/metacubex/mihomo/common/picker"
@@ -51,7 +50,7 @@ func updateTTL(records []D.RR, ttl uint32) {
}
}
func putMsgToCache(c *cache.LruCache[string, *D.Msg], key string, q D.Question, msg *D.Msg) {
func putMsgToCache(c dnsCache, key string, q D.Question, msg *D.Msg) {
// skip dns cache for acme challenge
if q.Qtype == D.TypeTXT && strings.HasPrefix(q.Name, "_acme-challenge.") {
log.Debugln("[DNS] dns cache ignored because of acme challenge for: %s", q.Name)