• go+protobuf+grpc+consul简单的服务发现模型


    一  环境准备

    • windows64 (此处我用的windows,建议大家linux)
    • 安装consul,请自行搜索
    • 安装protobuf,请自行搜索 

    二  概念梳理

    • consul 是服务发现工具,简单地说,就是各个server将自己注册到consul上,client不再记住各个server的ip+port,而是去consul上获取想要连接的server。使得server对client不再需要暴露,可以动态伸缩。
    • protobuf 可以拿来和xml、json对比,都是数据格式,只是protobuf更加轻量级,适合做微服务或者tcp通信。使用起来相对繁琐一点点。
    • rpc 可以对比ipc(进程间通信),它是各个服务间的通信,重点在r和i的区别,rpc是远程调用。
    • grpc 是rpc的一种,它是进阶版,更高效,基于http2(可以双工通信),默认采用protobuf格式的数据

    三  实现过程

      3.1 目录结构

          

    • 项目名称test_grpc_consul
    • pb目录为存放protobuf文件
    • person.proto为源生protobuf代码
    • person.pb.go为编译打包出的能为go调用的代码
    • consul-server.go为server程序,实现了往consul的注册和服务的监听
    • consul-client.go为client程序,实现了从consul查找server并发起调用
    • consul-deregister为一个管理程序,实现了consul中server的注销

      3.2 protobuf的生成

        person.proto

     1 syntax = "proto3";
     2 
     3 package pb;
     4 option go_package = "./;pb";   //此处我也不知道干嘛用的,不加他报错,网上搜索的解决方案
     5
     6 message Person{
     7     string name = 1;
     8     int32 age = 2;
     9 }
    10
    11 //添加rpc服务
    12 service hello{
    13     rpc sayHello(Person) returns (Person);
    14 
    15 }

        将person.proto编译打包

    先cd到pb目录,再执行以下命令    

    protoc --go_out=plugins=grpc:./ *.proto

    生成person.pb.go文件

    其实golang中,一般的rpc中proto的打包为以下命令:

    protoc --go_out=./ *.proto

      3.3 server程序

    package main
    
    import (
        "context"
        "fmt"
        "/test_grpc_consul/pb"    //你们自己的路径
        "github.com/hashicorp/consul/api"
        "google.golang.org/grpc"
        "net"
    )
    type Children struct {
    
    }
    func (this *Children)SayHello(ctx context.Context,p *pb.Person) (*pb.Person,error){
        p.Name = "hello "+p.Name
        return p,nil
    }
    func main(){
        //把grpc服务注册到consul上
        //初始化consul配置
        consulConfig := api.DefaultConfig()
        //创建consul对象
        consulClient,err := api.NewClient(consulConfig)
        if err!=nil{
            fmt.Println("server, api.newclient err:",err)
            return
        }
        //告诉consul,即将注册的服务的配置信息
        reg := api.AgentServiceRegistration{
            Kind:              "",
            ID:                "wbw1_id",
            Name:              "wbw001_grpc_consul",
            Tags:              []string{"wbw1","asa1"},
            Port:              8800,
            Address:           "127.0.0.1",
            TaggedAddresses:   nil,
            EnableTagOverride: false,
            Meta:              nil,
            Weights:           nil,
            Check:             &api.AgentServiceCheck{
                CheckID:                        "wbw1_id_check",
                Name:                           "",
                Args:                           nil,
                DockerContainerID:              "",
                Shell:                          "",
                Interval:                       "5s",
                Timeout:                        "1s",
                TTL:                            "",
                HTTP:                           "",
                Header:                         nil,
                Method:                         "",
                Body:                           "",
                TCP:                            "127.0.0.1:8800",
                Status:                         "",
                Notes:                          "",
                TLSServerName:                  "",
                TLSSkipVerify:                  false,
                GRPC:                           "",
                GRPCUseTLS:                     false,
                AliasNode:                      "",
                AliasService:                   "",
                SuccessBeforePassing:           0,
                FailuresBeforeCritical:         0,
                DeregisterCriticalServiceAfter: "",
            },
            Checks:            nil,
            Proxy:             nil,
            Connect:           nil,
            Namespace:         "",
        }
        //注册gprc服务到consul上
        consulClient.Agent().ServiceRegister(&reg)
        grpcServer := grpc.NewServer()
        pb.RegisterHelloServer(grpcServer,new(Children))
        listener,err := net.Listen("tcp", "127.0.0.1:8800")
        if err != nil{
            fmt.Println("listen err:",err)
        }
        defer listener.Close()
        grpcServer.Serve(listener)
    }

      3.4 client程序

    package main
    
    import (
        "context"
        "fmt"
        "/test_grpc_consul/pb"   //同server此处
        "github.com/hashicorp/consul/api"
        "google.golang.org/grpc"
        "strconv"
    )
    func main(){
        consulConfig := api.DefaultConfig()
        conculClient,err := api.NewClient(consulConfig)
        if err!=nil{
            fmt.Println("client, api.newclient err:",err)
            return
        }
        services,_,err := conculClient.Health().Service("wbw001_grpc_consul","wbw1",true,nil )
        addr := services[0].Service.Address+":"+strconv.Itoa(services[0].Service.Port)
    
        //grpcConn,err := grpc.Dial("127.0.0.1:8800",grpc.WithInsecure())
        grpcConn,err := grpc.Dial(addr,grpc.WithInsecure())
        if err != nil{
            fmt.Println("dial err:",err)
        }
        defer grpcConn.Close()
    
        grpcClient := pb.NewHelloClient(grpcConn)
    
        var person pb.Person
        person.Name = "wbw"
        person.Age = 18
        p,err := grpcClient.SayHello(context.TODO(),&person)
        fmt.Println(p,err)
    }

      3.5 server注销程序

    package main
    
    import (
        "fmt"
        "github.com/hashicorp/consul/api"
    )
    
    func main(){
        consulConfig := api.DefaultConfig()
        consulClient,err := api.NewClient(consulConfig)
        if err != nil{
            fmt.Println("deregister, api.newclient err:",err)
            return
        }
        consulClient.Agent().ServiceDeregister("wbw1_id") 
    }

    四  调用说明

      4.1 启动 consul

    //本文请用
    consul agent -dev

    //但是生产环境建议用
    // consul agent -server -bootstrap-expect 1 -data-dir D: oolsconsul_1.10.0_windows_amd64data_dir -node=n1 -bind=10.10.10.18 -ui -rejoin -config-dir=D: oolsconsul_1.10.0_windows_amd64config_dir -client 0.0.0.0

    我们进入网址http://localhost:8500/
    可以发现我们的consul启动完成

      4.2 启动server

    先cd到test_grpc_consul目录,再执行以下命令    

    go run consul-server.go

    可以看到我们的服务已经执行了

    然后进入网址http://localhost:8500/可以看到我们的服务已经成功注册到consul了,点进去还能看到健康检测正常

      4.3 启动client

    先cd到test_grpc_consul目录,再执行以下命令    

    go run consul-client.go

    调用成功!!!

      4.4 启动注销程序

    先cd到test_grpc_consul目录,再执行以下命令    

    go run consul-deregister.go

     我们可以看到该server已经不再consul中了,同时我们调用client也会失败。

     注意:

     如果我们把client直连server,依然能成功,因为我们的server并没有退出,仅仅是在consul中抹掉了痕迹。

    四  补充说明

    • 建议开启go mod,这样不依赖于gopath等路径,且不需要go get等操作,能利用goland自动拉取

  • 相关阅读:
    表白利器,马赛克拼贴照片制作
    听说国漫最近崛起了,那我们就来爬几部国漫看看(动态加载,反爬)
    python爬虫--看看虎牙女主播中谁最“顶”
    “花小猪”,滴滴搬起石头砸自己的脚?
    Linux命令学习之awk
    《Redis深度历险》集群篇、拓展篇
    《Redis深度历险》原理篇
    《Redis深度历险》应用篇
    《鸟哥的Linux私房菜 基础篇》下
    Git使用
  • 原文地址:https://www.cnblogs.com/bushuwei/p/14927810.html
Copyright © 2020-2023  润新知