Files
workflow/docs/about-dns.md
2024-03-12 22:11:08 +08:00

6.0 KiB
Raw Blame History

关于DNS

当使用域名请求网络时首先需要通过域名解析获取服务器地址再使用网络地址进行后续的请求。Workflow已经实现了完备的域名解析和缓存系统通常来说用户无需知晓内部机制即可流畅地发起网络任务。

DNS相关配置

Workflow中的全局配置包括

struct WFGlobalSettings
{
    struct EndpointParams endpoint_params;
    struct EndpointParams dns_server_params;
    unsigned int dns_ttl_default;
    unsigned int dns_ttl_min;
    int dns_threads;
    int poller_threads;
    int handler_threads;
    int compute_threads;
    int fio_max_events;
    const char *resolv_conf_path;
    const char *hosts_path;
};

其中与域名解析相关的配置项有

  • dns_server_params
    • address_family: 该项会在后续展开说明
    • max_connections: 向DNS服务器发送请求的最大并发数默认为200
    • connect_timeout/response_timeout/ssl_connect_timeout: 参考超时相关说明
  • dns_threads: 当使用同步方式实现域名解析时解析操作会在独立的线程池中执行该项指定线程池的线程数默认为4
  • dns_ttl_default: 域名解析成功的结果会被放到域名缓存中该项指定其存活时间单位为秒默认值1小时当解析结果过期后会重新解析以获取最新内容
  • dns_ttl_min: 当通信失败时有可能出现缓存的结果已经失效的情况该项指定一个较短的存活时间当通信失败时以更频繁的速率更新缓存单位为秒默认值1分钟
  • resolv_conf_path: 该文件保存了访问DNS相关的配置在常见的Linux发行版上通常位于/etc/resolv.conf,若该项配置为NULL则表示使用多线程同步解析的模式
  • hosts_path: 该文件是一个本地的域名查找表若被解析的域名命中该表则不会向DNS发起请求在常见的Linux发行版上通常位于/etc/hosts,若该项配置为NULL则表示不使用查找表

resolv.conf扩展功能

Workflow对resolv.conf配置文件进行了扩展,用户可以通过修改配置以支持DNS over TLS(DoT)功能,注意直接修改/etc/resolv.conf会影响其他进程可以将该文件复制一份用于修改并将Workflow的resolv_conf_path配置修改为新文件的路径。例如使用dnss协议的nameserver会通过SSL进行连接

nameserver dnss://8.8.8.8/
nameserver dnss://[2001:4860:4860::8888]/

Address Family

在某些网络环境下虽然本机支持IPv6但因未被分配公网IPv6地址而无法与外部通信例如本地IPv6地址以fe80开始)。此时可以将endpoint_params.address_family设置为AF_INET来强制域名解析时仅解析IPv4地址。同样的resolv.conf文件中可能同时指定了nameserver的IPv4地址和IPv6地址此时可以将dns_server_params.address_family设置为AF_INETAF_INET6来强制仅使用IPv4或IPv6地址来访问DNS。

使用Upstream配置

全局配置默认对每个域名生效,若需要对某些域名单独指定不同的配置,则可使用Upstream功能。使用Upstream可以单独指定dns_ttl_defaultdns_ttl_min配置项,以及通过endpoint_params.address_family单独指定该域名使用的IP地址类别。

域名解析与缓存策略

网络任务通常需要通过域名解析获取到需要访问的IP地址Workflow中域名解析相关策略如下

  1. 检查域名缓存是否有该域名对应的IP地址若有缓存且未过期则使用该组IP地址
  2. 检查域名是否为IPv4、IPv6地址或Unix Domain Socket,若是则直接使用该地址,无需发起域名解析
  3. 检查hosts_path文件中是否包含该域名对应的IP地址若有则直接使用该地址
  4. 获取异步锁保证同一域名的解析请求在同一时刻仅发起一次并向DNS发起解析请求
  5. 解析成功后会将解析结果保存到当前进程的域名缓存中,以供下次使用,并释放异步锁
  6. 解析失败后会释放异步锁且将失败原因通知给等在同一个异步锁上的所有任务通知结束后再发起的新的任务则会再次请求DNS

许多需要大量发起网络请求的场景都会配备域名缓存组件如果每次发起网络任务时都向DNS发起解析请求则DNS必然会不堪重负。Workflow设置了缓存存活时长dns_ttl_default和dns_ttl_min来保证缓存会在合理的时间后过期以及时更新域名的解析结果。当某个域名的缓存项过期后首先发现过期的任务会将其存活时间延长5秒并向DNS发起解析请求5秒内同一域名上的请求会直接使用缓存的DNS解析结果而无需等待本次解析结束。

异步锁机制可以保证同一域名的解析请求在同一时刻仅发起一次在没有锁保护的情况下若短时间内对同一域名发起大量网络任务每个任务都会因无法从缓存中获取结果而向DNS发起解析请求这会对DNS带来很大且不必要的负担。这里的同一域名表示的是(host, port, family)三元组若通过Upstream的方式对某域名分别要求只使用IPv4和IPv6则他们会被不同的异步锁保护也就有可能同时发起DNS请求。

异步域名解析

Workflow实现了完备的DNS任务参考dns_cli),若指定了resolv_conf_path配置项则向DNS发起域名解析时会使用异步请求的方式进行在类Unix系统下Workflow默认使用/etc/resolv.conf作为该配置的值。异步域名解析不会阻塞任何线程,也不会独占线程池,可以更高效地完成域名解析的任务。

同步域名解析

若指定resolv_conf_pathNULL,则会通过调用getaddrinfo函数来实现同步域名解析,该方式会使用独立的线程池,其线程数通过dns_threads参数配置。若短时间内需要发起较多的域名解析请求,则同步的方式会带来较大的延迟。