golang入门consul(docker版)

使用Go入门学习Consul服务注册与发现

第一步:Centos7中安装并启动consul

很简单,在安装有Docker的基础之上,拉consul的最新镜像,指令:【 docker pull consul 】即可完成
拉完consul的镜像之后,用该镜像跑三个容器,分别是consul的三个实例作为集群。实现如下,编写一个start.sh

echo -e "\033[33m 是否启动consul\033[0m"
echo "y 是"
echo "n 否"
read start_con
if [ $start_con == "y" ] 
then
    JOIN_IP="$(docker inspect -f '{{.NetworkSettings.IPAddress}}' consul_server_1_master)";
    docker stop $(docker ps | grep consul | awk '{print $1}')
    docker rm $(docker ps -qf status=exited)
    docker run -d -p 8500:8500 --restart=always -v /data/consul/data/server1:/consul/data -v /data/consul/conf/server1:/consul/config -e CONSUL_BIND_INTERFACE='eth0' --privileged=true --name=consul_server_1_master consul:latest agent -server -bootstrap-expect=2 -ui -node=consul_server_1_master -client='0.0.0.0' -data-dir /consul/data -config-dir /consul/config -datacenter=dc1;
    docker run -d -p 8501:8500 --restart=always -v /data/consul/data/server2:/consul/data -v /data/consul/conf/server2:/consul/config -e CONSUL_BIND_INTERFACE='eth0' --privileged=true --name=consul_server_2 consul:latest agent -server -ui -node=consul_server_2 -client='0.0.0.0' -datacenter=dc1 -data-dir /consul/data -config-dir /consul/config -join=$JOIN_IP
    docker run -d -p 8502:8500 --restart=always -v /data/consul/data/server3:/consul/data -v /data/consul/conf/server3:/consul/config -e CONSUL_BIND_INTERFACE='eth0' --privileged=true --name=consul_server_3 consul:latest agent -server -ui -node=consul_server_3 -client='0.0.0.0' -datacenter=dc1 -data-dir /consul/data -config-dir /consul/config -join=$JOIN_IP
fi

其中
在这里插入图片描述
是为了获取leader实例的ip地址,然后让后面两个follower实例加入他的集群。
直接跑上面的脚本就可以run了三个容器,然后consul集群就搭建好了,接下来打开网址:【http://localhost:8500/ui/dc1/services】 就可以看到具体三个实例
在这里插入图片描述

现在环境搭建好了,就用go实现一个小例子,一共就两个文件分别是server层的main.go和client层的main.go
server/main.go

package main
import (
	"fmt"
	"io"
	"net"

	"net/http"

	consulapi "github.com/hashicorp/consul/api"
)
const RECV_BUF_LEN = 1024
//服务的健康检测
func consulCheck(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "consulCheck")
}
func registerServer() {
	config := consulapi.DefaultConfig()
	client, err := consulapi.NewClient(config)
	if err != nil {
		fmt.Println("consul client error : ", err)
	}
	checkPort := 8080
	registration := new(consulapi.AgentServiceRegistration)
	registration.ID = "serverNode_1"
	registration.Name = "serverNode"
	registration.Port = 9527 //提供服务的端口号
	registration.Tags = []string{"serverNode"}
	registration.Address = localIP()                   //获取提供服务的ip
	registration.Check = &consulapi.AgentServiceCheck{ //自动检测服务健康状况
		HTTP:                           fmt.Sprintf("http://%s:%d%s", registration.Address, checkPort, "/check"),
		Timeout:                        "3s",
		Interval:                       "5s",
		DeregisterCriticalServiceAfter: "30s", //check失败后30秒删除本服务
	}
	err = client.Agent().ServiceRegister(registration) //将服务注册进代理
	if err != nil {
		fmt.Println("register server error : ", err)
	}
	fmt.Println("register server success.")
	http.HandleFunc("/check", consulCheck) //健康检测接口的声明
	http.ListenAndServe(fmt.Sprintf(":%d", checkPort), nil)

}
func main() {
	go registerServer()                          //去consul注册服务
	ln, err := net.Listen("tcp", "0.0.0.0:9527") //开始监听本端口的请求
	if nil != err {
		panic("Error: " + err.Error())
	}
	for {
		conn, err := ln.Accept() //拿到请求连接
		if err != nil {
			panic("Error: " + err.Error())
		}
		go EchoServer(conn) //异步处理请求~
	}
}
//以下就是对连接进行处理,简单的消息传递
func EchoServer(conn net.Conn) {
	buf := make([]byte, RECV_BUF_LEN)
	defer conn.Close()
	for {
		n, err := conn.Read(buf)
		switch err {
		case nil:
			fmt.Println("get and echo:", "EchoServer "+string(buf[0:n]))
			conn.Write(append([]byte("EchoServer "), buf[0:n]...))
		case io.EOF:
			fmt.Printf("Warning: End of data: %s\n", err)
			return
		default:
			fmt.Printf("Error: Reading data: %s\n", err)
			return
		}
	}
}
//获取本机ip地址
func localIP() string {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return ""
	}
	for _, address := range addrs {
		if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
			if ipnet.IP.To4() != nil {
				return ipnet.IP.String()
			}
		}
	}
	return ""
}

client/main.go

package main
import (
	"fmt"
	"net"
	"time"

	consulapi "github.com/hashicorp/consul/api"
)
const RECV_BUF_LEN = 1024
func main() {
	client, err := consulapi.NewClient(consulapi.DefaultConfig()) //初始化一个默认配置的consul客户端
	if err != nil {
		fmt.Println("consul client error : ", err)
	}
	for {
		time.Sleep(time.Second * 3)
		var services map[string]*consulapi.AgentService
		var err error
		services, err = client.Agent().Services() //获取所有代理的服务[服务发现]
		if nil != err {
			fmt.Println("in consual list Services:", err)
			continue
		}
		if _, found := services["serverNode_1"]; !found { //找到我们server注册的serverNode_1服务
			fmt.Println("consul_server not found")
			continue
		}
		sendData(services["serverNode_1"]) 获取到consul代理的服务然后进行处理
	}
}
func sendData(service *consulapi.AgentService) {
	conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", service.Address, service.Port)) //拨号连接
	if err != nil {
		fmt.Println(err)
		return
	}
	defer conn.Close()
	buf := make([]byte, RECV_BUF_LEN)
	i := 0
	for {
		i++
		msg := fmt.Sprintf("Hello World, %03d", i)
		n, err := conn.Write([]byte(msg)) //发消息
		if err != nil {
			println("Write Buffer Error:", err.Error())
			break
		}
		n, err = conn.Read(buf) //收消息
		if err != nil {
			println("Read Buffer Error:", err.Error())
			break
		}
		fmt.Println("get:", string(buf[0:n]))
		//等一秒钟
		time.Sleep(time.Second)
	}
}

以上就是server和client的代码实现,执行顺序是先跑server层的main之后可以在consul的ui网址那里可以看到我们刚刚注册的服务:名为【serverNode】已经注册进去了
在这里插入图片描述
点进去看看,
在这里插入图片描述
其中如下图所示打勾了就是自动检测该服务是健康的,如果你改动了如下的Check的网址是返回非200的就会打×在这里插入图片描述
好了现在服务注册进去了,在跑一下client的main的话可以看到如下内容既是成功:
在这里插入图片描述
在这里插入图片描述
到这里本文就结束了,记录自己学习go+consul的结果,分享一下给那些可能不那么熟悉或者过程有点坎坷的小伙伴。
感谢观看。

本文参考的文献有:
https://www.cnblogs.com/chaselogs/p/11462954.html
https://github.com/changjixiong/goNotes/blob/master/consulnotes/ 【源码内容,不全是】
https://www.cnblogs.com/dayang12525/p/13889429.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值