Nginx怎么做域名解析?怎么在你自己开发的模块里面使用Nginx提供的方法解析域名?它内部实现是什么样的?
本文以Nginx 1.5.1为例 , 从nginx_mail_smtp模块如何进行域名解析出发 , 分析Nginx进行域名解析的过程 。为了简化流程 , 突出重点 , 在示例代码中省掉了一些异常部分的处理 , 比如内存分配失败等 。
文章插图
DNS查询分为两种:根据域名查询地址和根据地址查询域名 , 在代码结构上这两种方式非常相似 , 这里只介绍根据域名查询地址这一种方式 。本文将从以下几个方面进行介绍:
- 域名查询的函数接口介绍
- 域名解析流程分析
- 查询场景分析及实现介绍
在使用同步IO的情况下 , 调用gethostbyname()或者gethostbyname_r()就可以根据域名查询到对应的IP地址, 但因为可能会通过网络进行远程查询 , 所以需要的时间比较长 。
文章插图
为了不阻塞当前线程 , Nginx采用了异步的方式进行域名查询 。整个查询过程主要分为三个步骤 , 这点在各种异步处理时都是一样的:
- 准备函数调用需要的信息 , 并设置回调方法
- 调用函数
- 处理结束后回调方法被调用
下面先从调用者的角度对每个步骤做详细的分析:
- 初始化域名查询所需要的的全局信息
- 需要初始化的全局信息包括:
- 因为resolver是全局的 , 与任何一个connection都无关 , 所有需要放在一个随时都可以取到的地方 , 如 ngx_mail_core_srv_conf_t结构体上 , 在使用时从当前session找到ngx_mail_core_srv_conf_t , 然后找到resolver 。
- DNS 服务器的信息需要在配置文件中明确指出 , 比如
- 下面根据配置中的resolver参数 , 初始化全局的ngx_resolver_t , 其中保存了前面提及的DNS服务器地址和查询结果等信息:
- DNS 服务器的地址 , 如果指定了多个服务器 , nginx会采用Round Robin的方式轮流查询每个服务器
- 对查询结果的缓存 , 采用Red Black Tree的数据结构 , 以要查询名字的Hash作为Key, 节点信息存放在 struct ngx_resolver_node_t中 。
- 准备本次查询的信息
- 和本次查询相关的信息放在ngx_resolver_ctx_t结构体中 , 包括要查询的名称 , 查询完的回调方法 , 以及超时时间等 。如果本次要查询的地址已经是IPv4用点分隔的地址了 , 比如74.125.128.100, nginx会在ngx_resolve_start中进行判断 , 并设置好标志位 , 在调用ngx_resolve_name时不会发送真正的DNS查询请求 。
- 根据名字进行IP地址查询
- 前面方法的最后通过ngx_resolve_name方法进行IP地址查询 。查询时 , Nginx会先检查本地缓存 , 如果在缓存中 , 就更新缓存过期时间 , 并回调设置的handler, 如前面设置的:ngx_mail_smtp_resolve_name_handler , 然后整个查询过程结束 。如果没有在缓存中就发送查询请求给dns server , 同时方法返回 。
推荐阅读
- Linux安装Nginx
- 20万以下汽车做保养,修理厂为什么不建议,使用全合成机油呢
- 搭建nginx+tomcat+Java的负载均衡环境
- 对巡回指导组的建议 巡回检查组是在青岛拍的吗
- 对程序员的20建议
- nginx反向代理IIS出现response header返回Locaiton问题
- 一文掌握ORACLE DBMS_ROWID包用法,值得收藏
- nginx实现动静分离实战
- Nginx 搭建图片服务器
- 角质层薄用什么洗面奶,建议采用温和型的