很简单,在安装有Docker的基础之上,拉consul的最新镜像,指令:【 docker pull consul 】即可完成
拉完consul的镜像之后,用该镜像跑三个容器,分别是consul的三个实例作为集群。实现如下,编写一个start.sh
echo -e "3[33m 是否启动consul3[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 }')
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
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)