DNS是consul提供的主要查询接口之一。DNS接口允许应用程序在没有与consul高度集成的情况下使用服务发现。
例如:替代consul的HTTP API请求,主机能够通过名字查找直接使用DNS服务器,类似"redis.service.east-aws.consul",此查询自动转换为查找位于数据中心"east-aws"节点提供的redis服务——没有故障的redis健康检查。它是如此简单!
如果要使用DNS接口,必须配置一些重要的参数client_addr, ports.dns, recursors, dns_config等。
默认情况下,Consul监听127.0.0.1:8600,使用.consul域提供DNS查询服务,但不支持进一步的DNS递归。
相关参数请参考https://www.consul.io/docs/agent/options.html
使用DNS接口的方法有多种。
一种方法是在consul中自定义DNS解析器动态库。另一个方法是为节点设置Consul的DNS服务器,并提供recursors配置,也可以解决non-Consul查询。最后一种方法是将所有的关于"consul."域的查询都从现有的DNS服务器转移consul Agent。
可以尝试使用的Consul DNS服务器的命令行工具dig:
$ dig @127.0.0.1 -p8600 redis.service.dc1.consul. ANY
注:在DNS中,都是不区分大小写的。比如PostgreSQL.node.dc1.consul会查询所有节点中名字为postgresql的节点。
要解决名称,Consul依赖于非常具体的查询格式。基本上有两种类型的查询:节点查找和服务查找。
节点查找,类似如下:包含节点的address
<node>.node[.datacenter].<domain>
例如,如果有默认节点“foo”,可以查找“foo.node.dc1.consul.”其中数据中心名称dc1是可选参数,如果不提供,Agent将选择默认数据中心——agent肯定属于一个数据中心。可以采用"foo.node.consul."进行查找,本约束可以在适当的地方使用,同时支持在远程数据中心得节点查询。
节点查找,唯一的返回记录——包含节点IP地址的A记录。
$ dig @127.0.0.1 -p8600 foo.node.consul ANY ; <<>>DiG 9.8.3-P1 <<>> @127.0.0.1 -p 8600 foo.node.consul ANY ; (1 server found) ;; global options:+cmd ;; Got answer: ;;->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24355 ;; flags: qr aa rd;QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 0 ;; WARNING: recursionrequested but not available ;; QUESTION SECTION: ;foo.node.consul. IN ANY ;; ANSWER SECTION: foo.node.consul. 0 IN A 10.1.10.12 ;; AUTHORITYSECTION: consul. 0 IN SOA ns.consul.postmaster.consul. 1392836399 3600 600 86400 0
服务查找用于查询服务提供者。服务查询支持两种查找方法:标准和严格RFC 2782。
格式如下:
[tag.]<service>.service[.datacenter].<domain>
Tag是可选的,而且与节点查找一样,数据中心也是可选。如果没有提供Tag,就不会有过滤,如果没有数据中心,就会选择默认的数据中心。
在本地数据中心,如果想查找redis服务提供商,可以通过命令"redis.service.consul.",如果想在指定的数据中心中查找PostgreSQL master,命令如下"master.postgresql.service.dc2.consul."
DNS查询系统利用健康检查以防止不良节点路由信息。当服务查询时,如果服务健康检查失败或者系统检查失败,服务信息将会从查询结果中删除。为了实现简单的负载平衡,返回的节点集合每次都是随机的。这种机制使得利用DNS接口基于应用级重试实现面向auto-healing服务体现架构变得更加容易。
标准服务查询,不但支持A record,还支持SRV record。。SRV reconds提供服务注册的端口,使客户能够避免依赖于众所周知的端口。只有client端指定时,SRV record才会提供服务。命令如下:
$ dig @127.0.0.1 -p8600 consul.service.consul SRV ; <<>>DiG 9.8.3-P1 <<>> @127.0.0.1 -p 8600 consul.service.consul ANY ; (1 server found) ;; global options:+cmd ;; Got answer: ;;->>HEADER<<- opcode: QUERY, status: NOERROR, id: 50483 ;; flags: qr aa rd;QUERY: 1, ANSWER: 3, AUTHORITY: 1, ADDITIONAL: 1 ;; WARNING:recursion requested but not available ;; QUESTION SECTION: ;consul.service.consul. IN SRV ;; ANSWER SECTION: consul.service.consul. 0 IN SRV 1 1 8300foobar.node.dc1.consul. ;; ADDITIONALSECTION: foobar.node.dc1.consul.0 IN A 10.1.10.12
格式如下:
_<service>._<protocol>.service[.datacenter][.domain]
根据RFC 2782, SRV请求都应该在service和protocol前使用(_)作为前缀。避免发生DNS冲突。Protocol可以是service任何一个tag,如果service没有tag,使用tcp作为protocol。如果一旦设置了tcp,那么查询时将不会执行任何标签过滤。
处理查询格式和默认的tcp外, RFC查找方式与标准查找是相同的。
假设通过port5672和Tag “amqp”注册服务"rabbitmq",可以发现RFC2782的SRV查询,如"_rabbitmq._amqp.service.consul":
$ dig @127.0.0.1 -p8600 _rabbitmq._amqp.service.consul SRV ; <<>>DiG 9.8.3-P1 <<>> @127.0.0.1 -p 8600 _rabbitmq._amqp.service.consulANY ; (1 server found) ;; global options:+cmd ;; Got answer: ;;->>HEADER<<- opcode: QUERY, status: NOERROR, id: 52838 ;; flags: qr aa rd;QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; WARNING:recursion requested but not available ;; QUESTION SECTION: ;_rabbitmq._amqp.service.consul. IN SRV ;; ANSWER SECTION: _rabbitmq._amqp.service.consul.0 IN SRV 1 1 5672 rabbitmq.node1.dc1.consul. ;; ADDITIONALSECTION: rabbitmq.node1.dc1.consul. 0 IN A 10.1.11.20
再次说明,SRV record返回的是服务端口和IP。
格式如下:
<query orname>.query[.datacenter].<domain>
其中datacenter是可选参数,若不提供,则选择本地数据中心,Query或name是现已存在PreparedQuery的ID和名称。
就像标准服务查询,但是PreparedQuery查询提供了更为丰富的功能,比如:多重tag过滤,自动故障转移——当本地服务中心无有效健康节点时自动到远程数据中心的进行服务寻找。
Consul 0.6.4及后续版本,都支持prepared query templates——支持前缀匹配,支持一对多模板。
若DNS查询使用UDP,COnsul将截断查询结果单不设置截断点。这是为了避免为TCP产生附加负担。如果使用TCP,结果不会被截断。
默认情况下,Consul提供的所有DNS结果都设置为 0TTL值。这种方式会禁用DNS结果的caching。但是,在很多场景中,都是希望使用caching的,比如性能和可扩展性。
详情参加DNS caching
默认情况下,Consul DNS查询返回的是节点的本地IP地址,即使查询的是远程的数据中心。如果需要使用不同的IP地址访问数据中心外部的节点,可以配置advertise-wan
和translate_wan_addrs
。