mosdns
mosdns copied to clipboard
[Bug] lazy cache导致dnsmasq CPU占用率过高
在提交之前,请确认
- [X] 我已经尝试搜索过 Issue ,但没有找到相关问题。
- [X] 我正在使用最新的 mosdns 版本(或者最新的 commit),问题依旧存在。
- [X] 我仔细看过 wiki 后仍然无法自行解决该问题。
- [X] 我非常确定这是 mosdns 核心的问题。(如果是通过第三方衍生软件使用 mosdns 核心,不确定问题源头时,请先向衍生软件开发者提交问题。)
mosdns 版本
v5.1.3
操作系统
Openwrt LEDE 当前最新仓库代码+PW最新版本
Bug 描述和复现步骤
如题所示,5.1.3如果设置为dnsmasq上游,且启用lazy cache的时候,在main sequence里查询lazy cache,会导致dnsmasq 周期性的CPU浪涌,关掉cache能减缓这种现象。通过openwrt上netdata和htop可以观测到(htop就不贴了)
使用的配置文件
log:
level: error
file: "/mnt/sdc1/mosdns/mosdns.log"
# API 入口设置
api:
http: "0.0.0.0:9091"
include: []
plugins:
# 国内域名
- tag: geosite_cn
type: domain_set
args:
files:
- "/var/mosdns/geosite_cn.txt"
# 国内ip
- tag: geoip_cn
type: ip_set
args:
files:
- "/var/mosdns/geoip_cn.txt"
# Google CN
- tag: geosite_google_cn
type: domain_set
args:
files:
- "/var/mosdns/geosite_google-cn.txt"
# 国外域名
- tag: geosite_no_cn
type: domain_set
args:
files:
- "/var/mosdns/geosite_geolocation-!cn.txt"
# 白名单 加入的域名始终允许使用 “本地 DNS” 进行解析
- tag: whitelist
type: domain_set
args:
files:
- "/etc/mosdns/rule/whitelist.txt"
# 黑名单 加入的域名将屏蔽 DNS 解析
- tag: blocklist
type: domain_set
args:
files:
- "/etc/mosdns/rule/blocklist.txt"
# 灰名单 加入的域名始终使用 “远程 DNS” 进行解析
- tag: greylist
type: domain_set
args:
files:
- "/etc/mosdns/rule/greylist.txt"
# DDNS域名 加入的域名始终使用 “本地 DNS” 进行解析,并且修改 TTL 为 5 秒,解析结果不进行缓存
- tag: ddnslist
type: domain_set
args:
files:
- "/etc/mosdns/rule/ddnslist.txt"
# 自定义 Hosts 重写
- tag: hosts
type: hosts
args:
files:
- "/etc/mosdns/rule/hosts.txt"
# 重定向请求的域名
- tag: redirect
type: redirect
args:
files:
- "/etc/mosdns/rule/redirect.txt"
# PTR 黑名单 加入的域名将阻止 PTR 请求
- tag: local_ptr
type: domain_set
args:
files:
- "/etc/mosdns/rule/local-ptr.txt"
# 屏蔽失效/威胁 URL
- tag: sp_low
type: domain_set
args:
files:
- "/usr/share/mosdns/sp_low.tdata"
# 缓存
- tag: lazy_cache
type: cache
args:
size: 20000
lazy_cache_ttl: 86400
dump_file: "/etc/mosdns/cache.dump"
dump_interval: 600
# 转发至本地服务器
- tag: forward_local
type: forward
args:
upstreams:
- addr: https://doh.pub/dns-query
bootstrap: 223.5.5.5
# 转发至远程服务器
- tag: forward_remote
type: forward
args:
upstreams:
- addr: https://1.1.1.1/dns-query
enable_pipeline: false
# 修改ttl(默认0 不修改ttl)
- tag: modify_ttl
type: sequence
args:
- exec: ttl 0-0
# 修改 ddns 域名 ttl(默认 5秒)
- tag: modify_ddns_ttl
type: sequence
args:
- exec: ttl 5-5
# 国内解析
- tag: local_sequence
type: sequence
args:
- exec: $forward_local
# 国外解析
- tag: remote_sequence
type: sequence
args:
- exec: prefer_ipv4
- exec: $forward_remote
# 有响应则修改 TTL 并终止返回
- tag: has_resp_sequence
type: sequence
args:
- matches: qname $ddnslist
exec: $modify_ddns_ttl
- matches: "!qname $ddnslist"
exec: $modify_ttl
- matches: has_resp
exec: accept
# fallback 用本地服务器 sequence
# 返回非国内 ip 则 drop_resp
- tag: query_is_local_ip
type: sequence
args:
- exec: $local_sequence
- matches: "!resp_ip $geoip_cn"
exec: drop_resp
# fallback 用远程服务器 sequence
- tag: query_is_remote
type: sequence
args:
- exec: $remote_sequence
# fallback 用远程服务器 sequence
- tag: fallback
type: fallback
args:
primary: query_is_remote
secondary: query_is_remote
threshold: 500
always_standby: true
# 查询 DDNS 域名
- tag: query_is_ddns_domain
type: sequence
args:
- matches: qname $ddnslist
exec: $local_sequence
#查询国内Google域名
- tag: query_is_google_cn_domain
type: sequence
args:
- matches: qname $geosite_google_cn
exec: $remote_sequence
# 查询国内域名
- tag: query_is_local_domain
type: sequence
args:
- matches: qname $geosite_cn
exec: $local_sequence
# 查询国外域名
- tag: query_is_no_local_domain
type: sequence
args:
- matches: qname $geosite_no_cn
exec: $remote_sequence
# 查询白名单
- tag: query_is_whitelist_domain
type: sequence
args:
- matches: qname $whitelist
exec: $local_sequence
# 查询灰名单
- tag: query_is_greylist_domain
type: sequence
args:
- matches: qname $greylist
exec: $remote_sequence
# 拒绝名单
- tag: query_is_reject_domain
type: sequence
args:
- matches: qname $blocklist
exec: reject 3
- matches: qname $sp_low
exec: reject 3
- matches:
- qtype 12
- qname $local_ptr
exec: reject 3
- matches: qtype 65
exec: reject 3
# 主要的运行逻辑插件
# sequence 插件中调用的插件 tag 必须在 sequence 前定义,
# 否则 sequence 找不到对应插件。
- tag: main_sequence
type: sequence
args:
- exec: $hosts
- exec: jump has_resp_sequence
# 非 “拒绝名单” 或 “DDNS域名” 则启用缓存
- matches:
- "!qname $ddnslist"
- "!qname $blocklist"
- "!qname $sp_low"
- "!qname $local_ptr"
#exec: $lazy_cache
exec: $redirect
- exec: jump has_resp_sequence
- exec: $query_is_ddns_domain
- exec: jump has_resp_sequence
- exec: $query_is_whitelist_domain
- exec: jump has_resp_sequence
- exec: $query_is_reject_domain
- exec: jump has_resp_sequence
- exec: $query_is_greylist_domain
- exec: jump has_resp_sequence
- exec: $query_is_google_cn_domain
- exec: jump has_resp_sequence
- exec: $query_is_local_domain
- exec: jump has_resp_sequence
- exec: $query_is_no_local_domain
- exec: jump has_resp_sequence
- exec: $fallback
# 启动 udp 服务器。
- tag: udp_server
type: udp_server
args:
entry: main_sequence
listen: ":5335"
# 启动 tcp 服务器。
- tag: tcp_server
type: tcp_server
args:
entry: main_sequence
listen: ":5335"
mosdns 的 log 记录
日志设置成error最高级别,减少因为日志IO带来的问题判断干扰
2023-08-09T14:33:41.781Z INFO unpacking entry {"tag": "cn", "length": 11543, "file": "/var/mosdns/geoip_cn.txt"}
2023-08-09T14:33:41.887Z INFO unpacking entry {"tag": "cn", "length": 66054, "file": "/var/mosdns/geosite_cn.txt"}
2023-08-09T14:33:41.890Z INFO unpacking entry {"tag": "geolocation-!cn", "length": 19212, "file": "/var/mosdns/geosite_geolocation-!cn.txt"}
2023-08-09T14:33:41.997Z INFO unpacking entry {"tag": "google-cn", "length": 159, "file": "/var/mosdns/geosite_google-cn.txt"}
lazy cache 是实验性功能,毕竟破坏了 dns 协议 ttl 的功能,不兼容是正常的。如果出问题建议直接关掉。
你的 mosdns 似乎是修改版。原版的 mosdns 应该不会打印上述 log。“unpacking entry”
lazy cache 是实验性功能,毕竟破坏了 dns 协议 ttl 的功能,不兼容是正常的。如果出问题建议直接关掉。
你的 mosdns 似乎是修改版。原版的 mosdns 应该不会打印上述 log。“unpacking entry”
我感觉是cache本身的性能问题(或者是go的问题?),导致dnsmasq后端被阻塞,所以会有delta peak效应,暂时的workaround就是关掉mosdns的cache用dnsmasq端的cache。另外,是用的原版啊,我看了lede仓库的make file是用的这里的啊
我感觉是cache本身的性能问题(或者是go的问题?),导致dnsmasq后端被阻塞,所以会有delta peak效应,暂时的workaround就是关掉mosdns的cache用dnsmasq端的cache。另外,是用的原版啊,我看了lede仓库的make file是用的这里的啊
阻塞不占 cpu,如果是 dnsmasq cpu 占用高,最可能的就是 mosdns 并发了大量请求打在了 dnsmasq 上。开 debug 日志可以看到 lazy cache 有没有往上游 dnsmasq 发送请求。
~~另外,我搜了源代码,mosdns 真不会打印 “unpacking entry” 然后报告载入了的列表有多少条。这功能我之前想加的但是鸽了。~~
搜到了。这是 v2dat 的日志。
我就是出现了‘mosdns 并发了大量请求打在了 dnsmasq 上。开 debug 日志可以看到 lazy cache 有没有往上游 dnsmasq 发送请求。’ 导致出国查询dns失败,如何解决?
更新到v5.2.1后,发现 lazy_cache 一直报 failed to update。是安装问题还是BUG呢?
我直接建了个debian 用mosdns做了个服务 比在lede等op下 效率更高
更新到v5.2.1后,发现 lazy_cache 一直报 failed to update。是安装问题还是BUG呢?
我也是,请问你现在解决了么?
我也遇到这种情况了……关闭cache会好一些,并且版本从v4~v5都试过,cpu占用会相当的高
刷回21或者19版本的op,负载正常了