查询完成后回调在ngx_resolver_ctx_t中指定的方法 真正的DNS查询完成后 , 不管成功 , 失败或是超时 , nginx会回调相应查询的handler, 如前面设置的:ngx_mail_smtp_resolve_name_handler 。在handler中都需要调用ngx_resolve_addr_done来标识查询结束 。static voidngx_mail_smtp_resolve_name_handler(ngx_resolver_ctx_t *ctx){ in_addr_t addr; ngx_uint_t i; ngx_connection_t *c; struct sockaddr_in *sin; ngx_mail_session_t *s;s = ctx->data; c = s->connection;if (ctx->state) { ngx_log_error(NGX_LOG_ERR, c->log, 0, ""%V" could not be resolved (%i: %s)", &ctx->name, ctx->state, ngx_resolver_strerror(ctx->state)); } else { /* AF_INET only */ sin = (struct sockaddr_in *) c->sockaddr;for (i = 0; i < ctx->naddrs; i++) { addr = ctx->addrs[i];ngx_log_debug4(NGX_LOG_DEBUG_MAIL, c->log, 0, "name was resolved to %ud.%ud.%ud.%ud", (ntohl(addr) >> 24) & 0xff, (ntohl(addr) >> 16) & 0xff, (ntohl(addr) >> 8) & 0xff, ntohl(addr) & 0xff);if (addr == sin->sin_addr.s_addr) { goto found; } }s->host = smtp_unavailable; } found: //不管成功失败都要执行 ngx_resolve_name_done(ctx);}二、域名解析流程分析

文章插图
通过Nginx进行域名查询的流程图如下 , 颜色越深花费的时间越长 。调用过程分为三种:
- 首先判断是不是IPv4地址 , 如果是就直接调用Handler
- 再次检查是不是在缓存中 , 如果有 , 就调用Handler
- 最后发送远程DNS请求 , 收到回复后调用Handler
三、查询场景分析及实现介绍
查询的地址是IP v4地址
比如74.125.128.100, nginx会在ngx_resolve_start中通过ngx_inet_addr方法进行判断 , 如果是IPv4的地址 , 就设置好标志位 ngx_resolver_ctx_t->quick , 在接下来的ngx_resolve_name中会对这个标志位进行判断 , 如果为1 , 就直接调用ngx_resolver_ctx_t->handler
ngx_resolver_ctx_t *ngx_resolve_start(ngx_resolver_t *r, ngx_resolver_ctx_t *temp){ in_addr_t addr; ngx_resolver_ctx_t *ctx;if (temp) { addr = ngx_inet_addr(temp->name.data, temp->name.len);if (addr != INADDR_NONE) { temp->resolver = r; temp->state = NGX_OK; temp->naddrs = 1; temp->addrs = &temp->addr; temp->addr = addr; temp->quick = 1;return temp; } } ...}
- 超时没有得到查询结果
- 调用ngx_resolve_name时设置的回调方法被调用 , 同时ngx_resolver_ctx_t->state被设置为NGX_RESOLVE_TIMEDOUT 。相应的代码为:
static voidngx_resolver_timeout_handler(ngx_event_t *ev){ ngx_resolver_ctx_t *ctx; ctx = ev->data; ctx->state = NGX_RESOLVE_TIMEDOUT; ctx->handler(ctx);}
- 正常查询一个不在缓存中的域名
- 如果要查询的域名不在缓存中 , 首先把域名按hash值放在缓存中 , 然后准备查询需要的数据 , 发送DNS查询的UDP请求给DNS服务器 ,
static ngx_int_tngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx){ ngx_resolver_node_t *rn; rn = ngx_resolver_alloc(r, sizeof(ngx_resolver_node_t)); ngx_rbtree_insert(&r->name_rbtree, &rn->node); ngx_resolver_create_name_query(rn, ctx); ngx_resolver_send_query(r, rn);rn->cnlen = 0; rn->naddrs = 0; rn->valid = 0; rn->waiting = ctx;ctx->state = NGX_AGAIN;} //收到DNS查询结果后的回调方法static voidngx_resolver_read_response(ngx_event_t *rev){ ssize_t n; ngx_connection_t *c; u_char buf[NGX_RESOLVER_UDP_SIZE]; c = rev->data;do { n = ngx_udp_recv(c, buf, NGX_RESOLVER_UDP_SIZE); if (n < 0) { return; }ngx_resolver_process_response(c->data, buf, n); } while (rev->ready);} static voidngx_resolver_process_a(ngx_resolver_t *r, u_char *buf, size_t last, ngx_uint_t ident, ngx_uint_t code, ngx_uint_t nan, ngx_uint_t ans){ hash = ngx_crc32_short(name.data, name.len); rn = ngx_resolver_lookup_name(r, &name, hash);//copy addresses to cached node rn->u.addrs = addrs;//回调所有等待本域名解析的请求 next = rn->waiting; rn->waiting = NULL;while (next) { ctx = next; ctx->state = NGX_OK; ctx->naddrs = naddrs; ctx->addrs = (naddrs == 1) ? &ctx->addr : addrs; ctx->addr = addr; next = ctx->next;ctx->handler(ctx); }}
- 对同一域名查询多次查询
- 如果多次查询时 , 之前的查询结果还在缓存中并且没有失效 , 就直接从缓存中取到查询结果 , 并调用设置的回调方法 。
static ngx_int_tngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx){ uint32_t hash; in_addr_t addr, *addrs; ngx_uint_t naddrs; ngx_resolver_ctx_t *next; ngx_resolver_node_t *rn;hash = ngx_crc32_short(ctx->name.data, ctx->name.len); rn = ngx_resolver_lookup_name(r, &ctx->name, hash);if (rn) { if (rn->valid >= ngx_time()) { naddrs = rn->naddrs;if (naddrs) { ctx->next = rn->waiting; rn->waiting = NULL;do { ctx->state = NGX_OK; ctx->naddrs = naddrs; ctx->addrs = (naddrs == 1) ? &ctx->addr : addrs; ctx->addr = addr; next = ctx->next;ctx->handler(ctx);ctx = next; } while (ctx);return NGX_OK; } } }}
推荐阅读
-
-
云南将建新高铁,全长107公里,共设5个站点,经过你的家乡吗
-
好事儿娇娘|为了延续儿子的性命,在佛前叩首三千回,民间故事:初为人母
-
Techweb■2015 年至 2019 年全球人工智能投资报告:美国公司吸走了 56%
-
肌酐升高时,人体会出现哪些症状?肌酐386中医治疗降为正常值
-
[Andy无泪]商家不给你拿柜台上的,而是去仓库拿货?,为什么去实体店买电脑
-
猫眼娱乐V|呼吸困难送医院,当妈心切称想生4个?曝郭富城旧爱冻卵后太操劳
-
-
血管 让血管一通到底的食物是它们,记得每天吃1种,清除血管垃圾毒素
-
临安检察:商版《庆渝年》之抢“传国玉玺”有没有用?
-
公路施工标准化测量钢筋直螺纹套筒连接工艺及质量检查
-
-
-
-
-
-
游戏提莫酱|IVL秋季赛:Weibo迎战MRC,梦之女巫或成为胜负手
-
-
『石军帅说娱乐』才艺表演唱了歌,打赏礼物的却寥寥无几,胡海泉直播试水不太成功
-
摄影师|奇闻:新郎拍婚纱照只拍到两只脚,新娘不满意,看成片服了