微服务系列Consul的介绍与安装
Posted 清风拂山岗
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微服务系列Consul的介绍与安装相关的知识,希望对你有一定的参考价值。
微服务系列(三)Consul的介绍与安装
1.Consul简介
Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置。包含多个组件,但是作为一个整体,为你的基础设施提供服务发现和服务配置的工具.他提供以下关键特性:
-
服务发现:consul提供服务,服务端主动向consul发起注册。
-
健康检查:健康检测使consul可以快速的告警在集群中的操作。和服务发现的集成,可以防止服务转发到故障的服务上面。(心跳机制)
-
键/值存储:一个用来存储动态配置的系统。提供简单的HTTP接口,可以在任何地方操作。
-
多数据中心:无需复杂的配置,即可支持任意数量集群搭建。
2.Consul 安装说明
Consul用Golang实现,因此具有天然可移植性 (支持 Linux、windows和macOS)。安装包仅包含一个可执行文件。 Consul安装非常简单,只需要下载对应系统的软件包并解压后就可使用。
安装步骤如下:
# 这里以 ubuntu系统为例:
$ wget https://releases.hashicorp.com/consul/1.5.2/consul_1.5.2_linux_amd64.zip
$ unzip consul_1.5.2_linux_amd64.zip
$ sudo mv consul /usr/local/bin/
输入consul -h
命令显示如下信息即为安装成功:
3.Consul 常用命令
consul agent
:是consul的核心指令,它运行agent来维护成员的重要信息、运行检查、服务宣布、查询处理等等。其中重要的参数如下:
-bind=0.0.0.0 指定 consul所在机器的IP地址。 默认值:0.0.0.0
-http-port=8500 consul 自带一个web访问的默认端口:8500
-client=127.0.0.1 表明哪些机器可以访问consul 。 默认本机。0.0.0.0 所有机器均可访问。
-config-dir=foo 所有主动注册服务的 描述信息
-data-dir=path 储存所有注册过来的server机器的详细信息。
-dev 开发者模式,直接以默认配置启动 consul
-node=hostname 服务发现的名字。
-rejoin consul 启动的时候,加入到的 consul集群
-server 以服务方式开启consul, 允许其他的consul 连接到开启的 consul上 (形成集群)。如果不加 -server, 表示以 “客户端” 的方式开启。不能被连接。
-ui 可以使用 web 页面 来查看服务发现的详情
测试上述命令:
# 在终端中,键入:
consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node=n1 -bind=192.168.19.101 -ui -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0
#看到提示:
==> Consul agent running!
启动浏览器,输入192.168.19.101:8500(虚拟机+端口号)测试:
-
consul members
: 指令输出consul agent目前所知道的所有的成员以及它们的状态,节点的状态只有alive、left、failed三种状态。![image-20210605093234463](https://raw.githubusercontent.com/zmk-c/blogImages/master/img/consul members.png)
-
consul info
: 查看当前 consul 的 IP 信息。 -
consul leave
:优雅的关闭 consul 。—— 不优雅!Ctrl +c![image-20210605093601531](https://raw.githubusercontent.com/zmk-c/blogImages/master/img/consul leave.png)
-
consul reload
:重新加载配置文件,再启动网络
注册服务到 consul 并查看
步骤:
-
进入配置文件路径
cd /etc/consul.d/
-
创建 json 文件
sudo vim web.json
-
shell按 json 的语法,填写 服务信息。
{"service": { "name": "myfirstconsul", "tags": ["first","consul"], "port": 8800 } }
-
重新启动 consul
consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node=n1 -bind=192.168.19.101 -ui -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0
-
查询服务
健康检查
健康检查是服务发现的关键组件,预防使用到不健康的服务。和服务注册类似,一个检查可以通过检查定义或HTTP API请求来注册。
-
打开配置文件
sudo vim /etc/consul.d/check.json
-
写入 服务的配置信息。
{ "service":{ "name":"web", "tags":["ahnu","computer"], "address":"192.168.19.101", "port":8800, "check":{ "id":"api", "name":"Health check", "http":"http://192.168.19.101:8800", // http形式的健康检查 "interval":"5s", // 按照预设的时间间隔创建一个HTTP “get”请求 "timeout":"1s" // 服务没有给consul回复的超时时间 } } }
-
执行命令
consul reload
重新加载配置文件关闭consul 再重启。 -
使用 浏览器 键入 192.168.19.101:8500 查看 “web” 这个服务 的健康状况
不健康!服务web没有给 consul 实时回复!
注意:consul做健康检查的必须是HTTP、Script脚本、TCP、TTL中的一种。
4.Consul 和 grpc 结合
安装 consul 源码包:
$ go get -u -v github.com/hashicorp/consul
使用整体流程
- 创建 proto文件 , 指定 rpc 服务
- 启动 consul 服务发现
consul agent -dev
开发者模式 - 启动server
- 获取consul 对象
- 使用 consul对象,将 server 信息,注册给 consul
- 启动服务
- 启动client
- 获取consul 对象
- 使用consul对象,从consul 获取健康的服务
- 再访问服务 (grpc远程调用)
编码实现
-
用到的函数:
// 从 consul 服务发送上获取 健康服务 func (h *Health) Service(service, tag string, passingOnly bool, q *QueryOptions) ([]*ServiceEntry, *QueryMeta, error) // 参数: service: 服务名。 -- 注册服务时,指定该string tag:外名/别名。 如果有多个,任选一个 passingOnly:是否通过健康检查。 true q:查询参数。 通常传 nil // 返回值: ServiceEntry: 存储服务的切片,一个集群共用一个服务名。 QueryMeta:额外查询返回值。 nil error: 错误信息
-
proto文件
// 默认proto2 syntax="proto3"; package pb; option go_package="../pb"; // 设置消息 message Person{ string name=1; int32 age=2; } // 添加 rpc服务 service hello{ rpc sayHello(Person) returns (Person); }
编译protobuf文件
protoc --go_out=plugins=grpc:./ *.proto
-
服务端
package main import ( "context" "fmt" "github.com/hashicorp/consul/api" "google.golang.org/grpc" "iHome/day02/pb" "net" ) type Children struct { } func (c *Children) SayHello(ctx context.Context,p *pb.Person) (*pb.Person,error) { p.Name += "你好" p.Age = 18 return p,nil } func main(){ // 把 grpc 服务注册到consul上 // 1.初始化consul配置 consulConfig := api.DefaultConfig() // 2.创建 consul 对象 consulClient, err := api.NewClient(consulConfig) if err != nil { fmt.Printf("创建consul对象失败:%v",err) return } // 3.告诉 consul ,即将注册的服务的配置信息 registration := api.AgentServiceRegistration{ ID: "web", Tags: []string{"grpc", "consul"}, Name: "Consul and gRPC", Port: 8800, //Address: "127.0.0.1", Address: "192.168.19.101", Check: &api.AgentServiceCheck{ CheckID: "consul grpc test", //TCP: "127.0.0.1:8800", TCP: "192.168.19.101:8800", Interval: "5s", Timeout: "1s", }, } // 4.注册 grpc 服务到 consul 上 err = consulClient.Agent().ServiceRegister(®istration) if err != nil { fmt.Printf("注册grpc到consul上失败:%v",err) return } ///////////////////////以下为 grpc 服务的远程调用//////////////////////// // 1.初始化一个grpc对象 grpcServer := grpc.NewServer() // 2.注册服务 pb.RegisterHelloServer(grpcServer,new(Children)) // 3.设置监听并建立连接,指定ip和端口号 //listener, err := net.Listen("tcp","127.0.0.1:8800") listener, err := net.Listen("tcp","192.168.19.101:8800") if err != nil { fmt.Printf("监听失败:%v",err) return } defer listener.Close() //fmt.Println("开始监听127.0.0.1:8800 ...") fmt.Println("开始监听192.168.19.101:8800 ...") // 4.启动服务 Serve() err = grpcServer.Serve(listener) if err != nil { panic(err) } }
-
客户端
package main import ( "context" "fmt" "github.com/hashicorp/consul/api" "google.golang.org/grpc" "iHome/day02/pb" "strconv" ) func main(){ // 1.初始化Consul配置 consulConfig := api.DefaultConfig() // 2.创建consul对象 (可以重新指定consul的属性) consulClient, err := api.NewClient(consulConfig) if err != nil { fmt.Printf("创建consul对象失败:%v",err) return } // 3.服务发现 从 consul 上获取健康的服务 service, _, err := consulClient.Health().Service("Consul and gRPC", "grpc", true, nil) if err != nil { fmt.Printf("服务发现阶段错误:%v",err) return } // 获取ip地址+端口号的地址 ip := service[0].Service.Address port := service[0].Service.Port target := ip+":"+strconv.Itoa(port) ///////////////////////以下为 grpc 服务的远程调用/////////////////////// // 1.连接grpc服务 //grpcConn, err := grpc.Dial("127.0.0.1:8800",grpc.WithInsecure()) grpcConn, err := grpc.Dial(target,grpc.WithInsecure()) if err != nil { fmt.Printf("连接拨号失败:%v",err) return } defer grpcConn.Close() // 2.初始化grpc客户端 grpcClient := pb.NewHelloClient(grpcConn) var child pb.Person child.Name = "小宝" // 3.调用远程服务 hello, err := grpcClient.SayHello(context.TODO(), &child) if err != nil { fmt.Printf("调用远程服务失败:%v",err) return } fmt.Println(hello) }
服务注销
package main
import (
"fmt"
"github.com/hashicorp/consul/api"
)
func main() {
// 1.初始化consul配置
consulConfig := api.DefaultConfig()
// 2.创建consul对象
consulClient, err := api.NewClient(consulConfig)
if err != nil {
fmt.Printf("创建consul对象失败:%v",err)
return
}
// 3.注销服务
err = consulClient.Agent().ServiceDeregister("web")
if err != nil {
panic(err)
}
}
以上是关于微服务系列Consul的介绍与安装的主要内容,如果未能解决你的问题,请参考以下文章
微服务-SpringCloud学习系列:注册中心Consul