• Hello GRPC


    GRPC使用protocol buffers 作为接口定义语言(IDL)和信息交换格式。

    安装GRPC

    按照GRPC官方的教程,第一步要安装PROTOBUF的编译器

    下载地址:

    https://github.com/protocolbuffers/protobuf/releases/tag/v3.17.0

    我这里下载了个 windows版本的  protoc-3.17.0-win64.zip

    下载完成之后,配置一下环境变量,使得protoc 可以在cmd中运行。

    image

    配置完成之后验证一下

    image

    下面安装针对go语言相关的GRPC插件

    为了安装顺利,设置一下go语言的国内代理,防止被墙

    go env -w GOPROXY=https://goproxy.cn,direct

    安装将.proto生成go代码的插件

    go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.26

    由于这个插件并不包含 proto中 service 的部分,需要包含用于生成go-grpc的代码还需要安装下面的工具

    在安装完成之后,我们的GOPATH/bin 中就会存在这两个文件

    image

    实践GRPC

    首先新建一个go项目 grpcdemo

    目录结构如下:

    proto/gen/go

    main.go

    在proto中新建greeting.proto文件

    在greeting.proto中写入:

    // 使用 version 3版本的protocol buffer
    syntax = "proto3";
    // 指定 go package 的路径 和需要导入的名字
    option go_package="grpcdemo/proto/gen/go;greeting";
    //定义性别的枚举类型
    enum Gender{
        MALE =0;
        FEMALE =1;
    }
    // User 
    message User{
        int32 User_ID=1;  // 指定第1个字段
        string User_Name=2; // 指定第2个字段
        Gender gender=3;// 指定第3个字段
    }
    // GreetingTxt
    message GreetingTxt {
        int32 Id =1;
        string Content=2;
        // repeated 用于生产切片类型的字段
        repeated User Receives=3;
    }
    // GetGreetingTxtRequest server method 的请求结构
    message GetGreetingTxtRequest {
        int32 Id =1;
    }
    // GetGreetingTxtRequest server method 的响应结构
    message GetGreetingTxtResponse{
        GreetingTxt Txt =1;
    }
    // Greeter 定义一个 service 用于 client  -server之间的 交互
    service Greeter{
        // GetGreetingTxt 定义方法
        rpc GetGreetingTxt ( GetGreetingTxtRequest) returns (GetGreetingTxtResponse);
    }

    在 proto目录中执行CMD

    protoc --proto_path=.  --go_out=gen/go --go_opt=paths=source_relative greeting.proto

    会在grpcdemo/proto/gen/go 下生成 greeting.pb.go 里边包含了 proto的message go语言的基础代码

    然后执行

    protoc --proto_path=.  --go-grpc_out=gen/go --go-grpc_opt=paths=source_relative greeting.proto

    会在grpcdemo/proto/gen/go 下生成greeting_grpc.pb.go文件,其中包含了 grpc service的代码。

    .proto文件生成go代码的工作准备完毕,我们可以编写用于server –client 交互的代码用于测试grpc的 发送和响应。

    在grpcdemo下新建文件夹 services,在它下面新建greetor.go 文件 用于在服务端实现 刚刚定义好的 GetGreetingTxt 方法

    package services
    
    import (
        "context"
        greeting "grpcdemo/proto/gen/go"
    )
    
    type Greetor struct {
        greeting.UnimplementedGreeterServer
    }
    
    // GetGreetingTxt implement  interface method
    func (*Greetor) GetGreetingTxt(context.Context, *greeting.GetGreetingTxtRequest) (*greeting.GetGreetingTxtResponse, error) {
        return &greeting.GetGreetingTxtResponse{
            Txt: &greeting.GreetingTxt{
                Receives: []*greeting.User{
                    {
                        User_ID:   1,
                        User_Name: "gopher",
                        Gender:    greeting.Gender_MALE,
                    },
                    {
                        User_ID:   2,
                        User_Name: "csharp",
                        Gender:    greeting.Gender_FEMALE,
                    },
                },
                Content: "hello grpc",
                Id:      1,
            },
        }, nil
    }

    其中GetGreetingTxt 是 接口的实现方法,值得注意的地方是 greeting.UnimplementedGreeterServer

    这个结构体会自动实现一些未实现的方法,虽然听起来很怪,看一下grpc生成的代码就很好理解了。

    func (UnimplementedGreeterServer) GetGreetingTxt(context.Context, *GetGreetingTxtRequest) (*GetGreetingTxtResponse, error) {
        return nil, status.Errorf(codes.Unimplemented, "method GetGreetingTxt not implemented")
    }

    相关的proposal ,有兴趣的可以看一下 https://github.com/grpc/grpc-go/issues/3669

    既然有了方法的实现,还要加入针对grpc的链接和调用

    在 grpcdemo/main.go中写入:

    package main
    
    import (
        greeting "grpcdemo/proto/gen/go"
        "grpcdemo/services"
        "log"
        "net"
    
        "google.golang.org/grpc"
    )
    
    func main() {
        l, err := net.Listen("tcp", ":8088")
        if err != nil {
            log.Fatalf("listen grpc server error :%v", err)
        }
        server := grpc.NewServer()
        greeting.RegisterGreeterServer(server, &services.Greetor{})
        err = server.Serve(l)
        if err != nil {
            log.Fatalf("server error %v", err)
        }
    }

    这里边监听了 8088端口,下面在 grpcdemo/client中 创建一个用于调用 方法的客户端 main.go

    connclient, err := grpc.Dial("localhost:8088", grpc.WithInsecure())
        if err != nil {
            log.Fatalf("connection error %v", err)
        }
        defer connclient.Close()
        greetingClient := greeting.NewGreeterClient(connclient)
        resp, err := greetingClient.GetGreetingTxt(context.Background(), &greeting.GetGreetingTxtRequest{
            Id: 1,
        })
        if err != nil {
            log.Fatalf("invoke server grpc error:%v", err)
        }
        log.Printf("response :%v 
    ", resp)

    运行服务端和客户端,就能在客户端命令行中看到消息的response打印输出,完成了一次grpc的请求调用。

    原文地址

  • 相关阅读:
    Nginx创建密码保护目录
    Android:Field can be converted to a local varible.
    创建用户故事地图(User Story Mapping)的8个步骤
    用户故事地图(User Story Mapping)之初体验
    Android必知必会--GreenDao缓存
    Windows下多线程数据同步互斥的有关知识
    OpenCV3.0 3.1版本的改进
    利用OpenCV的人脸检测给头像带上圣诞帽
    一些关于并行计算的科研思路
    Java中httpClient中三种超时设置
  • 原文地址:https://www.cnblogs.com/lucky528/p/14773580.html
Copyright © 2020-2023  润新知