最新消息:

通过http协议进行域名解释

http admin 4031浏览 0评论

对于互联网的应用来说,域名是互联网的基础,几乎所有的应用都牵涉到域名的解释,而随着移动互联网的发展,网络的延迟不再是几十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协议进行域名解释

您必须 登录 才能发表评论!