1.consul安装
安装
Consul v1.15.2 Binaries | HashiCorp Releases

解压
unzip consul_1.15.2_linux_amd64.zip

查看帮助信息

启动
consul agent -server -bootstrap-expect 1 -data-dir /tmp/consul -node=n1 -bind=192.168.188.201 -ui -rejoin -config-dir=/etc/consul.d/ -client 0.0.0.0

2.代码演示
目录结构如下
新建个项目grpc-consul,再这之下新建个目录chitchat,再这之下新建client,proto,server
grpc基础调用
proto包下新建helloworld.proto
//指定版本 默认版本2
syntax = "proto3";
// 指定等会文件生成出来的package
package server;
//代码生成目录
option go_package = "grpc-consul/chitchat/proto";
service SayService{
//rpc服务的函数名 (传人参数)返回(返回参数)
//一元调用
rpc SayHello(SayRequest) returns(SayResponse){}
}
//定义消息
message SayRequest{
string name = 1;
string msg = 5;
}
message SayResponse{
string msg = 5;
}生成代码
protoc --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relati ve .\chitchat\proto\helloworld.proto
下载缺失依赖
go mod tidy
在server包下新建server.go
package main
import (
"context"
"google.golang.org/grpc"
"grpc/chitchat/proto"
"log"
"net"
)
func main() {
//tcp监听9090
listen, err := net.Listen("tcp", "localhost:9090")
if err != nil {
log.Fatal("出现错误", err)
return
}
newServer := grpc.NewServer()
proto.RegisterSayServiceServer(newServer, &server{})
log.Printf("server listen : %d", listen.Addr())
err = newServer.Serve(listen)
if err != nil {
log.Fatal(err)
}
}
type server struct {
proto.UnimplementedSayServiceServer
}
func (server) SayHello(ctx context.Context, in *proto.SayRequest) (*proto.SayResponse, error) {
log.Printf("服务端接收到 : %v\n", in)
return &proto.SayResponse{
Msg: "Hello client , This is server!",
}, nil
}一个简单的一元调用服务端代码,不再阐述。
同样在client包下新建client.go
代码如下:
package main
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"grpc/chitchat/proto"
"log"
)
func main() {
//建立与服务器的连接
connect, err := grpc.Dial("localhost:9090", grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatal(err)
return
}
defer connect.Close()
//创建客户端对象 client
client := proto.NewSayServiceClient(connect)
sayHello(client)
}
func sayHello(client proto.SayServiceClient) {
//创建一个上下文对象 ctx
ctx := context.Background()
sayRequest := &proto.SayRequest{
Name: "Dreams",
Msg: "Hello server , This is client!",
}
sayHello, err := client.SayHello(ctx, sayRequest)
if err != nil {
log.Fatal(err)
return
}
log.Println("客户端接收到 :", sayHello.Msg)
}一个简单的grpc客户端,,不再阐述。
运行如下:


consul注册
导入consul
go get github.com/hashicorp/consul/api
新建chitchat/consul/grpc_consul.go
package consul
import (
"github.com/hashicorp/consul/api"
"log"
)
func GetConsulRegister(ID, Name, Address string, Port int) {
config := api.DefaultConfig()
config.Address = "192.168.188.201:8500"
client, err := api.NewClient(config)
if err != nil {
log.Fatal(err)
}
// 健康检查设置
check := &api.AgentServiceCheck{
//存放本机ip地址,不能写localhost,否则consul就一直检测的是consul安装的主机ip地址
TCP: "********:9090",
Interval: "10s",
}
registration := api.AgentServiceRegistration{
ID: ID,
Name: Name,
Address: Address,
Port: Port,
Check: check,
}
err = client.Agent().ServiceRegister(®istration)
if err != nil {
log.Fatal(err)
}
}api.DefaultConfig()用于创建一个默认的 Consul 客户端配置对象
api.NewClient() 用于创建一个连接到 Consul 的客户端对象。该函数接受一个 api.Config 对象作为参数,并返回一个连接到 Consul 的客户端。
api.AgentServiceRegistration 是 Consul Go 库中的一个结构体,用于定义要注册到 Consul 上的服务的信息。
api.AgentServiceCheck 是 Consul Go 库中的一个结构体,用于定义服务的健康检查方式。
client.Agent().ServiceRegister(®istration) 用于将服务注册信息发送到 Consul Agent 进行注册。
修改server代码,添加注册consul
func main() {
//tcp监听9090
listen, err := net.Listen("tcp", "localhost:9090")
if err != nil {
log.Fatal("出现错误", err)
return
}
newServer := grpc.NewServer()
proto.RegisterSayServiceServer(newServer, &server{})
log.Printf("server listen : %d", listen.Addr())
//服务注册进consul
consul.GetConsulRegister("hello", "hello-server", "localhost", 9090)
err = newServer.Serve(listen)
if err != nil {
log.Fatal(err)
}
}
运行可以看到成功



consul发现
grpc_consul.go下新建GetConsulDiscover
func GetConsulDiscover() (string, error) {
// 创建 Consul 客户端连接
config := api.DefaultConfig()
config.Address = "192.168.188.201:8500"
client, err := api.NewClient(config)
if err != nil {
return "", err
}
// 查询 Consul 中的服务实例
services, _, err := client.Catalog().Service("hello-server", "", nil)
if err != nil {
return "", err
}
if len(services) == 0 {
return "", errors.New("没有发现该服务!")
}
// 返回第一个服务实例的地址和端口
service := services[0]
address := fmt.Sprintf("%s:%d", service.ServiceAddress, service.ServicePort)
return address, nil
}client.Catalog().Service() 是 Consul 的 Go 客户端库中的一个方法,用于查询 Consul 中特定服务的实例。
同样可以使用另一个方法:client.Health().Service() 用于查询指定服务的健康检查状态。
如下:
func GetConsulDiscover() (string, error) {
// 创建 Consul 客户端连接
config := api.DefaultConfig()
config.Address = "192.168.188.201:8500"
client, err := api.NewClient(config)
if err != nil {
return "", err
}
// 查询 Consul 中的服务实例
services,_, err := client.Health().Service("hello-server", "", true, nil)
if err != nil {
return "", err
}
// 返回第一个服务实例的地址和端口
service := services[0].Service
address := fmt.Sprintf("%s:%d", service.Address, service.Port)
return address, nil
}
在client.go修改main函数,调用发现函数
func main() {
addr, err := consul.GetConsulDiscover()
if err != nil {
log.Fatal(err)
return
}
//建立与服务器的连接
connect, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
log.Fatal(err)
return
}
defer connect.Close()
//创建客户端对象 client
client := proto.NewSayServiceClient(connect)
sayHello(client)
}
成功运行如下


服务注销
简单调用一下ServiceDeregister函数即可
func GetConsuldel(ID string,) {
config := api.DefaultConfig()
//config.Address = "192.168.188.201:8500"
client, err := api.NewClient(config)
if err != nil {
log.Fatal(err)
}
err = client.Agent().ServiceDeregister(ID)
if err != nil {
log.Fatal(err)
}
}

