Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] lazy cache导致dnsmasq CPU占用率过高 #705

Open
4 tasks done
GreatMichaelLee opened this issue Aug 9, 2023 · 9 comments
Open
4 tasks done

[Bug] lazy cache导致dnsmasq CPU占用率过高 #705

GreatMichaelLee opened this issue Aug 9, 2023 · 9 comments

Comments

@GreatMichaelLee
Copy link

GreatMichaelLee commented Aug 9, 2023

在提交之前,请确认

  • 我已经尝试搜索过 Issue ,但没有找到相关问题。
  • 我正在使用最新的 mosdns 版本(或者最新的 commit),问题依旧存在。
  • 我仔细看过 wiki 后仍然无法自行解决该问题。
  • 我非常确定这是 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就不贴了)

image

使用的配置文件

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"}
@IrineSistiana

This comment was marked as off-topic.

@GreatMichaelLee
Copy link
Author

GreatMichaelLee commented Aug 10, 2023

lazy cache 是实验性功能,毕竟破坏了 dns 协议 ttl 的功能,不兼容是正常的。如果出问题建议直接关掉。

你的 mosdns 似乎是修改版。原版的 mosdns 应该不会打印上述 log。“unpacking entry”

我感觉是cache本身的性能问题(或者是go的问题?),导致dnsmasq后端被阻塞,所以会有delta peak效应,暂时的workaround就是关掉mosdns的cache用dnsmasq端的cache。另外,是用的原版啊,我看了lede仓库的make file是用的这里的啊

image

@IrineSistiana
Copy link
Owner

IrineSistiana commented Aug 10, 2023

我感觉是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 的日志。

@sunshineyxc
Copy link

我就是出现了‘mosdns 并发了大量请求打在了 dnsmasq 上。开 debug 日志可以看到 lazy cache 有没有往上游 dnsmasq 发送请求。’ 导致出国查询dns失败,如何解决?

@cqjerry
Copy link

cqjerry commented Oct 1, 2023

更新到v5.2.1后,发现 lazy_cache 一直报 failed to update。是安装问题还是BUG呢?

@CYaNu
Copy link

CYaNu commented Oct 2, 2023

我直接建了个debian 用mosdns做了个服务 比在lede等op下 效率更高

@asnon
Copy link

asnon commented Nov 12, 2023

更新到v5.2.1后,发现 lazy_cache 一直报 failed to update。是安装问题还是BUG呢?

我也是,请问你现在解决了么?

@yishion819
Copy link

yishion819 commented Feb 13, 2024

我也遇到这种情况了……关闭cache会好一些,并且版本从v4~v5都试过,cpu占用会相当的高

@yishion819
Copy link

刷回21或者19版本的op,负载正常了

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants