【libcurl】使用c-ares 异步DNS解析库的客户端如何处理所在主机的DNS变更?

libcurl 是一个很强大的开源网络处理库,主要功能就是用不同的协议连接和沟通不同的服务器。
目前支持 http、https、ftp、gopher、telnet、dict、file 和 ldap 等协议。
libcurl 同样支持 HTTPS 证书授权,HTTP POST、HTTP PUT、FTP 上传,HTTP 基本表单上传、代理、cookies 和用户认证等功能。Google Chrome 内核就用到了 libcurl 库。

image.png

c-ares是一个C语言实现的DNS非阻塞异步解析库,libcurl、 libevent、 gevent,、nodejs和 wireshark都使用了c-ares,因此在一般开发一些服务的客户端Client,在连接服务器Server时,需要做的工作的就是域名解析。

客户端使用c-ares作为DNS解析库,但是当电脑DN地址发生变更时客户端并没有感知到,依然使用变更前的DNS地址做目标域名的解析,会是什么原因?

可能是因为c-ares库缓存了之前的DNS解析结果,导致客户端仍然使用旧的DNS地址进行解析。
c-ares库会在解析DNS时使用缓存来提高解析速度,并且缓存的生命周期是有限的。
如果缓存的生命周期还没有结束,c-ares库就会使用缓存中的DNS地址进行解析。
可以尝试清除c-ares的缓存或者重新初始化c-ares库来解决这个问题。
另外,建议客户端定期更新DNS缓存或者使用DNS服务器提供的TTL机制来自动更新DNS缓存。

如何解决这个问题?

解决这个问题的方法有以下几种:

  1. 在使用c-ares的代码中添加对DNS地址变更的监听,当检测到DNS地址变更时,清空c-ares的缓存,并重新初始化c-ares。这样可以确保c-ares使用最新的DNS地址进行解析。

  2. 在客户端的网络配置中正确设置DNS地址,确保DNS地址变更后客户端可以正确地使用新的DNS地址进行解析。

  3. 客户端可以定期检查DNS地址是否发生变更,如果发生变更,则清空c-ares的缓存,并重新初始化c-ares。这样可以确保c-ares使用最新的DNS地址进行解析。

  4. 如果客户端无法及时获取DNS地址变更的通知,则可以在客户端代码中添加定时器,定期检查DNS地址是否发生变更,并更新c-ares的DNS地址。

通过上述方法,可以确保c-ares能够正确地使用最新的DNS地址进行解析,避免出现DNS解析错误的问题。

当电脑DNS地址发生变更时,客户端并没有感知到依然使用变更前的DNS地址做目标域名的解析,超时时间是多少?

c-ares库的DNS解析超时时间是可以配置的,一般默认为5秒。
如果在这个超时时间内没有收到DNS响应,c-ares库会返回一个错误码,表示DNS解析失败。
如果客户端依然使用旧的DNS地址进行解析,那么解析会一直等待,直到超时时间到达。
在超时时间内,如果DNS服务器没有响应,客户端会一直等待,直到超时时间到达。
如果超时时间到达,c-ares库会返回一个错误码,表示DNS解析失败。
在实际使用中,为了避免DNS解析错误和超时错误,可以通过调整超时时间和优化DNS解析缓存等方式来提高解析效率和可靠性。

为什么在mac电脑上超时时间高达30秒?

c-ares库的DNS解析超时时间是可以通过参数进行配置的,一般默认为5秒。
但是在macOS系统上,由于系统的默认DNS解析超时时间为30秒,因此c-ares库也会继承这个超时时间。
如果需要修改c-ares库的DNS解析超时时间,可以通过设置CARES_TIMEOUTMS_DEFAULT宏定义来修改默认的超时时间。
例如,将超时时间设置为10秒,可以在编译时添加如下宏定义:

-D CARES_TIMEOUTMS_DEFAULT=10000

这样就可以将c-ares库的默认DNS解析超时时间修改为10秒。

使用c-ares的客户端,当所在电脑主DNS挂了,多久会切到从DNS做解析?

使用c-ares的客户端在解析域名时,会按照操作系统的DNS解析规则进行解析。
一般情况下,操作系统会先尝试使用主DNS服务器进行解析,如果主DNS服务器无法响应或者响应超时,则会尝试使用备用DNS服务器进行解析。
在Windows系统中,DNS解析的默认超时时间为2秒,如果在这个时间内无法获得响应,则会尝试使用备用DNS服务器进行解析。
在Linux系统中,DNS解析的默认超时时间为5秒,如果在这个时间内无法获得响应,则会尝试使用备用DNS服务器进行解析。
因此,当主DNS服务器挂掉时,客户端会在一定的超时时间后尝试使用备用DNS服务器进行解析。
如果备用DNS服务器也无法响应,则会继续尝试其他备用DNS服务器,直到获得响应或者所有备用DNS服务器都无法响应为止。
在使用c-ares的客户端中,可以通过调整DNS解析超时时间和优化DNS解析缓存等方式来提高解析效率和可靠性。

用node内置dns模块,替代 libcurl 的c-ares 做DNS解析

你可以使用 Node.js 内置的 dns 模块来替代 libcurl 的 c-ares 库进行 DNS 解析。
Node.js 的 dns 模块提供了多个方法来进行 DNS 查询,包括 dns.lookup()dns.resolve()dns.reverse() 等,可以满足大部分的 DNS 解析需求。

与 c-ares 不同,Node.js 的 dns 模块是基于系统的 DNS 解析机制实现的,因此可以直接使用系统的 DNS 缓存和 DNS 配置,无需单独管理 DNS 缓存和 DNS 配置。同时,Node.js 的 dns 模块也支持异步查询和回调函数,可以满足高并发的网络请求需求。

以下是一个使用 Node.js dns 模块进行 DNS 解析的示例代码:

const dns = require('dns');

// 解析域名为 IP 地址
dns.lookup('www.example.com', (err, address, family) => {
  if (err) throw err;
  console.log(`IP 地址: ${address}`);
});

// 解析域名为 IPv4 地址
dns.resolve4('www.example.com', (err, addresses) => {
  if (err) throw err;
  console.log(`IPv4 地址: ${JSON.stringify(addresses)}`);
});

// 解析域名为 IPv6 地址
dns.resolve6('www.example.com', (err, addresses) => {
  if (err) throw err;
  console.log(`IPv6 地址: ${JSON.stringify(addresses)}`);
});

// 查询邮件交换器记录
dns.resolveMx('example.com', (err, records) => {
  if (err) throw err;
  console.log(`MX 记录: ${JSON.stringify(records)}`);
});

// 解析 IP 地址为域名
dns.reverse('8.8.8.8', (err, hostnames) => {
  if (err) throw err;
  console.log(`域名: ${JSON.stringify(hostnames)}`);
});

需要注意的是,Node.js dns 模块的查询结果可能与 c-ares 的查询结果不完全相同,因为它们使用的 DNS 解析机制不同。
如果需要完全替代 c-ares 进行 DNS 解析,可以使用第三方的 DNS 解析库,例如 dns.jsnative-dns 等。

参考

curl
https://curl.haxx.se

libcurl
https://curl.haxx.se/libcurl

libcurl官方教程
https://curl.haxx.se/libcurl/c/libcurl-tutorial.html

libcurl 使用教程
https://getiot.tech/zh/awesome/awesome-c/libcurl

curl的25年之旅(译)
https://juejin.cn/post/7238804998276137020

为什么我们经常遇到curl域名解析超时?
https://toutiao.io/posts/sevo1kc/preview

c-ares 一个C语言的异步DNS解析库
http://wangxuemin.github.io/2015/07/31/c-ares%20%E4%B8%80%E4%B8%AAC%E8%AF%AD%E8%A8%80%E7%9A%84%E5%BC%82%E6%AD%A5DNS%E8%A7%A3%E6%9E%90%E5%BA%93/

CURLOPT_DNS_CACHE_TIMEOUT explained
https://curl.se/libcurl/c/CURLOPT_DNS_CACHE_TIMEOUT.html

你可能感兴趣的:(【libcurl】使用c-ares 异步DNS解析库的客户端如何处理所在主机的DNS变更?)