DNS响应流程:在DNS初始化流程的说明时已经说过,DNS启动后会打开到DNS server的链接,然后定时调用DNSHandler::mainEvent()进行DNS响应的接收和处理。接收是调用DNSHandler::recv_dns()函数来完成的,因此DNS响应处理流程从这里开始在前面也说过在向DNS server发起链接之前会向NET模块注册READ事件,让NET模块在有DNS响应报文到来时会把之加入DNSHandler的triggered队列中,而DNSHandler::recv_dns会遍历该队列去处理每个DNS响应main()---> DNSProcessor::start()--->DNSProcessor::open()--->DNSHandler::startEvent()--->DNSHandler::mainEvent()--->DNSHandler::recv_dns()--->dns_process()static booldns_process(DNSHandler *handler, HostEnt *buf, int len){ ProxyMutex *mutex = handler->mutex; HEADER *h = (HEADER *) (buf->buf);//获取对应的DNS查询表项 DNSEntry *e = get_dns(handler, (uint16_t) ntohs(h->id)); bool retry = false; bool server_ok = true; uint32_t temp_ttl = 0; if (!e || !e->written_flag) { Debug("dns", "unknown DNS id = %u", (uint16_t) ntohs(h->id)); return false; // cannot count this as a success }//已接收 e->written_flag = false; --(handler->in_flight);//计数 DNS_DECREMENT_DYN_STAT(dns_in_flight_stat); DNS_SUM_DYN_STAT(dns_response_time_stat, ink_get_hrtime() - e->send_time);//下面是解析处理DNS响应报文,看代码前先看看DNS协议,否则云里雾里的 if (h->rcode != NOERROR || !h->ancount) { Debug("dns", "received rcode = %d", h->rcode); switch (h->rcode) { default: Warning("Unknown DNS error %d for [%s]", h->rcode, e->qname); retry = true; server_ok = false; // could be server problems goto Lerror; case SERVFAIL: // recoverable error retry = true; case FORMERR: // unrecoverable errors case REFUSED: case NOTIMP: Debug("dns", "DNS error %d for [%s]", h->rcode, e->qname); server_ok = false; // could be server problems goto Lerror; case NOERROR: case NXDOMAIN: case 6: // YXDOMAIN case 7: // YXRRSET case 8: // NOTAUTH case 9: // NOTAUTH case 10: // NOTZONE Debug("dns", "DNS error %d for [%s]", h->rcode, e->qname); goto Lerror; } } else { // // Initialize local data // // struct in_addr host_addr; unused u_char tbuf[MAXDNAME + 1]; buf->ent.h_name = NULL; int ancount = ntohs(h->ancount); unsigned char *bp = buf->hostbuf; int buflen = sizeof(buf->hostbuf); u_char *cp = ((u_char *) h) + HFIXEDSZ; u_char *eom = (u_char *) h + len; int n; ink_assert(buf->srv_hosts.srv_host_count == 0 && buf->srv_hosts.srv_hosts_length == 0); buf->srv_hosts.srv_host_count = 0; buf->srv_hosts.srv_hosts_length = 0; unsigned& num_srv = buf->srv_hosts.srv_host_count; int rname_len = -1; // // Expand name // if ((n = ink_dn_expand((u_char *) h, eom, cp, bp, buflen)) < 0) goto Lerror; // Should we validate the query name? if (dns_validate_qname) { int qlen = e->qname_len; int rlen = strlen((char *)bp); rname_len = rlen; // Save for later use if ((qlen > 0) && ('.' == e->qname[qlen-1])) --qlen; if ((rlen > 0) && ('.' == bp[rlen-1])) --rlen; // TODO: At some point, we might want to care about the case here, and use an algorithm // to randomly pick upper case characters in the query, and validate the response with // case sensitivity. if ((qlen != rlen) || (strncasecmp(e->qname, (const char*)bp, qlen) != 0)) { // Bad mojo, forged? Warning("received DNS response with query name of '%s', but response query name is '%s'", e->qname, bp); goto Lerror; } else { Debug("dns", "query name validated properly for %s", e->qname); } } cp += n + QFIXEDSZ; if (is_addr_query(e->qtype)) { if (-1 == rname_len) n = strlen((char *)bp) + 1; else n = rname_len + 1; buf->ent.h_name = (char *) bp; bp += n; buflen -= n; } u_char **ap = buf->host_aliases; buf->ent.h_aliases = (char **) buf->host_aliases; u_char **hap = (u_char **) buf->h_addr_ptrs; *hap = NULL; buf->ent.h_addr_list = (char **) buf->h_addr_ptrs; if (local_num_entries >= DEFAULT_NUM_TRY_SERVER) { if ((attempt_num_entries % 50) == 0) { try_servers = (try_servers + 1) % countof(try_server_names); ink_strlcpy(try_server_names[try_servers], e->qname, MAXDNAME); memset(&try_server_names[try_servers][strlen(e->qname)], 0, 1); attempt_num_entries = 0; } ++attempt_num_entries; } else { // fill up try_server_names for try_primary_named try_servers = local_num_entries++; ink_strlcpy(try_server_names[try_servers], e->qname, MAXDNAME); memset(&try_server_names[try_servers][strlen(e->qname)], 0, 1); } /* added for SRV support [ebalsa] this skips the query section (qdcount) */ unsigned char *here = (unsigned char *) buf->buf + HFIXEDSZ; if (e->qtype == T_SRV) { for (int ctr = ntohs(h->qdcount); ctr > 0; ctr--) { int strlen = dn_skipname(here, eom); here += strlen + QFIXEDSZ; } } // // Decode each answer // int answer = false, error = false; while (ancount-- > 0 && cp < eom && !error) { n = ink_dn_expand((u_char *) h, eom, cp, bp, buflen); if (n < 0) { ++error; break; } cp += n; short int type; NS_GET16(type, cp); cp += NS_INT16SZ; // NS_GET16(cls, cp); NS_GET32(temp_ttl, cp); // NOTE: this is not a "long" but 32-bits (from nameser_compat.h) if ((temp_ttl < buf->ttl) || (buf->ttl == 0)) buf->ttl = temp_ttl; NS_GET16(n, cp); // // Decode cname // if (is_addr_query(e->qtype) && type == T_CNAME) { if (ap >= &buf->host_aliases[DNS_MAX_ALIASES - 1]) continue; n = ink_dn_expand((u_char *) h, eom, cp, tbuf, sizeof(tbuf)); if (n < 0) { ++error; break; } cp += n; *ap++ = (unsigned char *) bp; n = strlen((char *) bp) + 1; bp += n; buflen -= n; n = strlen((char *) tbuf) + 1; if (n > buflen) { ++error; break; } ink_strlcpy((char *) bp, (char *) tbuf, buflen); bp += n; buflen -= n; Debug("dns", "received cname = %s", tbuf); continue; } if (e->qtype != type) { ++error; break; } // // Decode names // if (type == T_PTR) { n = ink_dn_expand((u_char *) h, eom, cp, bp, buflen); if (n < 0) { ++error; break; } cp += n; if (!answer) { buf->ent.h_name = (char *) bp; Debug("dns", "received PTR name = %s", bp); n = strlen((char *) bp) + 1; bp += n; buflen -= n; } else if (ap < &buf->host_aliases[DNS_MAX_ALIASES - 1]) { *ap++ = bp; Debug("dns", "received PTR alias = %s", bp); n = strlen((char *) bp) + 1; bp += n; buflen -= n; } } else if (type == T_SRV) { if (num_srv >= HOST_DB_MAX_ROUND_ROBIN_INFO) break; cp = here; /* hack */ int strlen = dn_skipname(cp, eom); cp += strlen; const unsigned char *srv_off = cp; cp += SRV_FIXEDSZ; cp += dn_skipname(cp, eom); here = cp; /* hack */ SRV *srv = &buf->srv_hosts.hosts[num_srv]; int r = ink_ns_name_ntop(srv_off + SRV_SERVER, srv->host, MAXDNAME); if (r <= 0) { /* FIXME: is this really an error? or just a continue; */ ++error; goto Lerror; } Debug("dns_srv", "Discovered SRV record [from NS lookup] with cost:%d weight:%d port:%d with host:%s", ink_get16(srv_off + SRV_COST), ink_get16(srv_off + SRV_WEIGHT), ink_get16(srv_off + SRV_PORT), srv->host); srv->port = ink_get16(srv_off + SRV_PORT); srv->priority = ink_get16(srv_off + SRV_COST); srv->weight = ink_get16(srv_off + SRV_WEIGHT); srv->host_len = r; srv->host[r-1] = '\0'; srv->key = makeHostHash(srv->host); if (srv->host[0] != '\0') buf->srv_hosts.srv_hosts_length += r; else continue; ++num_srv; } else if (is_addr_query(type)) { if (answer) { if (n != buf->ent.h_length) { cp += n; continue; } } else { int nn; buf->ent.h_length = n; buf->ent.h_addrtype = T_A == type ? AF_INET : AF_INET6; buf->ent.h_name = (char *) bp; nn = strlen((char *) bp) + 1; Debug("dns", "received %s name = %s", QtypeName(type), bp); bp += nn; buflen -= nn; } // attempt to use the original buffer (if it is word aligned) if (!(((uintptr_t) cp) % sizeof(unsigned int))) { *hap++ = cp; cp += n; } else { ip_text_buffer ip_string; bp = (unsigned char *) align_pointer_forward(bp, sizeof(int)); if (bp + n >= buf->hostbuf + DNS_HOSTBUF_SIZE) { ++error; break; } memcpy((*hap++ = bp), cp, n); Debug("dns", "received %s = %s", QtypeName(type), inet_ntop(T_AAAA == type ? AF_INET6 : AF_INET, bp, ip_string, sizeof(ip_string)) ); bp += n; cp += n; } } else goto Lerror; ++answer; } if (answer) { *ap = NULL; *hap = NULL; // // If the named didn't send us the name, insert the one // the user gave us... // if (!buf->ent.h_name) { Debug("dns", "inserting name = %s", e->qname); ink_strlcpy((char *) bp, e->qname, sizeof(buf->hostbuf) - (bp - buf->hostbuf)); buf->ent.h_name = (char *) bp; } //处理DNS响应结果 dns_result(handler, e, buf, retry); return server_ok; } }Lerror:; DNS_INCREMENT_DYN_STAT(dns_lookup_fail_stat); dns_result(handler, e, NULL, retry); return server_ok;}main()---> DNSProcessor::start()--->DNSProcessor::open()--->DNSHandler::startEvent()--->DNSHandler::mainEvent()--->DNSHandler::recv_dns()--->dns_process()--->dns_result()这个函数的功能是处理DNS响应的结果static voiddns_result(DNSHandler *h, DNSEntry *e, HostEnt *ent, bool retry) { ProxyMutex *mutex = h->mutex; bool cancelled = (e->action.cancelled ? true : false);//如果查询结果没有ip地址,则重试//如果重试次数还没用完,则继续重试 if (!ent && !cancelled) { // try to retry operation if (retry && e->retries) { Debug("dns", "doing retry for %s", e->qname); DNS_INCREMENT_DYN_STAT(dns_retries_stat); --(e->retries); write_dns(h); return; //如果重试次数已用完,则扩展主机名后继续重新发DNS查询 } else if (e->domains && *e->domains) { do { Debug("dns", "domain extending %s", e->qname); //int l = _strlen(e->qname); char *dot = strchr(e->qname, '.'); if (dot) { if (e->qname_len + strlen(*e->domains) + 2 > MAXDNAME) { Debug("dns", "domain too large %s + %s", e->qname, *e->domains); goto LnextDomain; } if (e->qname[e->qname_len - 1] != '.') { e->qname[e->qname_len] = '.'; ink_strlcpy(e->qname + e->qname_len + 1, *e->domains, MAXDNAME - (e->qname_len + 1)); e->qname_len = strlen(e->qname); } else { ink_strlcpy(e->qname + e->qname_len, *e->domains, MAXDNAME - e->qname_len); e->qname_len = strlen(e->qname); } } else { if (e->qname_len + strlen(*e->domains) + 2 > MAXDNAME) { Debug("dns", "domain too large %s + %s", e->qname, *e->domains); goto LnextDomain; } e->qname[e->qname_len] = '.'; ink_strlcpy(e->qname + e->qname_len + 1, *e->domains, MAXDNAME - (e->qname_len + 1)); e->qname_len = strlen(e->qname); } ++(e->domains); e->retries = dns_retries; Debug("dns", "new name = %s retries = %d", e->qname, e->retries); write_dns(h); return; LnextDomain: ++(e->domains); } while (*e->domains); } else { e->qname[e->qname_len] = 0; if (!strchr(e->qname, '.') && !e->last) { e->last = true; write_dns(h); return; } } if (retry) { DNS_INCREMENT_DYN_STAT(dns_max_retries_exceeded_stat); } }//失败处理 if (ent == BAD_DNS_RESULT) ent = NULL; if (!cancelled) { if (!ent) { DNS_SUM_DYN_STAT(dns_fail_time_stat, ink_get_hrtime() - e->submit_time); } else { DNS_SUM_DYN_STAT(dns_success_time_stat, ink_get_hrtime() - e->submit_time); } }//从DNSHandler的entries队列中删除 h->entries.remove(e); if (is_debug_tag_set("dns")) { if (is_addr_query(e->qtype)) { ip_text_buffer buff; char const* ptr = "<none>"; char const* result = "FAIL"; if (ent) { result = "SUCCESS"; ptr = inet_ntop(e->qtype == T_AAAA ? AF_INET6 : AF_INET, ent->ent.h_addr_list[0], buff, sizeof(buff)); } Debug("dns", "%s result for %s = %s retry %d", result, e->qname, ptr, retry); } else { if (ent) { Debug("dns", "SUCCESS result for %s = %s af=%d retry %d", e->qname, ent->ent.h_name, ent->ent.h_addrtype, retry); } else { Debug("dns", "FAIL result for %s = <not found> retry %d", e->qname, retry); } } } if (ent) { DNS_INCREMENT_DYN_STAT(dns_lookup_success_stat); } else { DNS_INCREMENT_DYN_STAT(dns_lookup_fail_stat); }//如果是在重复队列上,则先从该队列中删除后告诉上层进行处理,如果处理出错重新加入重复队列 DNSEntry *dup = NULL; while ((dup = e->dups.dequeue())) { if (dup->post(h, ent)) { e->dups.enqueue(dup); goto Lretry; } } if (e->timeout) { e->timeout->cancel(e); e->timeout = NULL; }//设置查询结果 e->result_ent = ent; if (h->mutex->thread_holding == e->submit_thread) { MUTEX_TRY_LOCK(lock, e->action.mutex, h->mutex->thread_holding); if (!lock) { Debug("dns", "failed lock for result %s", e->qname); goto Lretry; } for (int i = 0; i < MAX_DNS_RETRIES; i++) { if (e->id[i] < 0) break; h->release_query_id(e->id[i]); } e->postEvent(0, 0);//清除报文的id } else { for (int i = 0; i < MAX_DNS_RETRIES; i++) { if (e->id[i] < 0) break; h->release_query_id(e->id[i]); } e->mutex = e->action.mutex;//进行post操作,即回调上层来处理查询结果 SET_CONTINUATION_HANDLER(e, &DNSEntry::postEvent); e->submit_thread->schedule_imm_signal(e); } return;Lretry: e->result_ent = ent; e->retries = 0; if (e->timeout) e->timeout->cancel(); e->timeout = h->mutex->thread_holding->schedule_in(e, DNS_PERIOD);}main()---> DNSProcessor::start()--->DNSProcessor::open()--->DNSHandler::startEvent()--->DNSHandler::mainEvent()--->DNSHandler::recv_dns()--->dns_process()--->dns_result()--->DNSEntry::postEvent()这个函数的功能是回调上层函数处理查询结果,处理完成后释放响应的结构intDNSEntry::postEvent(int /* event ATS_UNUSED */, Event * /* e ATS_UNUSED */){ if (!action.cancelled) { Debug("dns", "called back continuation for %s", qname); //回调上层处理函数 action.continuation->handleEvent(DNS_EVENT_LOOKUP, result_ent); }//清理结果 result_ent = NULL; action.mutex = NULL; mutex = NULL; dnsEntryAllocator.free(this); return EVENT_DONE;}main()---> DNSProcessor::start()--->DNSProcessor::open()--->DNSHandler::startEvent()--->DNSHandler::mainEvent()--->DNSHandler::recv_dns()--->dns_process()--->dns_result()--->DNSEntry::postEvent()--->HostDBContinuation::dnsEvent()这个函数的功能是接收DNS的响应结果HostEnt,根据这个结果创建HostDBInfo结果写入hostdb数据库,最后把结果传给HTTPSM处理intHostDBContinuation::dnsEvent(int event, HostEnt * e){ ink_assert(this_ethread() == hostDB.lock_for_bucket(fold_md5(md5.hash) % hostDB.buckets)->thread_holding); if (timeout) { timeout->cancel(this); timeout = NULL; } EThread *thread = mutex->thread_holding; if (event == EVENT_INTERVAL) { if (!action.continuation) { remove_trigger_pending_dns(); hostdb_cont_free(this); return EVENT_DONE; } MUTEX_TRY_LOCK_FOR(lock, action.mutex, thread, action.continuation); if (!lock) { timeout = thread->schedule_in(this, HOST_DB_RETRY_PERIOD); return EVENT_CONT; } if (!action.cancelled && action.continuation) action.continuation->handleEvent(EVENT_HOST_DB_LOOKUP, NULL); action = NULL; timeout = thread->schedule_in(this, HRTIME_SECONDS(hostdb_insert_timeout)); return EVENT_DONE; } else { //来,从这里开始 bool failed = !e; bool rr = false; pending_action = NULL;//当响应的ip地址大于一个时,rr为true if (is_srv()) { rr = !failed && (e->srv_hosts.srv_host_count > 0); } else if (!failed) { rr = 0 != e->ent.h_addr_list[1]; } else { } ttl = failed ? 0 : e->ttl / 60; int ttl_seconds = failed ? 0 : e->ttl; //再查一下hostdb HostDBInfo *old_r = probe(mutex, md5, true); HostDBInfo old_info; if (old_r) old_info = *old_r; HostDBRoundRobin *old_rr_data = old_r ? old_r->rr() : NULL; int n = 0, nn = 0; void* first = 0; uint8_t af = e ? e->ent.h_addrtype : AF_UNSPEC; //记录合法的ip地址的个数 if (rr) { if (is_srv() && !failed) { n = e->srv_hosts.srv_host_count; } else { void* ptr; // tmp for current entry. for ( ; nn < HOST_DB_MAX_ROUND_ROBIN_INFO && 0 != (ptr = e->ent.h_addr_list[nn]) ; ++nn ) { if (is_addr_valid(af, ptr)) { if (! first) first = ptr; ++n; } else { Warning("Zero address removed from round-robin list for '%s'", md5.host_name); } } if (!first) { failed = true; rr = false; } } } else if (!failed) { first = e->ent.h_addr_list[0]; } HostDBInfo *r = NULL; IpAddr tip; // temp storage if needed. if (is_byname()) { //设置第一个ip地址 if (first) ip_addr_set(tip, af, first); //把结果(第一个合法的ip地址)写入hostdb r = lookup_done(tip, md5.host_name, rr, ttl_seconds, failed ? 0 : &e->srv_hosts); } else if (is_srv()) { if (!failed) tip._family = AF_INET; // force the tip valid, or else the srv will fail r = lookup_done(tip, /* junk: FIXME: is the code in lookup_done() wrong to NEED this? */ md5.host_name, /* hostname */ rr, /* is round robin, doesnt matter for SRV since we recheck getCount() inside lookup_done() */ ttl_seconds, /* ttl in seconds */ failed ? 0 : &e->srv_hosts); } else if (failed) { r = lookup_done(tip, md5.host_name, false, ttl_seconds, 0); } else { r = lookup_done(md5.ip, e->ent.h_name, false, ttl_seconds, &e->srv_hosts); } ink_assert(!r || (r->app.allotment.application1 == 0 && r->app.allotment.application2 == 0));//下面出要是响应结果有多个ip地址时的处理:每个ip地址对应一个HostDBInfo结构,然后放到 HostDBRoundRobin的数组info中 if (rr) { const int rrsize = HostDBRoundRobin::size(n, e->srv_hosts.srv_hosts_length); HostDBRoundRobin *rr_data = (HostDBRoundRobin *) hostDB.alloc(&r->app.rr.offset, rrsize); Debug("hostdb", "allocating %d bytes for %d RR at %p %d", rrsize, n, rr_data, r->app.rr.offset); if (rr_data) { rr_data->length = rrsize; int i = 0, ii = 0; if (is_srv()) { int skip = 0; char *pos = (char *) rr_data + sizeof(HostDBRoundRobin) + n * sizeof(HostDBInfo); SRV *q[HOST_DB_MAX_ROUND_ROBIN_INFO]; ink_assert(n <= HOST_DB_MAX_ROUND_ROBIN_INFO); // sort for (i = 0; i < n; ++i) { q[i] = &e->srv_hosts.hosts[i]; } for (i = 0; i < n; ++i) { for (ii = i + 1; ii < n; ++ii) { if (*q[ii] < *q[i]) { SRV *tmp = q[i]; q[i] = q[ii]; q[ii] = tmp; } } } for (i = 0; i < n; ++i) { SRV *t = q[i]; HostDBInfo& item = rr_data->info[i]; memset(&item, 0, sizeof(item)); item.round_robin = 0; item.reverse_dns = 0; item.is_srv = 1; item.data.srv.srv_weight = t->weight; item.data.srv.srv_priority = t->priority; item.data.srv.srv_port = t->port; item.data.srv.key = t->key; ink_assert((skip + t->host_len) <= e->srv_hosts.srv_hosts_length); memcpy(pos + skip, t->host, t->host_len); item.data.srv.srv_offset = (pos - (char *) rr_data) + skip; skip += t->host_len; item.md5_high = r->md5_high; item.md5_low = r->md5_low; item.md5_low_low = r->md5_low_low; item.full = 1; item.app.allotment.application1 = 0; item.app.allotment.application2 = 0; Debug("dns_srv", "inserted SRV RR record [%s] into HostDB with TTL: %d seconds", t->host, ttl_seconds); } rr_data->good = rr_data->rrcount = n; rr_data->current = 0; if (old_rr_data) { for (i = 0; i < rr_data->rrcount; ++i) { for (ii = 0; ii < old_rr_data->rrcount; ++ii) { if (rr_data->info[i].data.srv.key == old_rr_data->info[ii].data.srv.key) { char *new_host = rr_data->info[i].srvname(rr_data); char *old_host = old_rr_data->info[ii].srvname(old_rr_data); if (!strcmp(new_host, old_host)) rr_data->info[i].app = old_rr_data->info[ii].app; } } } } } else { for (ii = 0; ii < nn; ++ii) { if (is_addr_valid(af, e->ent.h_addr_list[ii])) { HostDBInfo& item = rr_data->info[i]; ip_addr_set(item.ip(), af, e->ent.h_addr_list[ii]);// rr_data->info[i].ip() = *(unsigned int *) e->ent.h_addr_list[ii]; item.full = 1; item.round_robin = 0; item.reverse_dns = 0; item.is_srv = 0; item.md5_high = r->md5_high; item.md5_low = r->md5_low; item.md5_low_low = r->md5_low_low; if (!restore_info(&item, old_r, old_info, old_rr_data)) { item.app.allotment.application1 = 0; item.app.allotment.application2 = 0; } ++i; } } rr_data->good = rr_data->rrcount = n; rr_data->current = 0; } } else { ink_assert(!"out of room in hostdb data area"); Warning("out of room in hostdb for round-robin DNS data"); r->round_robin = 0; } } if (!failed && !rr && !is_srv()) restore_info(r, old_r, old_info, old_rr_data); ink_assert(!r || !r->round_robin || !r->reverse_dns); ink_assert(failed || !r->round_robin || r->app.rr.offset);#ifdef NON_MODULAR//cluster模式时的处理,留到cluster再分析 ClusterMachine *m = cluster_machine_at_depth(master_hash(md5.hash)); if (m) do_put_response(m, r, NULL);#endif if (action.continuation) { if (failed && check_for_retry(md5.db_mark, host_res_style)) { this->refresh_MD5(); SET_CONTINUATION_HANDLER(this, (HostDBContHandler) & HostDBContinuation::probeEvent); thread->schedule_in(this, MUTEX_RETRY_DELAY); return EVENT_CONT; } MUTEX_TRY_LOCK_FOR(lock, action.mutex, thread, action.continuation); if (!lock) { remove_trigger_pending_dns(); SET_HANDLER((HostDBContHandler) & HostDBContinuation::probeEvent); thread->schedule_in(this, HOST_DB_RETRY_PERIOD); return EVENT_CONT; } //把结果传给上层处理:最终调到HttpSM::state_hostdb_lookup来处理 if (!action.cancelled) reply_to_cont(action.continuation, r, is_srv()); } remove_trigger_pending_dns(); hostdb_cont_free(this); return EVENT_DONE; }}main()---> DNSProcessor::start()--->DNSProcessor::open()--->DNSHandler::startEvent()--->DNSHandler::mainEvent()--->DNSHandler::recv_dns()--->dns_process()--->dns_result()--->DNSEntry::postEvent()--->HostDBContinuation::dnsEvent()--->HttpSM::process_hostdb_info()在这里这个函数接收DNS响应并调用process_hostdb_info进行处理intHttpSM::state_hostdb_lookup(int event, void *data){ switch (event) { case EVENT_HOST_DB_LOOKUP: pending_action = NULL;//直接调用process_hostdb_info处理 process_hostdb_info((HostDBInfo *) data); call_transact_and_set_next_state(NULL); break; ......}main()---> DNSProcessor::start()--->DNSProcessor::open()--->DNSHandler::startEvent()--->DNSHandler::mainEvent()--->DNSHandler::recv_dns()--->dns_process()--->dns_result()--->DNSEntry::postEvent()--->HostDBContinuation::dnsEvent()--->HttpSM::process_hostdb_info()--->HttpSM::process_hostdb_info()这个函数功能是把DNS查询结果设置到HTTP状态机的host_db_info上,DNS响应大概流程到此结束voidHttpSM::process_hostdb_info(HostDBInfo * r){ //判断查询结果是否成功 if (r && !r->failed()) { ink_time_t now = ink_cluster_time(); HostDBInfo *ret = NULL; //设置为查询成功 t_state.dns_info.lookup_success = true; //如果开启round_robin功能,则根据客户端ip地址选择一个ip地址 if (r->round_robin) { HostDBRoundRobin *rr = r->rr(); ret = rr->select_best_http(&t_state.client_info.addr.sa, now, (int) t_state.txn_conf->down_server_timeout); if (t_state.dns_info.srv_lookup_success) { uint32_t last_failure = 0xFFFFFFFF; for (int i = 0; i < rr->rrcount && last_failure != 0; ++i) { if (last_failure > rr->info[i].app.http_data.last_failure) last_failure = rr->info[i].app.http_data.last_failure; } if (last_failure != 0 && (uint32_t) (now - t_state.txn_conf->down_server_timeout) < last_failure) { HostDBApplicationInfo app; app.allotment.application1 = 0; app.allotment.application2 = 0; app.http_data.last_failure = last_failure; hostDBProcessor.setby_srv(t_state.dns_info.lookup_name, 0, t_state.dns_info.srv_hostname, &app); } } } else { ret = r; } if (ret) { t_state.host_db_info = *ret; ink_release_assert(!t_state.host_db_info.reverse_dns); ink_release_assert(ats_is_ip(t_state.host_db_info.ip())); } } else { //DNS查询失败 DebugSM("http", "[%" PRId64 "] DNS lookup failed for '%s'", sm_id, t_state.dns_info.lookup_name); t_state.dns_info.lookup_success = false; t_state.host_db_info.app.allotment.application1 = 0; t_state.host_db_info.app.allotment.application2 = 0; ink_assert(!t_state.host_db_info.round_robin); }//DNS查询结束时间 milestones.dns_lookup_end = ink_get_hrtime(); if (is_debug_tag_set("http_timeout")) { if (t_state.api_txn_dns_timeout_value != -1) { int foo = (int) (milestone_difference_msec(milestones.dns_lookup_begin, milestones.dns_lookup_end)); DebugSM("http_timeout", "DNS took: %d msec", foo); } }}