traffic server dns解析相关代码分析
来源:互联网 发布:网络渗透技术 编辑:程序博客网 时间:2024/04/30 03:40
http://blog.chinaunix.net/uid-23242010-id-93354.html
TrafficServer提供了DNS解析相关的功能,相关模块为iocore/dns。目前dns模块还有很多问题需要解决[1]。
首先从配置管理上分析dns模块。以下给出ts配置文件records.config中与dns相关的配置选项:
CONFIG proxy.config.dns.splitDNS.enabled INT 0
CONFIG proxy.config.dns.resolv_conf STRING /etc/resolv.conf
dns针对以上两种解析方式,采用如下设计逻辑进行了实现:通过DNSProcessor+DNSHandler+DNSEntry实现dns解析;通过SplitDNS+SplitDNSConfig+SplitDNSRecord提供额外的splitdns解析功能。
(1)
dns解析遵循ts的异步事件模型的设计原理[3],DNSProcessor借助DNSHandler对一个域名进行解析。
DNSEntry类实现了对一个dns请求的封装。ts内部实现封装了一组与libresolv库相同功能的方法[4],例如ink_res_int等等。
DNSHandler维护了两个队列:
struct DNSHandler: public Continuation
{
DNSConnection con[MAX_NAMED];
Queue<DNSEntry> entries;
};
if (dns_ns_rr) {//使用roundrobin
int max_nscount = m_res->nscount;
if (max_nscount > MAX_NAMED)
max_nscount = MAX_NAMED;
n_con = 0;
for (int i = 0; i < max_nscount; i++) {
struct sockaddr_in *sa = &m_res->nsaddr_list[i].sin;
ip = sa->sin_addr.s_addr;
if (ip) {
port = ntohs(sa->sin_port);
dnsProcessor.handler->open_con(ip, port, false, n_con);
++n_con;
Debug("dns_pas", "opened connection to %d.%d.%d.%d:%d, n_con = %d",DOT_SEPARATED(ip), port, n_con);
}
}
dns_ns_rr_init_down = 0;
} else {
dnsProcessor.handler->open_con(ip, port);
n_con = 1;
}
根据以上分析,通过DNSHandler::startEvent,与dns解析服务器进行连接。在startEvent函数中,通过下面两行代码异步周期调用DNSHandler::mainEvent:
SET_HANDLER(&DNSHandler::mainEvent);
dnsProcessor.thread->schedule_every(this, DNS_PERIOD);
recv_dns(event, e);
if (entries.head)
write_dns(this);
下面分析ts是如何将一个dns请求插入到DNSHandler维护的DNSEntry队列中去的。前面提到,dns解析遵循ts的异步事件模型的设计逻辑,这种设计逻辑通常由Processor调度Handler处理一个Continuation状态序列,在这里也不例外。DNSProcessor提供了一组get方法作域名解析,这些get方法都通过内部调用DNSProcessor::getby方法实现域名解析,以DNSProcessor::gethostbyname为例:
inline Action *
DNSProcessor::gethostbyname(Continuation * cont, const char *name, DNSHandler * adnsH,int timeout)
{
return getby(name, 0, T_A, cont, 0, adnsH, timeout);
}
DNSEntry *e = dnsEntryAllocator.alloc();
e->retries = dns_retries;
e->init(x, len, type, cont, wait, adnsH, timeout);
SET_HANDLER((DNSEntryHandler) & DNSEntry::mainEvent);
我们分析DNSEntry::mainEvent方法,这段代码中最主要的是以下两行:dnsH->entries.enqueue(this);
write_dns(dnsH);
通过以上分析可以看出,dns解析通过DNSProcessor::getby不断处理每一个dns请求,并构造dns消息体插入到DNSHandler对应的DNSEntry队列中去,DNSHandler定期调用DNSHandler::mainEvent方法从dns服务器中取回dns响应,并根据其维护的DNSEntry队列构造新的dns请求发送给dns服务器。
dns解析是通过DNSProcessor::start方法启用的。该方法首先读取一些配置选项,然后执行DNSProcessor::dns_init加载resolv_conf变量对应的文件(默认为/etc/resolv.conf),最后执行DNSProcessor::open方法,该方法内部调用DNSHandler::startEvent,接下来按照上面描述的流程,一个dns解析服务就启用了。
(2)
splitdns是后来的ts开发团队在原有基础上增加的功能,设计逻辑非常混乱,以TrafficServer2.1.4版本为例,整个代码嵌套在了iocore/dns,iocore/hostdb,以及proxy模块中。从功能上来看,目前splitdns的功能还不是很完善,后续需要很多改进,[1]介绍了后续的一些改进方案。以下大体介绍一下splitdns相关的一些关键代码。
1)SplitDNSConfig通过SplitDNSConfig::startup方法根据配置文件选项选择是否启动splitdns功能,该函数调用SplitDNSConfig::reconfig函数。下面分析reconfig这个函数的内容:
IOCORE_ReadConfigInt32(gsplit_dns_enabled, "proxy.config.dns.splitDNS.enabled");
if (0 == gsplit_dns_enabled)
return;
params->m_DNSSrvrTable = NEW(new DNS_table("proxy.config.dns.splitdns.filename",modulePrefix, &sdns_dest_tags));
这行代码基本上完成了加载splitdns.config以及启用splitdns的所有工作。通过分析DNS_table的类型:typedef ControlMatcher<SplitDNSRecord, SplitDNSResult> DNS_table;
ControlMatcher是一个泛型类,一路跟踪其构造函数,直到HostMatcher<Data, Result>::NewEntry函数体,里面有这么两行关键代码:
Data *cur_d;
errBuf = cur_d->Init(line_info);
2)通过SplitDNSConfig::startup方法,当在records.config文件中enable splitdns后,splitdns已经开启。我们接着分析SplitDNSRecord这个结构体,可以看出其内部有一个成员:
DNSServer m_servers;
继续分析DNSServer这个结构体:struct DNSServer
{
unsigned int x_server_ip[MAXNS];
char x_dns_ip_line[MAXDNAME * 2];
char x_def_domain[MAXDNAME];
char x_domain_srch_list[MAXDNAME];
int x_dns_server_port[MAXNS];
DNSHandler *x_dnsH;
};
3)SplitDNS这个结构体提供了对外的接口。SplitDNS::getDNSRecord解析参数指向的域名,并返回一个DNSServer,从而也间接得到了一个DNSHandler。将这个DNSHandler作为参数调用DNSProcessor::getby,就可以实现从splitdns模块解析一个域名了。
从上面的描述中我们可以看出,通过splitdns解析一个域名。只需要首先配置records.config文件,将CONFIG proxy.config.dns.splitDNS.enabled赋值为1;然后通过
SplitDNSConfig::startup();
启用splitdns;再通过
if(x && NULL == adnsH && SplitDNSConfig::isSplitDNSEnabled()){
const char *scan = x;
for(; *scan != '\0' && (ParseRules::is_digit(*scan) || '.' == *scan); ++scan);
if('\0' != *scan){
void *pSD = (void *) SplitDNSConfig::acquire();
if(0 != pSD){
void *pDS = ((SplitDNS *) pSD)->getDNSRecord(x);
if(0 != pDS){
adnsH = ((DNSServer *) pDS)->x_dnsH;
}
}
}
}
针对splitdns的功能完善问题,TS-435[5]以及TS-541[6]有更为详细的描述。
[1]https://cwiki.apache.org/confluence/display/TS/HostDBandDNS
[2]http://trafficserver.apache.org/docs/v2/admin/ConfigurationFiles下面splitdns.config
[3]http://trafficserver.apache.org/docs/v2/sdk/CreatingTSPlugins.htmlchapter2
[4]http://publib.boulder.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=/apis/resmkq.htm
[5]https://issues.apache.org/jira/browse/TS-435?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12932442#action_12932442
[6]https://issues.apache.org/jira/browse/TS-541
- traffic server dns解析相关代码分析
- dns解析相关代码分析
- dns解析相关代码分析
- Traffic Server Net子系统分析
- Android DNS 代码分析
- DNS解析操作相关说明
- traffic server cache源码分析一 存储机制分析
- traffic server cache源码分析二 读写逻辑分析
- Traffic Server的eventsystem源码分析 多线程框架
- traffic server cache源码分析三 evacuate机制的实现
- dns解析超时故障分析
- 关于dns解析时间分析
- [转]Android DNS 代码分析
- Traffic Server Overview
- Traffic Server 简介
- traffic server 正向代理
- Apache Traffic Server 简介
- Traffic Server编译安装
- Kinect for Windows SDK开发入门(一):开发环境配置
- jsp传送的值在接受后末尾多出一个斜杠问题解决办法
- 自己玩垂直搜索
- VC6环境下的OMNet工程配置
- PostMessage
- traffic server dns解析相关代码分析
- 斯库利在接受采访时谈到了使乔布斯成功的12条原则
- event.keyCode键值表
- SQL Server 读取Excel 2003
- 摘自别人的,主要学习与线程编程相关的函数
- Kalman滤波器
- traffic server cache源码分析一 存储机制分析
- 几种序列化协议(protobuf,xstream,jackjson,jdk,hessian)相关数据对比
- Ubuntu软件安装与删除相关命令