对于互联网的应用来说,域名是互联网的基础,几乎所有的应用都牵涉到域名的解释,而随着移动互联网的发展,网络的延迟不再是几十ms,而是几百ms的延迟,对于一个应用来说都是有好几个域名,如果单纯解释一个域名都需要几百ms,打开一个应用,包括数据的传输,渲染,都是5s以上,由于移动互联网,网络比较的差,这个时候,有可能域名都无法解释,如果对于多个域名解释,是否可以进行域名的批量解释呢?一次解释所有的域名,还有部分运营商有可能对域名进行挟持,导致域名无法解释,或者解释到一个错误的地址,导致应用无法使用,特别对于我们公司的一些域名,因为牵涉到大数量的下载,导致很多运营商或者公司对我们公司的域名进行封锁,而一些非下载类应用这个时候也跟随着遭殃,催生我写个基于http协议进行域名解释dns的服务,具体实现采用nginx+lua+lua-resty-dns这个模块,具体的代码解释如下:
local cjson = require "cjson" local dns = ngx.shared.dns local args = ngx.req.get_uri_args() if args.domain == nil then ngx.say("['domain is empty, failed to query!']") ngx.exit(200) end local nameserver = {} table.insert(nameserver, '114.114.114.114') table.insert(nameserver, '8.8.8.8') ngx.say(nameserver[1]) key = args.domain .. '_' .. nameserver[1] local val = dns:get(key) if val ~= nil then ngx.say(val) ngx.exit(200) end local resolver = require "resty.dns.resolver" local r, err = resolver:new{ nameservers = nameserver, retrans = 5, -- 5 retransmissions on receive timeout timeout = 2000, -- 2 sec } if not r then ngx.say("['failed to instantiate the resolver: " .. err .. "']") return end local answers, err = r:query(args.domain) if not answers then ngx.say("['failed to query the DNS server: " .. err .. "']") ngx.exit(200) end if answers.errcode then ngx.say("['server returned error code: " .. answers.errcode .. ":" .. answers.errstr .. "']") ngx.exit(200) end local ips = {} local ttl = 0 for i, ans in ipairs(answers) do if ttl == 0 or ttl > ans.ttl then ttl = ans.ttl end if ans.type == 1 then table.insert(ips, ans.address) end --ngx.say(ans.name, " ", ans.address or ans.cname, -- " type:", ans.type, " class:", ans.class, -- " ttl:", ans.ttl) end dns:set(key, cjson.encode(ips), ttl) ngx.say(cjson.encode(ips))
另外nginx的配置如下
lua_shared_dict dns 30m; lua_package_path "/data/vhosts/lib/?.lua;;"; lua_package_cpath "/data/vhosts/lib/?.so;;"; server { listen 80; server_name dns.netzhou.net; location = /dns { default_type "text/plain"; content_by_lua_file /data/vhosts/lua/dns.lua; } }
需要安装一个lua的cjson模块,为提高性能,这里面采用了nginx的字典进行域名缓存,根据域名的ttl进行域名缓存,由于缓存了,这个时候如果一个域名对应了多个ip地址,这个时候客户端拿到的ip地址列表,顺序都是一致的,这个时候如果客户端应用都是取的第一个,就无法做到基于域名的轮询进行服务器端的负载均衡,客户端编写要注意一下进行随机选择单个ip地址。另外针对国内这个网络环境,需要区分电信,网通,铁通,移动等小运营商,普通的域名解释都是基于用户填写的dns进行域名解释,这个时候如果电信用户填写了一个网通的dns,这个时候有可能,解释到了一个网通地区去了,这个时候用户访问就会慢了,原来很多种解释方式,采用cookie,标识用户网域,或者一个单独的http server做一次302的方式,这个时候,如果采用基于http协议,进行域名解释,区分用户来源ip进行解释,可以直接加一个nginx的geo模块,或者lua里面区分用户的ip进行判断进行域名解释,具体的实现就不写了,大家可以进行扩充一下,具体实现起来比较的容易。
转载请注明:爱开源 » 通过http协议进行域名解释