技术分享 | 基于 OpenResty 权威 DNS 服务
Posted 新浪云计算
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了技术分享 | 基于 OpenResty 权威 DNS 服务相关的知识,希望对你有一定的参考价值。
最新的 nginx 已经支持 4 层服务 ngx_stream_core_module, 有了 4 层支持我们可以做更多服务,本篇我们用 OpenResty 配合 lua-resty-dns-server 做一个高性能权威 DNS 服务。
查看更多信息请参考:
http://nginx.org/en/docs/stream/ngx_stream_core_module.html
http://openresty.org/cn
https://github.com/vislee/lua-resty-dns-server
先来看下压力测试,QPS 10W/s 左右
# cat /tmp/q.txt
lb.sinacloud.com
# queryperf -s 127.0.0.1 -d /tmp/q.txt -l 30
DNS Query Performance Testing Tool
Version: $Id: queryperf.c,v 1.12 2007/09/05 07:36:04 marka Exp $
[Status] Processing input data
[Status] Sending queries (beginning with 10.23.2.241)
[Status] Testing complete
Statistics:
Parse input file: multiple times
Run time limit: 30 seconds
Ran through file: 3212709 times
Queries sent: 3212710 queries
Queries completed: 3212710 queries
Queries lost: 0 queries
Queries delayed(?): 0 queries
RTT max: 0.000836 sec
RTT min: 0.000069 sec
RTT average: 0.000153 sec
RTT std deviation: 0.000030 sec
RTT out of range: 0 queries
Percentage completed: 100.00%
Percentage lost: 0.00%
Started at: Wed Jun 19 17:05:33 2019
Finished at: Wed Jun 19 17:06:03 2019
Ran for: 30.000171 seconds
Queries per second: 107089.722922 qps
OpenResty 安装
参考: http://openresty.org/en/installation.html
lua-resty-dns-server 安装
opm install vislee/lua-resty-dns-server
常见DNS类型, 都已支持
TYPE_A
TYPE_NS
TYPE_CNAME
TYPE_SOA
TYPE_MX
TYPE_TXT
TYPE_AAAA
TYPE_SRV
TYPE_ANY
查看更多信息请参考:
https://github.com/vislee/lua-resty-dns-server
nginx.conf 配置
stream {
server {
listen 53 udp ;
content_by_lua_file conf/53.lua;
}
}
53.lua 代码
local server = require 'resty.dns.server'
local sock, err = ngx.req.socket()
if not sock then
ngx.log(ngx.ERR, "failed to get the request socket: ", err)
return ngx.exit(ngx.ERROR)
end
local req, err = sock:receive()
if not req then
ngx.log(ngx.ERR, "failed to receive: ", err)
return ngx.exit(ngx.ERROR)
end
local dns = server:new()
local request, err = dns:decode_request(req)
if not request then
ngx.log(ngx.ERR, "failed to decode request: ", err)
local resp = dns:encode_response()
local ok, err = sock:send(resp)
if not ok then
ngx.log(ngx.ERR, "failed to send: ", err)
ngx.exit(ngx.ERROR)
end
return
end
local query = request.questions[1]
ngx.log(ngx.DEBUG, "qname: ", query.qname, " qtype: ", query.qtype)
local cname = "sinacloud.com"
if query.qtype == server.TYPE_A then
local err = dns:create_a_answer(query.qname, 600, "192.168.1.1")
local err = dns:create_a_answer(query.qname, 600, "192.168.2.2")
if err then
ngx.log(ngx.ERR, "failed to create cname answer: ", err)
return
end
end
local resp = dns:encode_response()
local ok, err = sock:send(resp)
if not ok then
ngx.log(ngx.ERR, "failed to send: ", err)
return
end
dig 测试
# dig @127.0.0.1 lb.sinacloud.com
; <<>> DiG 9.9.4-RedHat-9.9.4-74.el7_6.1 <<>> @127.0.0.1 lb.sinacloud.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 45924
;; flags: qr rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available
;; QUESTION SECTION:
;lb.sinacloud.com. IN A
;; ANSWER SECTION:
lb.sinacloud.com. 600 IN A 192.168.1.1
lb.sinacloud.com. 600 IN A 192.168.2.2
;; Query time: 0 msec
;; SERVER: 127.0.0.1#(127.0.0.1)
;; WHEN: Wed Jun 19 17:27:17 CST 2019
;; MSG SIZE rcvd: 98
后续
目前只是实现了一个很简单的例子, 如果做成一个可持续的服务, 还需要很多工作, 比如:
DNS 记录可以放到Redis、mysql 或本地文件;
封装 API 接口, 可以动态修改 DNS 记录;
从 ngx.var.remote_addr 获取客户端IP, 支持智能解析;
tld 顶级域 QPS限制;
记录请求日志;
支持递归查询, 做 LocalDNS 服务等等...
以上是关于技术分享 | 基于 OpenResty 权威 DNS 服务的主要内容,如果未能解决你的问题,请参考以下文章
速致云技术分享:云时代的多面手,OpenResty在云计算领域的开源应用
HelloTalk 基于 OpenResty 的全球化探索之路
个推PPT | 基于OpenResty和Node.js的微服务架构实践