Consul 按照教程搭建集群后,无法获取已注册的服务

Xavier
  • 281

题目描述

按照 Deployment Guide 搭建了3个 Server 节点的集群,然后添加了2个 Client 节点,在任意节点注册一个服务后,尝试从其他节点获取,获取不到,但是在 UI 界面可以看到. 集群日志没有发现异常信息,设置完全是按照教程进行的,至少没有查出来差异.. 提前感谢..

相关代码

服务代码

package main

import (
    "context"
    "fmt"
    "log"
    "net"
    "net/http"
    "os"
    "os/signal"
    "strings"
    "syscall"
    "time"

    "github.com/gin-gonic/gin"
    consulapi "github.com/hashicorp/consul/api"
)

const (
    serviceName string = "111"
    port        int    = 8003
)

var (
    consulEndpoint string = "0.0.0.0:8500"
)

/*
服务主体
Graceful shutdown
启动时服务注册
终止时解注册
*/
func main() {
    router := gin.Default()

    router.GET("/", func(c *gin.Context) {
        c.String(http.StatusOK, "ok")
    })

    srv := &http.Server{
        Addr:    fmt.Sprintf(":%d", port),
        Handler: router,
    }

    register()

    go func() {
        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Fatalf("listen: %s\n", err)
        }
    }()

    quit := make(chan os.Signal)
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    <-quit

    deregister()

    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    if err := srv.Shutdown(ctx); err != nil {
        log.Fatal("Server Shutdown:", err)
    }
    select {
    case <-ctx.Done():
        log.Println("timeout of 5 seconds")
    }
    log.Println("Server exiting")
}

/*
获取本机IP地址
*/
func getLocalIP() (string, error) {
    conn, err := net.Dial("udp", "8.8.8.8:53")
    if err != nil {
        return "", err
    }
    addr := conn.LocalAddr().(*net.UDPAddr)
    host := strings.Split(addr.String(), ":")[0]
    return host, nil
}

/*
服务注册
*/
func register() {
    // init client
    config := consulapi.DefaultConfig()
    config.Address = consulEndpoint
    client, err := consulapi.NewClient(config)
    if err != nil {
        log.Fatalf("Service Register Failed: %s\n", err.Error())
    }
    host, err := getLocalIP()
    if err != nil {
        log.Fatalf("Service Register Failed: %s\n", err.Error())
    }
    // define registry
    reg := &consulapi.AgentServiceRegistration{
        ID:      serviceName,
        Name:    serviceName,
        Port:    port,
        Tags:    []string{"test"},
        Address: host,
        Check: &consulapi.AgentServiceCheck{
            TCP:                            fmt.Sprintf("%s:%d", host, port),
            Timeout:                        "5s",
            Interval:                       "10s",
            Status:                         "passing",
            DeregisterCriticalServiceAfter: "30s",
        },
    }
    err = client.Agent().ServiceRegister(reg)
    if err != nil {
        log.Fatal(err.Error())
    }
    log.Println("Service Registered")
}

/*
服务解注册
*/
func deregister() {
    config := consulapi.DefaultConfig()
    config.Address = consulEndpoint
    client, err := consulapi.NewClient(config)
    if err != nil {
        log.Fatal(err)
    }
    client.Agent().ServiceDeregister(serviceName)
    log.Println("Service Deregistered")
}

调用代码

只能在注册服务的节点查到服务,其他节点拿不到任何一个服务的信息

package main

import (
    "net"
    "fmt"
    "log"
    "strings"

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


const (
    serviceName string = "111"
)

var (
    consulEndpoint string
)


func main() {
    host, err := getLocalIP()
    if err != nil {
        log.Fatal(err)
    }

    consulEndpoint = fmt.Sprintf("%s:8500", host)
    config := consulapi.DefaultConfig()
    config.Address = consulEndpoint
    client, err := consulapi.NewClient(config)
    if err != nil {
        log.Fatal(err)
    }
    services, _ := client.Agent().Services()
    if len(services) == 0 {
        log.Fatal("No Services")
    }
    for k, v := range services {
        fmt.Println(k)
        fmt.Printf("%#v", v)
    }

    service, qm, err := client.Agent().Service(serviceName, nil)
    if err != nil {
        log.Fatal("Get Service Failed:", err)
    }
    fmt.Printf("%#v\n", service)
    fmt.Printf("%#v\n", qm)
}


func getLocalIP() (string, error) {
    conn, err := net.Dial("udp", "8.8.8.8:53")
    if err != nil {
        return "", err
    }
    addr := conn.LocalAddr().(*net.UDPAddr)
    host := strings.Split(addr.String(), ":")[0]
    return host, nil
}
评论
阅读 181
1 个回答

刚刚找到一个解决方案,自问自答一下..

client.Agent().Services() 获取的内容不完整,看起来只能获取本地 Agent 上注册的服务。如果要获取整个集群完整同步的信息,需要使用 client.Catalog().Services(nil)

集群的配置也不知道有没有问题,参考了网上很多人的代码,全都是使用的 Agent,但是我用就是没办法获取其他节点的服务信息。后面还要继续了解一下 Agent 的 Gossip Protocol

另外就是查看文档之后才了解到 Catalog 这一层。 Catalog HTTP APIAgent HTTP API 这块儿还要再了解一下。

就算解决了一半吧,希望对其他遇到这个问题的人有帮助,也希望有大佬或者前辈能给出更准确的解答。

再来补充两个参考:
Consul difference between agent and catalog
Anti-Entropy

对不起,打扰了

撰写回答

登录后参与交流、获取后续更新提醒

宣传栏