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

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

搭配 resolver 指令

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

官方文档中是这么描述的

  1. Syntax: resolver address ... [valid=time] [ipv6=on|off];
  2. Default:
  3. Context: http, server, location

一个简单的例子

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

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

  1. local pcall = pcall
  2. local io_open = io.open
  3. local ngx_re_gmatch = ngx.re.gmatch
  4. local ok, new_tab = pcall(require, "table.new")
  5. if not ok then
  6. new_tab = function (narr, nrec) return {} end
  7. end
  8. local _dns_servers = new_tab(5, 0)
  9. local _read_file_data = function(path)
  10. local f, err = io_open(path, 'r')
  11. if not f or err then
  12. return nil, err
  13. local data = f:read('*all')
  14. f:close()
  15. return data, nil
  16. end
  17. local _read_dns_servers_from_resolv_file = function()
  18. local text = _read_file_data('/etc/resolv.conf')
  19. it, err = ngx_re_gmatch(text, [[^nameserver\s+(\d+?\.\d+?\.\d+?\.\d+$)]], "jomi")
  20. for captures, err in it do
  21. if not err then
  22. _dns_servers[#_dns_servers + 1] = captures[1]
  23. end
  24. end
  25. end
  26. _read_dns_servers_from_resolv_file()

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

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

高阶玩法

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

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

这里就不过多的阐述了。

  1. local client = mysql:new()
  2. client:connect({
  3. host = _get_addr(conf.mysql_hostname),
  4. port = 3306,
  5. database = "test",
  6. user = "test",
  7. password = "123456"

如何使用 /etc/hosts 自定义域名

还有些同学可能会在 hosts 文件中自定义域名和 ip,这时候 resolve 是无法正常解析的。

这个时候可以借助 dnsmasq 这个服务来缓存我们的 dns 结果,hosts 的定义可以被该服务识别。

需要在 nginx 的配置文件中,设置 resolver 为 服务的监听地址即可。