查询完成后回调在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; } } }}
推荐阅读
-
心脑血管|高血压不能吃的食物你知道吗?千万不要再吃错了
-
减肥|不用再节食吃药减肥了,52岁的我用这种方法从132斤减到103斤
-
AG|英媒关注“鲲龙”AG600海上首飞:未来或用于海上监视及后勤补给
-
:女子给弟弟买婚房,装修好了才知不是自己家:原房主卖错房子了!
-
「育儿小手册」鲁班没吸血铭文被瞬秒,他有蓝就行!,单挑龙王不掉血的英雄
-
环球车讯网|这车三大件有保障,比途岳还亲民,被称是德系“小坦克”
-
-
-
张柏芝|要拼四胎?张柏芝玩特效预测明年会有孩子,表情惊喜评论一片祝福
-
响尾蛇|世界上最快的蛇有多快?人能不能比它跑得快?
-
-
-
『基层』应对气候变化四川出台基层生态环境部门应对工作指南
-
家常培根炸薯饼,比薯片好吃,外酥里嫩超入味,美味的早餐零食
-
劳森|10中5半场25+6+5!五画面回放,劳森到底有多“无解”
-
奔驰2022年七大工厂生产8款EQ车型,将在华国产4款
-
IT之家5G手机首销:8分钟销量破10万台,1899元起,荣耀X10
-
木木不哭助手|西卡疑似被“LPL除名”!LPL电竞史查无西卡这个人
-
「情人」不管是夫妻还是情人,一旦把这些话挂在嘴边,那么感情就走到了头
-