Analysis of Nginx DNS parsing process

Source: Internet
Author: User
Tags sin

How does nginx do domain name resolution? How to use the method provided by Nginx to parse the domain name in the module that you develop yourself? What is the internal implementation of it?

This paper takes Nginx 1.5.1 as an example to analyze the process of the domain name resolution of Nginx from the NGINX_MAIL_SMTP module. In order to simplify the process and focus, the exception is omitted in the sample code, such as memory allocation failure. There are two types of DNS queries: query addresses based on domain names and query domain names based on addresses, which are very similar in code structure, and only the way to find addresses based on domain names. This article will be described in the following ways:

Introduction to the function interface of domain name query

Analysis of domain name parsing process

Query scenario analysis and implementation Introduction

First, the Domain Name Query function interface Introduction

In the case of synchronous IO, calling gethostbyname () or Gethostbyname_r () can be used to query the corresponding IP address based on the domain name, but it takes a long time because it may be queried remotely over the network.

In order not to block the current thread, Nginx uses the asynchronous way to query the domain name. The entire query process is divided into three main steps, which are the same in various asynchronous processing:

Prepares the information needed for a function call and sets the callback method

Calling functions

Callback method is called after processing ends

In addition, in order to minimize the time spent on queries, Nginx also made a local cache of query results. To initialize information such as DNS server addresses and local caches, you need to do some global initialization before you can actually query.

The following is a detailed analysis of each step from the caller's point of view:

The global information required to initialize the domain name query

The global information that needs to be initialized includes:

DNS server address, if you specify a number of servers, Nginx will use round robin in turn to query each server

The query results are cached using red Black tree's data structure, and the node information is stored in the struct ngx_resolver_node_t in order to query the hash of the name as key.

Because resolver is global, it has nothing to do with any of the connection, all need to be placed in a place that can be taken at any time, such as the ngx_mail_core_srv_conf_t structure, from the current session when used to find Ngx_mail_ core_srv_conf_t, and then find Resolver.

The DNS server information needs to be explicitly stated in the configuration file, such as

1

2

3

4

5

6

#nginx. conf

Resolver 8.8.8.8

#nginx is cached by default based on the TTL value in the DNS request result.

#当然也可以通过一个可选的参数valid来设置过期时间, such as:

#resolver 127.0.0.1 [:: 1]:5353 valid=30s;

The global ngx_resolver_t is initialized according to the resolver parameter in the configuration, which holds information such as the previously mentioned DNS server address and query results:

01

02

03

04

05

06

07

08

09

10

11

Static char *

Ngx_mail_core_resolver (ngx_conf_t *cf, ngx_command_t *cmd, void *conf)

{

ngx_mail_core_srv_conf_t *CSCF = conf;

ngx_str_t *value;

Value = cf->args->elts;

Cscf->resolver = ngx_resolver_create (cf, &value[1],

CF->ARGS->NELTS-1);

return NGX_CONF_OK;

}

Prepare the information for this query

The information associated with this query is placed in the ngx_resolver_ctx_t structure, including the name to be queried, the callback method to be queried, and the time-out. If the address of this secondary query is already IPv4 with a point-delimited address, such as 74.125.128.100, Nginx will be in the Ngx_resolve_start judgment, and set a good flag bit, in the call Ngx_resolve_ Name does not send a true DNS query request

static void

Ngx_mail_smtp_resolve_name (ngx_event_t *rev)

{

Ngx_connection_t *c;

Ngx_mail_session_t *s;

ngx_resolver_ctx_t *ctx;

ngx_mail_core_srv_conf_t *CSCF;

c = rev->data;

s = c->data;

CSCF = ngx_mail_get_module_srv_conf (s, ngx_mail_core_module);

CTX = Ngx_resolve_start (Cscf->resolver, NULL);

if (CTX = = NULL) {

Ngx_mail_close_connection (c);

Return

}

Ctx->name = s->host;

Ctx->type = ngx_resolve_a;

Ctx->handler = Ngx_mail_smtp_resolve_name_handler;

Ctx->data = s;

Ctx->timeout = cscf->resolver_timeout;

IP address Query by name

if (Ngx_resolve_name (CTX) = NGX_OK) {

Ngx_mail_close_connection (c);


}

}

IP address Query by name

At the end of the preceding method, the IP address is queried by the Ngx_resolve_name method. Query, Nginx checks the local cache first, if in the cache, the cache expiration time is updated, and the callback setting handler, as previously set: Ngx_mail_smtp_resolve_name_handler, and then the entire query process is complete. If no query is sent to the DNS server in the cache, the method returns.

callback method specified in ngx_resolver_ctx_t after query completion

After the real DNS query is completed, the Nginx will callback the handler of the corresponding query, regardless of success, failure or timeout, as previously set: Ngx_mail_smtp_resolve_name_handler. You need to call Ngx_resolve_addr_done in handler to identify the end of the query.

static void

Ngx_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 being 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 is resolved to%ud.%ud.%ud.%ud",

(Ntohl (addr) >>) & 0xFF,

(Ntohl (addr) >>) & 0xFF,

(Ntohl (addr) >> 8) & 0xFF,

Ntohl (addr) & 0xff);

if (addr = = sin->sin_addr.s_addr) {

Goto found;

}

}

S->host = smtp_unavailable;

}

Found

Regardless of the success of the failure to execute

Ngx_resolve_name_done (CTX);

}


Analysis of Nginx DNS parsing process

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.