core/ngx_resolver.h头文件分析
本章我们主要介绍一下ngx_resolver.h头文件,其主要是实现对nginx中涉及到的域名的解析。
1. 相关宏定义
2. ngx_resolver_connection_t数据结构
本数据结构用于表示resolver实例与DNS服务器的一条连接。下面简单介绍一下各字段的含义:
-
udp: 代表resolver与DNS服务器的udp连接
-
tcp: 代表resolver与DNS服务器的tcp连接
-
sockaddr: 存放DNS服务器的IP地址
-
socklen: DNS服务器IP地址的长度
-
server: DNS服务器IP地址的字符串表示形式
-
log: 与当前connection关联的日志对象
-
read_buf: 当前connection的读取缓冲(用于TCP)
-
write_buf: 当前connection的写缓冲(用于TCP)
-
resolver: 当前connection对象所属的resolver
2. ngx_resolver_srv_t数据结构
在进行NGX_RESOLVE_SRV
查询时,返回目标服务器的相关信息。下面简要介绍一下各字段的含义(rfc2782):
-
name: 目标服务器的域名信息
-
priority: 优先级。一般值越低,优先级越高
-
weight: 目标服务器所占用的权重
-
port: 该不服务在目标服务器上所占用的端口
3. ngx_resolver_srv_name_t数据结构
本数据结构用于表示某一个域名(name)下所指定的服务的IP地址,用于服务查询。下面我们简要介绍一下各字段的含义:
-
name: 服务对应的域名
-
priority: 服务在
name
域名下的优先级 -
weight: 权重
-
port: 对应的端口
-
ctx: 所关联的ngx_resolver_ctx_t上下文
-
naddrs: ip地址个数
-
addrs: 所返回的IP地址
4. ngx_resolver_node_t数据结构
下面简要介绍一下各字段的含义:
-
node: 作为红黑树的一个节点存在,将
ngx_resolver_node_t
数据结构作为红黑树的一个节点来进行管理 -
queue: 作为一个辅助元素,用于实现ngx_resolver_t中的超时队列。
-
name: 当执行的是DNS
A
类型查询时,本字段保存的是需要解析的域名; 当执行的是DNSPTR
类型的查询时,本字段保存的是逆解析后得到的域名 -
nlen: 用于指明
name
的长度 -
qlen: 用于指明
query
的长度 -
query: 用于存放当前DNS的查询请求报文
-
query6: 用于存放当前DNS的查询请求报文(适用于IPv6, 当前我们并不支持
NGX_HAVE_INET6
宏定义) -
u: 用于保存当前DNS查询到的地址信息(IPv4)。
-
naddrs: 用于指明当前解析到的
u.addrs
的个数。 -1表示未开始解析,或解析出错。 -
nsrvs: 用于指明当前解析大的
u.srvs
的个数。 -1表示未开始解析,或解析出错 -
cnlen: 用于指明u.cname的长度
-
u6: 用于保存当前DNS查询到的地址信息(IPv6)
-
naddrs6:当前DNS解析到的IPv6地址信息的个数。 -1表示未开始解析,或解析出错
-
expire: 用于指示当前节点的过期
时刻
,主要是用于控制超时队列使用,适时的淘汰ngx_resolver_t
中name_rbtree
、srv_rbtree
或addr_rbtree
中的节点,对应的超时队列分别是ngx_resolver_t中的name_expire_queue、srv_expire_queue或addr_expire_queue; -
valid: 用于指示当前节点的有效期
时刻
。注意: 本字段含义上与expire相似,但expire主要用于控制超时队列。 -
ttl: 用于保存DNS返回的TTL时间
-
last_connection: 用于表示适用resolver连接数组中的哪一个连接(这里采用round-robin算法)
-
waiting: 用于指示当前节点所对应的ngx_resolver_ctx_t类型的等待链表
5. ngx_resolver_t数据结构
ngx_resolver_t数据结构用于表示nginx中的一个DNS解析器。下面简单介绍一下各字段的含义:
-
event: 与当前resolver关联的event, 一般作为定时事件来执行resend_queue中相应的任务
-
log: 与当前resolver关联的日志对象
-
connections: 是一个
ngx_resolver_connection_t
类型的数组,数组的每一个元素代表与DNS的一条连接。这里涉及到两个方面,首先一个resolver可能对应多个不同域名(或IP)的DNS, 其次即使是同一个DNS域名,也可能对应多个IP地址, 因此这里需要用数组来保存。 -
last_connection:采用round-robin算法时,用于控制采用连接数组中的哪一个连接
-
name_rbtree: 用于保存从DNS查询到的
域名到IP地址的映射
的红黑树, -
name_sentinel: name_rbtree红黑树的叶子终节点
-
srv_rbtree: 用于保存从DNS查询到的
服务名到IP地址的映射
的红黑树(实际上,当前程序中并未有任何地方使用到此功能) -
srv_sentinel: srv_rbtree红黑树的叶子终节点
-
addr_rbtree: 用于保存从DNS逆查询得到的
IP地址到域名的映射
的红黑树。红黑树中的value是ngx_resolver_node_t
结构 -
addr_sentinel: addr_rbtree红黑树的叶子终节点
-
name_resend_queue:一般作为name查询服务类型ngx_resolver_node_t的waiting context所关联事件的
resend
队列 -
srv_resend_queue: 一般作为srv查询服务类型ngx_resolver_node_t的waiting context所关联事件的
resend
队列 -
addr_resend_queue: 一般作为addr查询服务类型ngx_resolver_node_t的waiting context所关联事件的
resend
队列 -
name_expire_queue: 用于控制name_rbtree中节点超时的队列
-
srv_expire_queue: 用于控制srv_rbtree中节点超时的队列
-
addr_expire_queue; 用于控制addr_rbtree中节点超时的队列
-
IPv6相关
#if (NGX_HAVE_INET6) ngx_uint_t ipv6; /* unsigned ipv6:1; */ ngx_rbtree_t addr6_rbtree; ngx_rbtree_node_t addr6_sentinel; ngx_queue_t addr6_resend_queue; ngx_queue_t addr6_expire_queue; #endif
在当前,我们暂未支持NGX_HAVE_INET6
这一宏定义。这里除了协议版本与ipv4不同外,字段含义与ipv4中对应字段均相同。
-
resend_timeout: 用于指示请求重发的超时时间
-
tcp_timeout: 代表与DNS服务连接的TCP超时时间
-
expire: 用于指示当前resolver缓存DNS解析结果的时间,这样就可以不需要每一次请求都去请求DNS
-
valid: 用于指明resolver的有效事件
注意: 上面介绍的DNS逆地址解析,一般只会在邮件模块用到
6. ngx_resolver_ctx_t数据结构
本数据结构用于表示resolver对象实例所关联的上下文对象。下面简单介绍一下各字段的含义:
-
next: 用于指示ngx_resolver_ctx_t链表中的下一个上下文对象;
-
resolver: 本上下文对象所关联的resolver(注意: 本身ngx_resolver_t并不直接与ctx关联,而是通过ngx_resolver_t中相应的节点来关联的)
-
node: 本上下文所关联的ngx_resolver_node_t数据结构。
-
state: 用于指示当前上下文对DNS域名解析,或DNS逆解析的状态
-
name: DNS
A
类型解析时保存的是将要解析的域名; DNSPTR
类型解析时,保存的是IP地址逆解析到的域名 -
service: 用于保存要解析的服务名称
-
valid: 当前context的有效期时间
-
addr: 当前需要进行DNS逆查询的IP地址(即IP地址到域名的映射)
-
count: 用于保存当前未处理完的srvs的个数。(srv表示将
服务名转换为IP地址
,有时可能不能直接转换,会先返回规范化的名称,然后我们需要再根据返回的规范化名称再去查询DNS,以返回IP地址。此处用于指明当前我们未处理的规范化名称个数) -
nsrvs: 当前ctx所要解析的
srvs
的个数 -
srvs: 当前ctx所要解析的
规范化服务名称
(canonical name) -
handler: 本context对象绑定的回调函数
-
data: 一般用于保存handler()回调函数的参数
-
timeout: 当前context的超时时间,主要用于event事件的超时管理
-
quick: 一般情况下,当我们并不需要调用DNS服务器进行解析时会将本字段设置为1,这时直接调用ngx_resolver_ctx_t的handler回调函数即可。
-
recursion: 因为DNS解析时可能会产生递归,这里用于记录递归的次数。超过了一定的次数之后,一般可以认为出现了问题,此时不应该继续查询DNS让递归一直进行下去了
下面我们给出nginx resolver各数据结构的一个整体图景:
[参看]