2026年6月9日
2026年6月9日
Unbound のパフォーマンスチューニング|統計で現状を測り、スレッド・キャッシュ・ソケットを調整する
Unbound のパフォーマンスチューニングは、設定値を大きくするところから始めるのではなく、unbound-control stats_noreset で現状を測り、詰まっている箇所に合わせて調整するのが近道です。多くの環境で効くのは、スレッド数とスラブ数をCPUコア数に合わせること、キャッシュのメモリを増やすこと、同時に扱える問い合わせ数とソケットのバッファを広げることの3つです。この記事では、計測の方法、各設定の意味と目安、反映と効果の確認までを順に説明します。
設定項目の既定値や挙動は Unbound の版によって変わります(2026年10月現在)。以下の値は NLnet Labs の公式ドキュメントにある考え方に沿った目安なので、手元の版の man unbound.conf で確認してから使ってください。
まず現状を測る
unbound-control を使えるようにする
統計の取得には unbound-control を使います。まだ有効にしていなければ、設定に remote-control を加え、証明書を作ります。
remote-control:
control-enable: yes
control-interface: 127.0.0.1
sudo unbound-control-setup
sudo unbound-checkconf
sudo systemctl restart unbound
sudo unbound-control status
見るべき統計
stats_noreset は統計を0に戻さずに読み出します(stats は読み出すたびに0に戻すため、ほかの監視と併用すると数字が合わなくなります)。
sudo unbound-control stats_noreset | grep -E \
'total\.num\.(queries|cachehits|cachemiss)|total\.requestlist\.(exceeded|overwritten|avg)|total\.recursion\.time\.(avg|median)|mem\.cache\.'
- total.num.cachehits と total.num.cachemiss:キャッシュで答えた割合を計算します。割合が低く、
mem.cache.rrsetやmem.cache.messageが設定した上限に張り付いているなら、キャッシュが小さすぎる可能性があります。 - total.requestlist.exceeded と total.requestlist.overwritten:処理待ちの一覧があふれて、問い合わせを捨てたか上書きした回数です。0 より大きくなり続けるなら、同時に扱える問い合わせ数が足りません。
- total.recursion.time.avg:キャッシュにない問い合わせを解決するのにかかった平均時間(秒)です。ここが大きい場合、原因は Unbound の設定より上流側やネットワークにあることが多いです。
OS 側では、UDP の受信バッファがあふれていないかも確認します。
netstat -su | grep -i 'receive buffer errors'
この値が増え続けている場合は、Unbound が受け取る前にカーネルがパケットを捨てています。
負荷をかけて測る
本番の統計だけでは、設定を変えた効果を比べにくいことがあります。検証環境に同じ設定の Unbound を用意し、DNS-OARC の dnsperf などで負荷をかけると、変更の前後を同じ条件で比べられます。負荷試験は自分が管理するサーバーに対してだけ行い、外部の公開DNSに向けないでください。
スレッド数とスラブ数を合わせる
num-threads の既定値は 1 で、1コアしか使いません。CPU のコア数に合わせて増やすと、処理能力が上がります。
スラブ(*-slabs)は、キャッシュをいくつに分けて、スレッド同士のロックの取り合いを減らすかの設定です。スレッド数に近い2のべき乗(2・4・8…)にします。2のべき乗でない値は使えません。
server:
# 4コアのサーバーの例
num-threads: 4
msg-cache-slabs: 4
rrset-cache-slabs: 4
infra-cache-slabs: 4
key-cache-slabs: 4
コア数より多いスレッドにしても速くはならず、ほかのプロセスとCPUを取り合うだけです。同じサーバーで別のサービスも動かしているなら、コア数より少なめにします。
キャッシュのメモリを増やす
既定のキャッシュは小さめなので、メモリに余裕があれば増やします。rrset-cache-size を msg-cache-size のおよそ2倍にするのが、公式ドキュメントで示されている目安です。
server:
msg-cache-size: 64m
rrset-cache-size: 128m
注意したいのは、実際のメモリ使用量がこの合計より大きくなることです。インフラキャッシュや DNSSEC の鍵のキャッシュ、メモリ確保の管理用の領域が加わるため、設定値の合計を大きく上回ることがあります。反映後に実際の使用量(ps や systemctl status の Memory 欄)を測り、十分な余裕を残してください。systemd の MemoryMax やコンテナのメモリ上限を設定している場合は、上限に達して強制終了されないかも確認します。
キャッシュを増やしても効果が出るのは、同じ名前が繰り返し引かれる環境です。問い合わせる名前がばらばらな環境では、ヒット率はあまり上がりません。
同時に扱える問い合わせ数とソケットを広げる
total.requestlist.exceeded が増えている場合は、次の2つを見直します。
outgoing-range:スレッドごとに使える外向きのポート数です。大きな値を使うには、Unbound が libevent を使ってビルドされている必要があります。unbound -Vの出力で、libevent を使っているかを確認できます。num-queries-per-thread:スレッドごとに同時に処理する問い合わせ数です。outgoing-rangeの半分程度にするのが目安です。
UDP の受信バッファがあふれている場合は、so-rcvbuf と so-sndbuf を設定します。OS 側の上限(net.core.rmem_max と net.core.wmem_max)がこれより小さいと、設定しても効かず、起動時に警告が出ます。
server:
outgoing-range: 8192
num-queries-per-thread: 4096
so-rcvbuf: 4m
so-sndbuf: 4m
so-reuseport: yes
# /etc/sysctl.d/90-unbound.conf に書き、sudo sysctl --system で反映する
net.core.rmem_max = 4194304
net.core.wmem_max = 4194304
so-reuseport: yes は、Linux で各スレッドに受信を分散させる設定です。スレッドを増やしたのに1つのスレッドに負荷が偏るときに効きます。
体感の速さに効く設定
処理能力とは別に、利用者が感じる応答の速さに効く設定もあります。
prefetch: yes:よく引かれる名前の有効期限が近づくと、期限切れの前に問い合わせ直します。人気のある名前でキャッシュ切れの待ち時間が出にくくなる代わりに、上流への問い合わせが少し増えます。serve-expired: yes:期限切れのキャッシュをいったん返し、裏で問い合わせ直します(RFC 8767 の考え方)。上流が一時的に不調でも答え続けられる反面、古い答えを返すことがあります。serve-expired-ttlで、どれだけ古いものまで返すかの上限を決めておきます。
cache-min-ttl で TTL を引き上げる方法もありますが、ドメインの管理者が意図した TTL を無視することになり、移転やフェイルオーバーの切り替えが反映されなくなります。使うとしても数十秒程度にとどめ、大きな値にはしません。
反映と効果の確認
設定を変えたら、構文を確認してから反映します。
sudo unbound-checkconf
sudo systemctl restart unbound
sudo unbound-control status
unbound-control reload でも設定は読み直されますが、キャッシュが空になる点は再起動と同じです。スレッド数やソケット関連の変更は、再起動で反映するのが無難です。利用者の多いリゾルバーなら、キャッシュが空になって一時的に遅くなるため、利用の少ない時間帯を選びます。複数台で運用しているなら1台ずつ反映します。
反映後は、最初に測った統計と同じ項目を、同じくらいの時間が経ってから比べます。
- キャッシュのヒット率が上がったか。
total.requestlist.exceededの増え方が止まったか。netstat -suの受信バッファのエラーが増えなくなったか。- メモリ使用量が想定の範囲に収まっているか。
改善しない項目があれば、1つずつ設定を戻して影響を見ます。複数の設定を一度に変えると、どれが効いたのか、どれが悪化させたのかが分からなくなるため、変更は少しずつ行い、変更内容と結果を記録しておきます。
まとめ
- チューニングの前に
unbound-control stats_noresetで、キャッシュのヒット率・処理待ち一覧のあふれ・解決時間・メモリを測ります。OS の UDP 受信バッファのエラーも確認します。 num-threadsはコア数に、*-slabsはそれに近い2のべき乗に合わせます。- キャッシュは
rrset-cache-sizeをmsg-cache-sizeの2倍程度にし、実際のメモリ使用量は設定値より大きくなる前提で上限を決めます。 - 問い合わせのあふれには
outgoing-range・num-queries-per-thread、パケットの取りこぼしにはso-rcvbufと OS の上限を合わせて調整します。 - 反映は
unbound-checkconfの後に行い、同じ統計で前後を比べて、変更は少しずつ記録しながら進めます。