开发者

一文详解Golang中consul的基本使用

开发者 https://www.devze.com 2023-03-07 10:52 出处:网络 作者: 白象孙国帅
目录consulconsul的安装和部署docker安装consul镜像的启动启动一个tcp_health_check的服务注册http版服务发现consul
目录
  • consul
  • consul的安装和部署
    • docker安装
    • consul镜像的启动
  • 启动一个tcp_health_check的服务注册
    • http版
  • 服务发现

    consul

    consul是一个开源服务注册和服务发现的中心,可以用于微服务的注册和服务之间的调用的发现,帮助上游服务找到下游服务的具体ip:port或者是domain,也可以使用dns的方式让consul帮你去做转发,具体介绍请看consul的官网,consul区分server-agent和client-agent,client-agent的作用一般来说就是用来转发到server-agent的,所以本文只启动server-agent,他们的详细差距可以在google上查到,本文基于golang实现一个服务注册和服务发现的demo。demo地址

    consul的安装和部署

    consul有两种部署模式,一种是直接在cvm上安装consul的bin包,然后以server-agent的模式进行启动,一种是用docker直接启动镜像,本文直接使用docker启动镜像,将这个镜像的启动参数设置为server-agent,在这种模式下,如果要使用服务发现的功能需要区分主机ip和容器ip 不能使用127.0.0.1这种ip去让server维持go服务的心跳

    本文使用的cvm系统为Centos8,其他linux发行版可以自行用包管理工具去安装一下的前置依赖

    docker安装

    curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

    systemctl start docker

    使用上文脚本一键安装docker

    consul镜像的启动

    docker pull consul

    docker run -d -p 8500:8500 -v ~/consul:/consul/data -e CONSUL_BIND_INTERFACE='eth0' --name=consul1 consul agent -server -bootstrap -ui -client='0.0.0.0'

    两步启动一个consul的server-agent,然后就可以通过ip:8www.devze.com500访问得到consul的一个web界面,如果ip访问不通可python以使用下文的vscode的代理模式去访问或者是在自己厂商的cvm控制台去开端口的访问策略,web界面如下

    一文详解Golang中consul的基本使用

    启动一个tcp_health_check的服务注册

    创建一个go项目

    mkdir consul_demo

    go mod init consul_demo

    go get -u github.com/hashicorp/consul/api

    touch main.go

    // main.go
    package main
    
    import (
    	"bufio"
    	"fmt"
    	"net"
    
    	consulapi "github.com/hashicorp/consul/api"
    )
    
    type DiscoveryConfig struct {
    	ID      string
    	Name    string
    	Tags    []string
    	Port    int
    	Address string
    }
    
    var consulAddress = "127.0.0.1:8500"
    
    func RegisterService(dis DiscoveryConfig) error {
    	config := consulapi.DefaultConfig()
    	config.Address = consulAddress
    	client, err := consulapi.NewClient(config)
    	if err != nil {
    		fmt.Printf("create consul client : %v\n", err.Error())
    	}
    	registration := &consulapi.AgentServiceRegistration{
    		ID:      dis.ID,
    		Name:    dis.Name,
    		Port:    dis.Port,
    		Tags:    dis.Tags,
    		Address: dis.Address,
    	}
    	// 启动tcp的健康检测,注意address不能使用127.0.0.1或者localhost,因为consul-agent在docker容器里,如果用这个的话,
    	// consul会访问容器里的port就会出错,一直检查不到实例
    	check := &consmbWJgLYXHyulapi.AgentServiceCheck{}
    	check.TCP = fmt.Sprintf("%s:%d", registration.Address, registration.Port)
    	check.Timeout = "5s"
    	check.Interval = "5s"
    	check.DeregisterCriticalServiceAfter = "60s"
    	registration.Check = check
    
    	if err := client.Agent().ServiceRegister(registration); err != nil {
    		fmt.Printf("register to consul error: %v\n", err.Error())
    		return err
    	}
    	return nil
    }
    
    func startTcp() {
    	ls, err := net.Listen("tcp", ":10111")
    	if err != nil {
    		fmt.Printf("start tcp listener error: %v\n", err.Error())
    		return
    	}
    	for {
    		conn, err := ls.Accept()
    		if err != nil {
    			fmt.Printf("connect error: %v\n", err.Error())
    		}
    		go func(conn net.Conn) {
    			_, err := bufio.NewWriter(conn).WriteString("hello consul")
    			if err != nil {
    				fmt.Printf("write conn error: %v\n", err)
    			}
    		}(conn)
    	}
    }
    func main() {
    	ch := make(chan error)
    	dis := DiscoveryConfig{
    		ID:      "9527",
    		Name:    "main_service",
    		Tags:    []string{"a", "b"},
    		Port:    10111,
    		Address: "192.168.0.124", //通过ifconfig查看本机的eth0的ipv4地址
    	}
    	go startTcp()
    	RegisterService(dis)
    	// 阻塞等待
    	<-ch
    }

    然后我们运行这个代码

    go run main.go

    就可以看到consul的web界面上多了一个服务实例

    一文详解Golang中consul的基本使用

    一文详解Golang中consul的基本使用

    http版

    如果不使用tcp作为健康检查的方式,可以使用Http_server去实现,逻辑是一样的,需要给consul返回一个消息,让consul确认你的心跳即可

    check := &consulapi.AgentServiceCheck{}
    check.HTTP = fmt.Sprintf("http://%s:%d/", registration.Address, registration.Port)
    
    func startHttp() {
    	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    		fmt.Printf("consul get uri: %s\n", r.RequestURI)
    		w.Write([]byte("hello consul"))
    	})
    	if err := http.ListenAndServe(":1011mbWJgLYXHy1", nil); err != nil {
    		fmt.Printf("start http server error: %v\n", err)
    	}
    }
    go startHttp()
    

    一文详解Golang中consul的基本使用

    服务发现

    服务发现其实就是通过http请求向consul请求指定的service下的实例,获取到他们对应的ip:port和一些其他的元信息,然后在客户端根据需要筛选得出一个ip:port的实例进行通讯,由于向consul发起http请求的sdk已经在consul官方实现了,所以我们不需要自己建一个httpclient去调用这些api,而是直接构建一个struct交给sdk去查询即可

    package main
    
    import (
    	"fmt"
    	"testing"
    
    	consulapi "github.com/hashicorp/consul/api"
    )
    
    func Discovery(serviceName string) []*consulapi.ServiceEntry {
    	config := consulapi.DefaultConfig()
    	config.Address = "127.0.0.1:8500"
    	cpythonlient, err := consulapi.NewClient(config)
    	if err != nil {
    		fmt.Printf("consul client error: %v", err)
    	}
    	service, _, err := client.Health().Service(serviceName, "", false, nil)
    	if err != nil {
    		fmt.Printf("consul client get serviceIp error: %v", err)
    	}
    	return service
    }
    
    func TestDiscoeryFromConsul(t *testing.T) {
    	t.Logf("client discovery start")
    	se := Discovery("main_service")
    	for i := 0; i < len(se); i++ {
    		t.Logf("the instance Node is %+v\n", se[i].Node)
    		t.Logf("the isntance Service is %+v\n", se[i].Service)
    		t.Logf("\n")
    	}
    }
    

    ut的结果如下,证明我们通过consul找到了下游服务的ip:port即可发起通讯

    [root@hecs-74066 consul_demo]# go test -v main_test.go 

    === RUN   TestDiscoeryFromConsul

        main_test.go:25: client discovery start

        main_test.go:28: the instance Node is &{ID:278ba4f1-0309-fc92-d641-a312b5797779 Node:241f8a20d7fb Address:172.17.0.2 Datacenter:dc1 TaggedAddresses:map[lan:172.17.0.2 lan_ipv4:172.17.0.2 wan:172.17.0.2 wan_ipv4:172.17.0.2] Meta:map[consul-network-segment:] CreateIndex:13 ModifyIndex:16 Partition: PeerName:}

        main_test.go:29: the isntance Service is &{Kind: ID:9527 Service:main_service Tags:[a b] Meta:map[] Port:10111 Address:192.168.0.124 SocketPath: TaggedAddresses:map[lan_ipv4:{Address:192.168.0.124 Port:10111} wan_ipv4:{Address:192.168.0.124 Port:10111}] Weights:{Passing:1 Warning:1} EnableTagOverride:false CreateIndex:开发者_C开发43 ModifyIndex:43 ContentHash: Proxy:0xc0000c44d0 Connect:0xc000091a50 PeerName: Namespace: Partition: Datacenter:}

        main_test.go:30: 

    --- PASS: TestDiscoeryFromConsul (0.00s)

    到此这篇关于一文详解Golang中consul的基本使用的文章就介绍到这了,更多相关Golang consul内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

    0

    精彩评论

    暂无评论...
    验证码 换一张
    取 消