如何在openresty里解析域名

如何在openresty里解析域名,第1张

比如在使用 Mysql 实例时某些云会给一个私有的域名搭配自有的 nameserver 使用

local client = mysql:new()

client:connect({

host = "rdsmxxxxxx.mysql.rds.xxxx.com",

port = 3306,

database = "test",

user = "test",

password = "123456"

})

以上代码在直接使用时往往会报一个无法解析的错误。那么怎么在 openresty 中使用域名呢

搭配 resolver 指令

我们可以直接在 nginx 的配置文件中使用 resolver 指令直接设置使用的 nameserver 地址。

官方文档中是这么描述的

Syntax: resolver address ... [valid=time] [ipv6=on|off]

Default: —

Context: http, server, location

一个简单的例子

resolver 8.8.8.8 114.114.114.114 valid=3600s

不过这样的问题在于 nameserver 被写死在配置文件中,如果使用场景比较复杂或有内部 dns服务时维护比较麻烦。

进阶玩法

我们的代码常常运行在各种云上,为了减少维护成本,我采用了动态读取本机 /etc/resolv.conf 的方法来做。

废话不说,让我们一赌为快。

local pcall = pcall

local io_open = io.open

local ngx_re_gmatch = ngx.re.gmatch

local ok, new_tab = pcall(require, "table.new")

if not ok then

new_tab = function (narr, nrec) return {} end

end

local _dns_servers = new_tab(5, 0)

local _read_file_data = function(path)

local f, err = io_open(path, 'r')

if not f or err then

return nil, err

end

local data = f:read('*all')

f:close()

return data, nil

end

local _read_dns_servers_from_resolv_file = function()

local text = _read_file_data('/etc/resolv.conf')

local captures, it, err

it, err = ngx_re_gmatch(text, [[^nameserver\s+(\d+?\.\d+?\.\d+?\.\d+$)]], "jomi")

for captures, err in it do

if not err then

_dns_servers[#_dns_servers + 1] = captures[1]

end

end

end

_read_dns_servers_from_resolv_file()

通过上述代码我们成功动态拿到了一组 nameserver 的地址,下面就可以通过 resty.dns.resolver 大杀四方了

local require = require

local ngx_re_find = ngx.re.find

local lrucache = require "resty.lrucache"

local resolver = require "resty.dns.resolver"

local cache_storage = lrucache.new(200)

local _is_addr = function(hostname)

return ngx_re_find(hostname, [[\d+?\.\d+?\.\d+?\.\d+$]], "jo")

end

local _get_addr = function(hostname)

if _is_addr(hostname) then

return hostname, hostname

end

local addr = cache_storage:get(hostname)

if addr then

return addr, hostname

end

local r, err = resolver:new({

nameservers = _dns_servers,

retrans = 5, -- 5 retransmissions on receive timeout

timeout = 2000, -- 2 sec

})

if not r then

return nil, hostname

end

local answers, err = r:query(hostname, {qtype = r.TYPE_A})

if not answers or answers.errcode then

return nil, hostname

end

for i, ans in ipairs(answers) do

if ans.address then

cache_storage:set(hostname, ans.address, 300)

return ans.address, hostname

end

end

return nil, hostname

end

ngx.say(_get_addr("www.baidu.com"))

ngx.say(_get_addr("192.168.0.1"))

我这边把解析的结果放入了 lrucache 缓存了5分钟,你们同样可以把结果放入 shared 中来减少 worker 查询次数。

高阶玩法

现在我们已经实现了自缓存体系的 dns 查询,如果搭配 resty.http 就会达到更好的效果。

一个简单的例子是,通过解析 uri 得到 hostname 、 port 、 path ,把 hostname 扔给自缓存 dns 获取结果

发起 request 请求, addr + port connect 之,设置 header 的 host 为 hostname , path等值来实现 ip 直接访问等高阶用法。

这里就不过多的阐述了。

最终的演示例子如下

local client = mysql:new()

client:connect({

host = _get_addr(conf.mysql_hostname),

port = 3306,

database = "test",

user = "test",

password = "123456"

})

解析未匹配是因为没有添加自己的主机ip地址,解决步骤如下:

1、首先第一步就是要进行登陆上后我们在左边的快捷栏里面找到域名和网站按钮然后接着点击云解析DNS按钮即可。

2、接着就是进入到云解析里面后,这时候注意的是就可以看到域名,没有域名的添加一个进入,然后在右边找到解析设置按钮,如下图所示。

3、然后就是进入到域名解析设置里面后这时候看到上方的新手引导按钮,然后点击新手引导按钮即可。

4、最后一步就是要进入新手引导页面后然后进行添加自己的主机ip地址,最后点击确定就完成了。


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/324466.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-05-02
下一篇2023-05-02

发表评论

登录后才能评论

评论列表(0条)

    保存