因为ecrawler,需要具有DNS解析功能,看文章都介绍说,要注意系统提供的gethostbyname之类的函数内部实现机制,是采用顺序执行,还是启动多个连接并发执行?
我在erlang中做了一下测试(windows2003 + R12B-3):
1,首先清空本地的dns信息(cmd中 ipconfig /flushdns)
2,多个process同时调用inet:getaddr/2请求dns地址
3,wireshark抓包,发现同时只有4个DNS(port 53)的请求,4个dns请求成功后,第一个又进行了一次请求,结果我的只有5个请求解析成功,其他的都是{error, timeout}
如此看来erlang的inet:getaddr/2 只是开启有限数目的连接,所后进行dns解析请求,至于后面多余的请求,只能超时了。是不是getaddr应该提供更多的选项?
下面是测试结果:
%% 请求
<0.258.0> start:{1221,193358,78000} Host:"www.toquick.com"
<0.259.0> start:{1221,193358,78001} Host:"www.ubuntu.org"
<0.260.0> start:{1221,193358,78002} Host:"www.china.com"
<0.261.0> start:{1221,193358,78003} Host:"www.tom.com"
<0.262.0> start:{1221,193358,78004} Host:"www.sohu.com"
<0.263.0> start:{1221,193358,78005} Host:"www.msn.com"
<0.264.0> start:{1221,193358,78006} Host:"www.answers.com"
<0.265.0> start:{1221,193358,78007} Host:"www.tudou.com"
<0.266.0> start:{1221,193358,78008} Host:"www.erlang.org"
<0.267.0> start:{1221,193358,78009} Host:"www.howcast.com"
<0.268.0> start:{1221,193358,78010} Host:"www.go2map.com"
<0.269.0> start:{1221,193358,78011} Host:"www.microsoft.com"
%% response
<0.259.0> end:{1221,193358,78012} Value:{ok,{147,83,195,55}}
<0.260.0> end:{1221,193358,78013} Value:{ok,{221,194,139,22}}
<0.258.0> end:{1221,193358,78014} Value:{ok,{211,136,108,240}}
<0.261.0> end:{1221,193358,78015} Value:{ok,{202,108,12,68}}
<0.262.0> end:{1221,193358,78016} Value:{ok,{61,135,189,165}}
<0.269.0> end:{1221,193366,93000} Value:{error,timeout}
<0.268.0> end:{1221,193366,93001} Value:{error,timeout}
<0.267.0> end:{1221,193366,93002} Value:{error,timeout}
<0.266.0> end:{1221,193366,93003} Value:{error,timeout}
<0.265.0> end:{1221,193366,93004} Value:{error,timeout}
<0.264.0> end:{1221,193366,93005} Value:{error,timeout}
<0.263.0> end:{1221,193366,93006} Value:{error,timeout}
接着感谢yufeng的帮助!
Erlang中提供native以及erlang dns请求,两种方式进行dns解析。其中native方式下,通过port调用外部应用实现,外部应用调用系统本身的dns相关API,如 gethostbyname等;erlang自身也实现了dns的请求解析,并拥有一套缓存,管理机制。
我们可以参考:ERTS User's Guide 的[url=http://www.erlang.org/doc/apps/erts/inet_cfg.html#7]inet configuration[/url] 进行配置。
erlang默认采用native方式进行dns解析,默认的并发数目为4,所以出现了本文中的问题,多个dns解析请求,只有前4个成功,其他均超时。我们可以通过设置变量:gethost_poolsize来增大并发数(请注意,每增大1,则外部应用新创建一个线程):
erl -kernel gethost_poolsize 12
我们启动erlang,设置并发请求数为12,随后运行testdns:dns()所有请求均可成功。
面对大量并发的dns请求,显然采用native方式不可行,因此我们采用erlang自身的dns请求,我们通过创建配置文件(erl_inetrc):
%erl_inetrc
%% specify lookup method
{lookup, [dns]}.
%% timeout
{timeout, 5000}.
{nameserver, {202, 106, 46, 151}, 53}.
随后启动erl:
erl -kernel inetrc './erl_inetrc'
运行:
testdns:dns()
发现12个dns请求全部成功!