skynet框架应用 (十一) 域名查询

11 域名查询

​ 在 skynet 的底层,当使用域名而不是 ip 时,由于调用了系统 api getaddrinfo ,有可能阻塞住整个 socket 线程(不仅仅是阻塞当前服务,而是阻塞整个 skynet 节点的网络消息处理)。虽然大多数情况下,我们并不需要向外主动建立连接。但如果你使用了类似 httpc 这样的模块以域名形式向外请求时,一定要关注这个问题。

​ skynet 暂时不打算在底层实现非阻塞的域名查询。但提供了一个上层模块来辅助你解决 dns 查询时造成的线程阻塞问题。

local dns = require "skynet.dns"

​ 在使用前,必须设置 dns 服务器。

  • dns.server(ip, port) : port 的默认值为 53 。如果不填写 ip 的话,将从 /etc/resolv.conf 中找到合适的 ip 。

  • dns.resolve(name, ipv6) : 查询 name 对应的 ip ,如果 ipv6 为 true 则查询 ipv6 地址,默认为 false 。如果查询失败将抛出异常,成功则返回 ip ,以及一张包含有所有 ip 的 table 。

  • dns.flush() : 默认情况下,模块会根据 TTL 值 cache 查询结果。在查询超时的情况下,也可能返回之前的结果。dns.flush() 可以用来清空 cache 。注意:cache 保存在调用者的服务中,并非针对整个 skynet 进程。所以,推荐写一个独立的 dns 查询服务统一处理 dns 查询。

11.1 DNS简单使用

示例代码:test_dns.lua

local skynet = require "skynet"
local dns = require "skynet.dns"

skynet.start(function()
    skynet.error("nameserver:", dns.server())   --设置DNS服务器地址
    -- you can specify the server like dns.server("8.8.4.4", 53)
    
    local ip, ips = dns.resolve "github.com"  --调用成功,则把结果缓存到这个服务的内存中,便于下次使用
    skynet.error("dns.resolve return:", ip)
    
    for k,v in ipairs(ips) do
        skynet.error("github.com",v)
    end
    dns.flush()
end)

运行结果:

$ ./skynet examples/config
test_dns
[:01000010] LAUNCH snlua test_dns
[:01000010] nameserver: 127.0.1.1
[:01000010] dns.resolve return: 192.30.255.112  #返回查询到的ip地址
[:01000010] github.com 192.30.255.112
[:01000010] github.com 192.30.255.113

11.2 封装一个DNS服务

​ 由于每个服务去调用dns接口查询IP时都会在这个服务上缓存一份,下次查询的时候速度就会快很多,但是如果每个服务都保存一份,显示是浪费了资源空间,下面我们来封装用"lua"消息进行查询的DNS服务。

示例代码:dnsservice.lua

local skynet = require "skynet"
require "skynet.manager"
local dns = require "skynet.dns"
    
local command = {}

function command.FLUSH()
    return dns.flush()
end


function command.GETIP(domain)
    return dns.resolve(domain)
end

skynet.start(function()
    dns.server()
    skynet.dispatch("lua", function(session, address, cmd, ...)
        cmd = cmd:upper()  
        local f = command[cmd] 
        if f then
            skynet.retpack(f(...))
        else
            skynet.error(string.format("Unknown command %s", tostring(cmd)))
        end
    end)
    skynet.register ".dnsservice" 
end)

测试代码:testdnsservice.lua

local skynet = require "skynet" 
local cmd,domain = ...
function task()
    local r, ips = skynet.call(".dnsservice", "lua", cmd, domain)
    skynet.error("dnsservice Test:", domain, r)
    skynet.exit()
end
skynet.start(function()
    skynet.fork(task)
end)

运行结果:

$ ./skynet examples/config
dnsservice
[:01000010] LAUNCH snlua dnsservice
testdnsservice getip www.baidu.com
[:01000012] LAUNCH snlua testdnsservice getip www.baidu.com
[:01000012] dnsservice Test 14.215.177.39
[:01000012] KILL self

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值