How can I read consul SRV records in my go application?

huangapple go评论98阅读模式
英文:

How can I read consul SRV records in my go application?

问题

我正在尝试为服务发现实现consul,但是我遇到了两个问题:连接到自定义DNS服务器和格式化我的net.LookupSRV()请求。

这是我在go应用程序中尝试查找的内容:

$ dig @127.0.0.1 -p 8600 serviceb.service.consul SRV

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> @127.0.0.1 -p 8600 serviceb.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 4511
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;serviceb.service.consul.    IN    SRV

;; ANSWER SECTION:
serviceb.service.consul. 0    IN    SRV    1 1 80 az1-serviceb1.node.dc1.consul.
serviceb.service.consul. 0    IN    SRV    1 1 80 az2-serviceb2.node.dc1.consul.

;; ADDITIONAL SECTION:
az1-serviceb1.node.dc1.consul. 0 IN    A    10.6.41.22
az2-serviceb2.node.dc1.consul. 0 IN    A    10.6.41.20

;; Query time: 6 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Fri May 16 15:09:28 2014
;; MSG SIZE  rcvd: 275

这是相关的代码。(我知道它是错误的,但是你可以看到我尝试做什么)

cname, addrs, err := net.LookupSRV("serviceb", "service", "consul")
log.Printf("%+v %+v %+v", cname, addrs, err)

输出结果为:

2014/05/16 15:24:31  [] lookup _serviceb._service.consul: no such host

任何帮助将不胜感激!谢谢

英文:

I am trying to implement consul for service discovery, and I am having trouble with two things: connecting to a custom DNS server, and formatting my net.LookupSRV() request.

Here is what I'm trying to look up from within my go app:

$ dig @127.0.0.1 -p 8600 serviceb.service.consul SRV

; &lt;&lt;&gt;&gt; DiG 9.8.4-rpz2+rl005.12-P1 &lt;&lt;&gt;&gt; @127.0.0.1 -p 8600 serviceb.service.consul SRV
; (1 server found)
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 4511
;; flags: qr aa rd; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 2
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;serviceb.service.consul.	IN	SRV

;; ANSWER SECTION:
serviceb.service.consul. 0	IN	SRV	1 1 80 az1-serviceb1.node.dc1.consul.
serviceb.service.consul. 0	IN	SRV	1 1 80 az2-serviceb2.node.dc1.consul.

;; ADDITIONAL SECTION:
az1-serviceb1.node.dc1.consul. 0 IN	A	10.6.41.22
az2-serviceb2.node.dc1.consul. 0 IN	A	10.6.41.20

;; Query time: 6 msec
;; SERVER: 127.0.0.1#8600(127.0.0.1)
;; WHEN: Fri May 16 15:09:28 2014
;; MSG SIZE  rcvd: 275

and here is the relevant code. (I know it's wrong, but just so you can see what I'm trying to do)

cname, addrs, err := net.LookupSRV(&quot;serviceb&quot;, &quot;service&quot;, &quot;consul&quot;)
log.Printf(&quot;%+v %+v %+v&quot;, cname, addrs, err)

and the output:

2014/05/16 15:24:31  [] lookup _serviceb._service.consul: no such host

Any help would be appreciated! thanks

答案1

得分: 4

尝试使用更锋利的工具,例如 github.com/miekg/dns 包。上次我查看它时,它允许控制几乎每个客户端设置的位,以进行 DNS 解析。

英文:

Try to use a more sharp tool such as the github.com/miekg/dns package. Last time I looked at it, it allowed to control virtually every bit of the client-side setup to do DNS resolution.

答案2

得分: 2

Consul支持严格的RFC 2782,并且可以仅使用标准库进行查找:

resolver := &net.Resolver{
	Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
		return (&net.Dialer{}).DialContext(ctx, network, "127.0.0.1:8600")
	},
}
_, addrs, err := resolver.LookupSRV(
	context.Background(), "svcname", "tcp", "consul",
)
英文:

Consul does support strict RFC 2782 and lookup can be done using the standard library only:

resolver := &amp;net.Resolver{
	Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
		return (&amp;net.Dialer{}).DialContext(ctx, network, &quot;127.0.0.1:8600&quot;)
	},
}
_, addrs, err := resolver.LookupSRV(
	context.Background(), &quot;svcname&quot;, &quot;tcp&quot;, &quot;consul&quot;,
)

答案3

得分: 1

虽然这并没有回答你的确切问题,但我发现这是一种更容易访问绿地应用程序的服务数据的方法。

使用net/http调用HTTP API非常简单:

package main
import (
    "fmt"
    "net/http"
    "io/ioutil"
)
func main() {
    resp, _ := http.Get("http://localhost:8500/v1/catalog/service/serviceb")
    body, _ := ioutil.ReadAll(resp.Body)
    fmt.Print(string(body))
}

HTTP API的基本知识在Services Guide中有文档记录。

英文:

While this doesn't answer your exact question, I find it's an easier way to access service data for greenfield apps.

It's quite easy to call the HTTP API with net/http:

package main
import (
	&quot;fmt&quot;
	&quot;net/http&quot;
	&quot;io/ioutil&quot;
)
func main() {
	resp, _ := http.Get(&quot;http://localhost:8500/v1/catalog/service/serviceb&quot;)
	body, _ := ioutil.ReadAll(resp.Body)
	fmt.Print(string(body))
}

The basics of the HTTP API are documented in the Services Guide.

答案4

得分: 1

最好的方法是使用PreparedQueries,如下所示:

import (
	"fmt"

	consulapi "github.com/hashicorp/consul/api"
)

func main() {
	config := consulapi.DefaultConfig()
	consul, err := consulapi.NewClient(config)
	if err != nil {
		fmt.Println(err)
	}

	preparedQuery := consul.PreparedQuery()
	queryID, _, err := preparedQuery.Create(&consulapi.PreparedQueryDefinition{
		Name: "DnsQuery",
		Service: consulapi.ServiceQuery{
			Service:     "serviceb",
			OnlyPassing: true,
		},
	}, &consulapi.WriteOptions{})
	if err != nil {
		fmt.Println(err)
	}

	res, _, _ := preparedQuery.Execute(queryID, &consulapi.QueryOptions{})
	for _, node := range res.Nodes {
		fmt.Println(node.Service.Address, node.Service.Port)
	}
}

你可以在这里找到更多信息。

英文:

The best way is to use PreparedQueries, as Posted here

import (
	&quot;fmt&quot;

	consulapi &quot;github.com/hashicorp/consul/api&quot;
)

func main() {
	config := consulapi.DefaultConfig()
	consul, err := consulapi.NewClient(config)
	if err != nil {
		fmt.Println(err)
	}

preparedQuery := consul.PreparedQuery()
queryID, _, err := preparedQuery.Create(&amp;consulapi.PreparedQueryDefinition{
    Name: &quot;DnsQuery&quot;,
    Service: consulapi.ServiceQuery{
        Service:     &quot;serviceb&quot;,
        OnlyPassing: true,
    },
}, &amp;consulapi.WriteOptions{})
if err != nil {
    fmt.Println(err)
}

res, _, _ := preparedQuery.Execute(queryID, &amp;consulapi.QueryOptions{})
for _, node := range res.Nodes {
    fmt.Println(node.Service.Address, node.Service.Port)
}

huangapple
  • 本文由 发表于 2014年5月16日 23:28:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/23699140.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定