Maison  >  Article  >  développement back-end  >  Recommandations de configuration du cache DNS pour chaque langage de développement

Recommandations de configuration du cache DNS pour chaque langage de développement

WBOY
WBOYavant
2023-04-10 11:31:031913parcourir

Auteur : Zhai Helong

1. Contexte

Dans le domaine informatique, l'un des premiers principes à prendre en compte lorsqu'il s'agit d'actions d'optimisation des performances est l'utilisation du cache. Un mécanisme raisonnable de mise en cache des données peut apporter la solution. avantages suivants :

1. Raccourcissez le chemin d'acquisition des données et mettez en cache les données des points d'accès à proximité pour une lecture ultérieure rapide, améliorant ainsi considérablement l'efficacité du traitement

2. -services de données finaux et réduire l'écart entre le front-end et le back-end

De la conception du cache multi-niveaux du matériel CPU à l'affichage rapide des pages par les navigateurs, en passant par les produits commerciaux populaires tels que CDN et Passerelles de stockage cloud, le concept de mise en cache est appliqué partout.

Dans le domaine des réseaux publics, le mécanisme de mise en cache des produits matures tels que les systèmes d'exploitation, les navigateurs et les applications mobiles a grandement éliminé les problèmes rencontrés par les fournisseurs de réseaux tels que China Telecom et China Unicom, et les fournisseurs de contenu tels que les principales plateformes de portail. et les fabricants de CDN sont confrontés à une forte pression de service. Seul le DNS de l'opérateur peut gérer calmement des milliards de résolutions DNS par seconde, le cluster d'équipements réseau peut facilement supporter la bande passante Internet au niveau de Tbit par seconde et la plate-forme CDN peut gérer rapidement des milliards de requêtes par seconde. .

Face à l'échelle d'accès aux noms de domaine actuellement énorme et croissante de l'entreprise, l'équipe de l'auteur optimise constamment l'architecture du cluster et améliore les performances du logiciel DNS. Elle doit également de toute urgence promouvoir divers environnements clients pour effectuer des demandes de résolution de noms de domaine. le mécanisme, nous avons spécialement organisé des membres de l'équipe pour rechercher et rédiger cet article de guide afin de donner des suggestions raisonnables au personnel de développement et d'exploitation front-end de l'entreprise, aux clients et aux partenaires, d'optimiser le processus global de demande DNS et d'augmenter l'efficacité commerciale.

Cet article explique principalement comment implémenter la mise en cache des enregistrements de résolution DNS localement sur le client dans différents contextes de langage commercial et de développement. En même temps, sur la base de la compréhension par l'équipe de l'auteur du DNS lui-même et de l'environnement réseau de l'entreprise, d'autres mesures. sont donnés, et finalement engagés à normaliser les demandes de résolution DNS côté client.

2. Explication des termes

1. Client

Le client mentionné dans cet article fait généralement référence à tous les objets qui lancent activement des requêtes réseau, y compris, mais sans s'y limiter, les serveurs, PC, terminaux mobiles, systèmes d'exploitation, ligne de commande. outils, scripts, logiciels de service, application utilisateur, etc.

2. DNS

Domain Name System (Serveur/Service), système de noms de domaine (serveur/service), peut être compris comme un type de service de base de données

Le client communique avec le serveur via le réseau ; , en s'appuyant sur l'adresse IP, identifie l'autre partie ; en tant qu'utilisateur client, il est difficile pour les humains de se souvenir d'un grand nombre d'adresses IP, c'est pourquoi des noms de domaine faciles à retenir tels que www.jd.com sont inventés pour stocker le mappage. relation entre les noms de domaine et les adresses IP dans DNS à utiliser par les clients

Ce n'est qu'après que le client a obtenu l'adresse IP du serveur en lançant une demande de résolution de nom de domaine auprès du DNS qu'il peut lancer une demande de communication réseau vers le serveur. Adresse IP et obtenir véritablement le service ou le contenu porté par le nom de domaine.

Référence : Système de noms de domaineProcessus de résolution de noms de domaine

3. LDNS

DNS local, l'environnement d'accès au réseau public est généralement automatiquement attribué par le fournisseur de réseau où il se trouve ( le fournisseur a le contrôle, même peut être utilisé pour le détournement de DNS, c'est-à-dire la falsification de l'adresse IP obtenue à partir de la résolution du nom de domaine), et l'environnement intranet est automatiquement attribué par les paramètres du service informatique

Généralement Unix, de type Unix ; , et les systèmes MacOS peuvent afficher leur propre LDNS via /etc/resolv.conf, dans le serveur de noms a déclaré plus tard que ce fichier prend également en charge l'auto-édition et la modification par l'utilisateur pour spécifier le LDNS, tel que le DNS public commun sur le réseau public tel que Google DNS, 114DNS, etc. ; dans les environnements intranet purs, il n'est généralement pas recommandé de modifier sans consulter le service informatique, ce qui peut entraîner l'indisponibilité du service ; veuillez vous référer aux résultats de la commande man resolv.conf.

Lorsque la résolution du nom de domaine est anormale, la possibilité d'une anomalie du service LDNS ou d'un détournement de résolution doit également être envisagée.

Référence : modifiez les paramètres TCP/IP (y compris DNS) dans le système Windows ;

4. Le système hosts

DNS peut fournir dynamiquement la relation de mappage entre les noms de domaine et les adresses IP, que l'on trouve couramment dans les fichiers hosts. de divers systèmes d'exploitation. Il s'agit d'un fichier d'enregistrement statique de la relation de mappage entre le nom de domaine et l'IP, et généralement l'enregistrement des hôtes a priorité sur la résolution DNS, c'est-à-dire que lorsqu'il n'y a pas de cache local ou que le cache manque, le nom de domaine correspondant. L'enregistrement est d'abord interrogé via les hôtes. S'il n'y a pas de mappage pertinent dans les hôtes, la demande DNS continuera à être initiée. Pour le contrôle de cette logique dans l'environnement Linux, veuillez vous référer à la section d'introduction du cache DNS du langage C/C++ ci-dessous.

Ainsi, dans le travail réel, les fonctionnalités par défaut ci-dessus sont souvent utilisées pour écrire la relation de mappage entre un nom de domaine spécifique et une adresse IP spécifique dans le fichier hosts (communément appelé « hôtes fixes »), qui est utilisé pour contourner la résolution DNS. traiter et fournir un accès ciblé à l'adresse IP cible (l'effet est le même que l'option -x de curl ou l'option de proxy spécifiée -e de wget

5. valeur vivante, ce concept est applicable dans de nombreux domaines et peut avoir des significations différentes.

Les descriptions TTL impliquées dans cet article concernent toutes la mise en cache des données, qui peut être comprise directement comme la « période de validité » des données mises en cache, à partir du moment où les données sont mises en cache, les données qui existent dans le cache pendant plus longtemps que la durée de vie des données. Le temps spécifié par TTL est pris en compte. Pour les données expirées, lorsque les données sont à nouveau appelées, la validité sera confirmée ou réobtenue immédiatement à partir de la source de données faisant autorité.

Étant donné que le mécanisme de mise en cache est généralement déclenché et mis à jour passivement, si les données d'origine faisant autorité du back-end changent pendant la période de validité du cache du client, le client ne le détectera pas, ce qui se manifestera par un certain degré de retard de mise à jour des données. et les données mises en cache dans l'entreprise. Incohérence temporaire avec les données faisant autorité.

Pour la durée de vie du cache des enregistrements DNS côté client, nous recommandons une valeur de 60 s en même temps. S'il s'agit d'une activité peu sensible comme les tests, ou d'une entreprise avec des ajustements de résolution de noms de domaine peu fréquents, il peut être étendu de manière appropriée, même au niveau de l'heure ou du jour ;

3. Suggestions d'optimisation de la résolution DNS

1 Enquête sur la prise en charge de la mise en cache DNS par diverses bibliothèques de réseaux linguistiques

Les résultats de l'enquête suivants sont recommandés aux développeurs. reportez-vous à pour implémenter la mise en cache DNS client auto-développée. Chaque langage de développement peut avoir un support différent pour la mise en cache DNS. Analysons-les un par un ici.

Langage C/C++

(1) Fonction getaddrinfo de la glibc

La bibliothèque glibc dans l'environnement Linux fournit deux fonctions de résolution de noms de domaine : la fonction gethostbyname et la fonction getaddrinfo Avec le passage à IPv6 et aux modèles de programmation threadés, getaddrinfo devient plus utile car il analyse non seulement les adresses IPv6 mais est également thread-safe. Il est recommandé d'utiliser la fonction getaddrinfo.

Prototype de fonction : la fonction

int getaddrinfo( const char *node, 
 const char *service,
 const struct addrinfo *hints,
 struct addrinfo **res);
getaddrinfo est une fonction de bibliothèque de base de niveau relativement bas. De nombreuses fonctions de résolution de noms de domaine dans les langages de développement reposent sur cette fonction, nous présenterons donc ici la logique de traitement de cette fonction. . Suivez cet appel système de fonction via la commande strace.

Recommandations de configuration du cache DNS pour chaque langage de développement1) Recherchez le cache nscd (voir ci-dessous pour une introduction à nscd)

Nous pouvons voir les appels système suivants via la commande strace dans l'environnement Linux

//连接nscd
socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)
Grâce au socket Unix l'interface "/var /run/nscd/socket" se connecte au service nscd pour interroger le cache DNS.

2) Interrogez le fichier /etc/hosts

Si le service nscd n'est pas démarré ou si le cache manque, continuez à interroger le fichier hosts, nous devrions voir l'appel système suivant

//读取 hosts 文件
open("/etc/host.conf", O_RDONLY)= 3
fstat(3, {st_mode=S_IFREG|0644, st_size=9, ...}) = 0
...
open("/etc/hosts", O_RDONLY|O_CLOEXEC)= 3
fcntl(3, F_GETFD) = 0x1 (flags FD_CLOEXEC)
fstat(3, {st_mode=S_IFREG|0644, st_size=178, ...}) = 0
3) Interrogez le service DNS

Interrogez l'adresse IP du serveur DNS (serveur de noms) à partir de la configuration /etc/resolv.conf, puis effectuez une requête DNS pour obtenir le résultat de la résolution. Nous pouvons voir l'appel système suivant

//获取 resolv.conf 中 DNS 服务 IP
open("/etc/resolv.conf", O_RDONLY)= 3
fstat(3, {st_mode=S_IFREG|0644, st_size=25, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fef2abee000
read(3, "nameserver 114.114.114.114nn", 4096) = 25
...
//连到 DNS 服务,开始 DNS 查询
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("114.114.114.114")}, 16) = 0
poll([{fd=3, events=POLLOUT}], 1, 0)= 1 ([{fd=3, revents=POLLOUT}])
Quant à savoir si le client doit d'abord rechercher le fichier /etc/hosts ou obtenir d'abord le serveur DNS à partir de /etc/resolv.conf pour la requête et la résolution, /etc/nsswitch. conf Contrôle :

#/etc/nsswitch.conf 部分配置
...
#hosts: db files nisplus nis dns
hosts:files dns
...
Vous pouvez réellement voir à travers la commande strace qu'après que le système appelle le socket nscd et avant de lire /etc/resolv.conf, le fichier sera lu

newfstatat(AT_FDCWD, "/etc/nsswitch.conf", {st_mode=S_IFREG|0644, st_size=510, ...}, 0) = 0
...
openat(AT_FDCWD, "/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
4) Vérification

#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>

int gethostaddr(char * name);

int main(int argc, char *argv[]){
if (argc != 2)
{
fprintf(stderr, "%s $host", argv[0]);
return -1;
}

int i = 0;
for(i = 0; i < 5; i++)
{
int ret = -1;
ret = gethostaddr(argv[1]);
if (ret < 0)
{
fprintf(stderr, "%s $host", argv[0]);
return -1;
}
//sleep(5);
}

return 0;
}

int gethostaddr(char* name){
struct addrinfo hints;
struct addrinfo *result;
struct addrinfo *curr;
int ret = -1;
char ipstr[INET_ADDRSTRLEN];
struct sockaddr_in*ipv4;

memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;

ret = getaddrinfo(name, NULL, &hints, &result);
if (ret != 0)
{
fprintf(stderr, "getaddrinfo: %sn", gai_strerror(ret));
return ret;
}

for (curr = result; curr != NULL; curr = curr->ai_next)
{
ipv4 = (struct sockaddr_in *)curr->ai_addr;
inet_ntop(curr->ai_family, &ipv4->sin_addr, ipstr, INET_ADDRSTRLEN);
printf("ipaddr:%sn", ipstr);
}

freeaddrinfo(result);
return 0;
}
Complet Sur la base de l'analyse ci-dessus, la fonction getaddrinfo combinée à nscd peut réaliser la mise en cache DNS.

(2) Fonction de résolution de nom de domaine de la bibliothèque libcurl

La bibliothèque libcurl est une bibliothèque de transmission réseau couramment utilisée par les clients dans le langage c/c++. La commande curl est implémentée sur la base de cette bibliothèque. Cette bibliothèque appelle également la fonction de bibliothèque getaddrinfo pour implémenter la résolution de nom de domaine DNS et prend également en charge la mise en cache DNS nscd.

int
Curl_getaddrinfo_ex(const char *nodename,
const char *servname,
const struct addrinfo *hints,
Curl_addrinfo **result)
{
...
error = getaddrinfo(nodename, servname, hints, &aihead);
if(error)
return error;
...
}
Java

Le langage Java est le langage principal pour le développement de systèmes d'entreprise dans de nombreuses entreprises. En écrivant un simple programme client HTTP, testez et vérifiez si la bibliothèque réseau Java prend en charge la mise en cache DNS. Le test vérifie les deux composants HttpURLConnection et Apache httpcomponents-client dans la bibliothèque standard Java.

(1) Bibliothèque standard Java HttpURLConnection

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;


public class HttpUrlConnectionDemo {

public static void main(String[] args) throws Exception {
String urlString = "http://example.my.com/";

int num = 0;
while (num < 5) {
URL url = new URL(urlString);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoOutput(true);

OutputStream os = conn.getOutputStream();
os.flush();
os.close();

if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream is = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
System.out.println("rsp:" + sb.toString());
} else {
System.out.println("rsp code:" + conn.getResponseCode());
}
num++;
}
}
}

测试结果显示 Java 标准库 HttpURLConnection 是支持 DNS 缓存,5 次请求中只有一次 DNS 请求。

(2)Apache httpcomponents-client

import java.util.ArrayList;
import java.util.List;

import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicNameValuePair;

public class QuickStart {
public static void main(final String[] args) throws Exception {
int num = 0;
while (num < 5) {
try (final CloseableHttpClient httpclient = HttpClients.createDefault()) {
final HttpGet httpGet = new HttpGet("http://example.my.com/");
try (final CloseableHttpResponse response1 = httpclient.execute(httpGet)) {
System.out.println(response1.getCode() + " " + response1.getReasonPhrase());
final HttpEntity entity1 = response1.getEntity();
EntityUtils.consume(entity1);
}
}
num++;
}
}
}

测试结果显示 Apache httpcomponents-client 支持 DNS 缓存,5 次请求中只有一次 DNS 请求。

从测试中发现 Java 的虚拟机实现一套 DNS 缓存,即实现在 java.net.InetAddress 的一个简单的 DNS 缓存机制,默认为缓存 30 秒,可以通过 networkaddress.cache.ttl 修改默认值,缓存范围为 JVM 虚拟机进程,也就是说同一个 JVM 进程中,30秒内一个域名只会请求DNS服务器一次。同时 Java 也是支持 nscd 的 DNS 缓存,估计底层调用 getaddrinfo 函数,并且 nscd 的缓存级别比 Java 虚拟机的 DNS 缓存高。

# 默认缓存 ttl 在 jre/lib/security/java.security 修改,其中 0 是不缓存,-1 是永久缓存
networkaddress.cache.ttl=10

# 这个参数 sun.net.inetaddr.ttl 是以前默认值,目前已经被 networkaddress.cache.ttl 取代

Go

随着云原生技术的发展,Go 语言逐渐成为云原生的第一语言,很有必要验证一下 Go 的标准库是否支持 DNS 缓存。通过我们测试验证发现 Go 的标准库 net.http 是不支持 DNS 缓存,也是不支持 nscd 缓存,应该是没有调用 glibc 的库函数,也没有实现类似 getaddrinfo 函数的功能。这个跟 Go语言的自举有关系,Go 从 1.5 开始就基本全部由 Go(.go) 和汇编 (.s) 文件写成的,以前版本的 C(.c) 文件被全部重写。不过有一些第三方 Go 版本 DNS 缓存库,可以自己在应用层实现,还可以使用 fasthttp 库的 httpclient。

(1)标准库net.http

package main

import (
"flag"
"fmt"
"io/ioutil"
"net/http"
"time"
)

var httpUrl string

func main() {
flag.StringVar(&httpUrl, "url", "", "url")
flag.Parse()
getUrl := fmt.Sprintf("http://%s/", httpUrl)

fmt.Printf("url: %sn", getUrl)
for i := 0; i < 5; i++ {
_, buf, err := httpGet(getUrl)
if err != nil {
fmt.Printf("err: %vn", err)
return
}
fmt.Printf("resp: %sn", string(buf))
time.Sleep(10 * time.Second)# 等待10s发起另一个请求
}
}

func httpGet(url string) (int, []byte, error) {
client := createHTTPCli()
resp, err := client.Get(url)
if err != nil {
return -1, nil, fmt.Errorf("%s err [%v]", url, err)
}
defer resp.Body.Close()

buf, err := ioutil.ReadAll(resp.Body)
if err != nil {
return resp.StatusCode, buf, err
}

return resp.StatusCode, buf, nil
}
func createHTTPCli() *http.Client {
readWriteTimeout := time.Duration(30) * time.Second
tr := &http.Transport{
DisableKeepAlives: true,//设置短连接
IdleConnTimeout: readWriteTimeout,
}
client := &http.Client{
Timeout: readWriteTimeout,
Transport: tr,
}
return client
}

从测试结果来看,net.http 每次都去 DNS 查询,不支持 DNS 缓存。

(2)fasthttp 库

fasthttp 库是 Go 版本高性能 HTTP 库,通过极致的性能优化,性能是标准库 net.http 的 10 倍,其中一项优化就是支持 DNS 缓存,我们可以从其源码看到

//主要在fasthttp/tcpdialer.go中
type TCPDialer struct {
...
// This may be used to override DNS resolving policy, like this:
// var dialer = &fasthttp.TCPDialer{
//Resolver: &net.Resolver{
//PreferGo: true,
//StrictErrors: false,
//Dial: func (ctx context.Context, network, address string) (net.Conn, error) {
//d := net.Dialer{}
//return d.DialContext(ctx, "udp", "8.8.8.8:53")
//},
//},
// }
Resolver Resolver

// DNSCacheDuration may be used to override the default DNS cache duration (DefaultDNSCacheDuration)
DNSCacheDuration time.Duration
...
}

可以参考如下方法使用 fasthttp client 端

func main() {
// You may read the timeouts from some config
readTimeout, _ := time.ParseDuration("500ms")
writeTimeout, _ := time.ParseDuration("500ms")
maxIdleConnDuration, _ := time.ParseDuration("1h")
client = &fasthttp.Client{
ReadTimeout: readTimeout,
WriteTimeout:writeTimeout,
MaxIdleConnDuration: maxIdleConnDuration,
NoDefaultUserAgentHeader:true, // Don't send: User-Agent: fasthttp
DisableHeaderNamesNormalizing: true, // If you set the case on your headers correctly you can enable this
DisablePathNormalizing:true,
// increase DNS cache time to an hour instead of default minute
Dial: (&fasthttp.TCPDialer{
Concurrency:4096,
DNSCacheDuration: time.Hour,
}).Dial,
}
sendGetRequest()
sendPostRequest()
}

(3)第三方DNS缓存库

这个是 github 中的一个 Go 版本 DNS 缓存库

可以参考如下代码,在HTTP库中支持DNS缓存

r := &dnscache.Resolver{}
t := &http.Transport{
DialContext: func(ctx context.Context, network string, addr string) (conn net.Conn, err error) {
host, port, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
ips, err := r.LookupHost(ctx, host)
if err != nil {
return nil, err
}
for _, ip := range ips {
var dialer net.Dialer
conn, err = dialer.DialContext(ctx, network, net.JoinHostPort(ip, port))
if err == nil {
break
}
}
return
},
}

Python

(1)requests 库

#!/bin/python

import requests

url = 'http://example.my.com/'

num = 0
while num < 5:
headers={"Connection":"close"} # 开启短连接
r = requests.get(url,headers = headers)
print(r.text)
num +=1

(2)httplib2 库

#!/usr/bin/env python
import httplib2
http = httplib2.Http()
url = 'http://example.my.com/'

num = 0
while num < 5:
loginHeaders={
'User-Agent': 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.0 Chrome/30.0.1599.101 Safari/537.36',
'Connection': 'close'# 开启短连接
}
response, content = http.request(url, 'GET', headers=loginHeaders)
print(response)
print(content)
num +=1

(3)urllib2 库

#!/bin/python

import urllib2
import cookielib

httpHandler = urllib2.HTTPHandler(debuglevel=1)
httpsHandler = urllib2.HTTPSHandler(debuglevel=1)
opener = urllib2.build_opener(httpHandler, httpsHandler)
urllib2.install_opener(opener)

loginHeaders={
'User-Agent': 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Maxthon/4.0 Chrome/30.0.1599.101 Safari/537.36',
'Connection': 'close' # 开启短连接
}

num = 0
while num < 5:
request=urllib2.Request('http://example.my.com/',headers=loginHeaders)
response = urllib2.urlopen(request)
page=''
page= response.read()
print response.info()
print page
num +=1

Python 测试三种库都是支持 nscd 的 DNS 缓存的(推测底层也是调用 getaddrinfo 函数),以上测试时使用 HTTP 短连接,都在 python2 环境测试。

总结

针对 HTTP 客户端来说,可以优先开启 HTTP 的 keep-alive 模式,可以复用 TCP 连接,这样可以减少 TCP 握手耗时和重复请求域名解析,然后再开启 nscd 缓存,除了 Go 外,C/C++、Java、Python 都可支持 DNS 缓存,减少 DNS查询耗时。

这里只分析了常用 C/C++、Java、Go、Python 语言,欢迎熟悉其他语言的小伙伴补充。

2. Unix/类 Unix 系统常用 dns 缓存服务:

在由于某些特殊原因,自研或非自研客户端本身无法提供 DNS 缓存支持的情况下,建议管理人员在其所在系统环境中部署DNS缓存程序;

现介绍 Unix/类 Unix 系统适用的几款常见轻量级 DNS 缓存程序。而多数桌面操作系统如 Windows、MacOS 和几乎所有 Web 浏览器均自带 DNS 缓存功能,本文不再赘述。

P.S. DNS 缓存服务请务必确保随系统开机启动;

nscd

name service cache daemon 即装即用,通常为 linux 系统默认安装,相关介绍可参考其 manpage:man nscdman nscd.conf

(1)安装方法:通过系统自带软件包管理程序安装,如 yum install nscd

(2)缓存管理(清除):

1.service nscd restart 重启服务清除所有缓存;

2.nscd -i hosts 清除 hosts 表中的域名缓存(hosts 为域名缓存使用的 table 名称,nscd 有多个缓存 table,可参考程序相关 manpage)

dnsmasq

较为轻量,可选择其作为 nscd 替代,通常需单独安装

(1)安装方法:通过系统自带软件包管理程序安装,如 yum install dnsmasq

(2)核心文件介绍(基于 Dnsmasq version 2.86,较低版本略有差异,请参考对应版本文档如 manpage 等)

(3)/etc/default/dnsmasq 提供六个变量定义以支持六种控制类功能

(4)/etc/dnsmasq.d/ 此目录含 README 文件,可参考;目录内可以存放自定义配置文件

(5)/etc/dnsmasq.conf 主配置文件,如仅配置 dnsmasq 作为缓存程序,可参考以下配置

listen-address=127.0.0.1#程序监听地址,务必指定本机内网或回环地址,避免暴露到公网环境
port=53 #监听端口
resolv-file=/etc/dnsmasq.d/resolv.conf#配置dnsmasq向自定义文件内的 nameserver 转发 dns 解析请求
cache-size=150#缓存记录条数,默认 150 条,可按需调整、适当增大
no-negcache #不缓存解析失败的记录,主要是 NXDOMAIN,即域名不存在
log-queries=extra #开启日志记录,指定“=extra”则记录更详细信息,可仅在问题排查时开启,平时关闭
log-facility=/var/log/dnsmasq.log #指定日志文件

#同时需要将本机 /etc/resolv.conf 第一个 nameserver 指定为上述监听地址,这样本机系统的 dns 查询请求才会通过 dnsmasq 代为转发并缓存响应结果。
#另 /etc/resolv.conf 务必额外配置 2 个 nameserver,以便 dnsmasq 服务异常时支持系统自动重试,注意 resolv.conf 仅读取前 3 个 nameserver

(6)缓存管理(清除):

1.kill -s HUP `pidof dnsmasq` 推荐方式,无需重启服务

2.kill -s TERM `pidof dnsmasq` 或 service dnsmasq stop

3.service dnsmasq force-reload 或 service dnsmasq restart

(7)官方文档:https://thekelleys.org.uk/dnsmasq/doc.html

3. 纯内网业务取消查询域名的AAAA记录的请求

以 linux 操作系统为例,常用的网络请求命令行工具常常通过调用 getaddrinfo() 完成域名解析过程,如 ping、telnet、curl、wget 等,但其可能出于通用性的考虑,均被设计为对同一个域名每次解析会发起两个请求,分别查询域名 A 记录(即 IPV4 地址)和 AAAA 记录(即 IPV6 地址)。

因目前大部分公司的内网环境及云上内网环境还未使用 ipv6 网络,故通常 DNS 系统不为内网域名添加 AAAA 记录,徒劳请求域名的 AAAA 记录会造成前端应用和后端 DNS 服务不必要的资源开销。因此,仅需请求内网域名的业务,如决定自研客户端,建议开发人员视实际情况,可将其设计为仅请求内网域名 A 记录,尤其当因故无法实施本地缓存机制时。

4. 规范域名处理逻辑

客户端需严格规范域名/主机名的处理逻辑,避免产生大量对不存在域名的解析请求(确保域名从权威渠道获取,避免故意或意外使用随机构造的域名、主机名),因此类请求的返回结果(NXDOMAIN)通常不被缓存或缓存时长较短,且会触发客户端重试,对后端 DNS 系统造成一定影响。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer