Go gRPC

2021-03-31  本文已影响0人  JunChow520

gRPC理念:定义一个服务,指定其能够被远程调用的方法(包含参数与返回类型)。在服务端实现此接口,并运行一个gRPC服务器来处理客户端调用,而在服务端拥有一个存根能够像服务端一样的方法。

gRPC

rRPC默认使用Protobuf对数据继续序列化和反序列化

安装protoc

grpc默认使用Prortobuf,因此必须首先安装Protobuf编译器。

$ protoc --version
libprotoc 3.15.6

安装protoc-gen-gogo插件

$ go get github.com/gogo/protobuf/protoc-gen-gogo

安装 grpc-go

$ go get -u google.golang.org/grpc

gRPC开发流程

  1. 编写Protobuf文件定义服务和接口
  2. 自动生成Golang代码
  3. 服务接口实现
  4. gRPC服务端实现
  5. gRPC客户端实现

编写.proto定义服务和接口

$ mkdir pb && cd pb
$ vim game.proto
syntax = "proto3";
package pb;

message Request{
    int32 id = 1;
    string name = 2;
}

message Response {
    int32 code = 1;
    string message = 2;
    bytes data = 3;
}
// 定义服务
service Waiter {
    // 定义接口
    rpc Get (Request) returns (Response){}
}

生成Golang代码文件

$ protoc game.proto --gogo_out=plugins=grpc:. 

更新项目依赖

$ cd ..
$ go get google.golang.org/grpc

编写RPC服务端

$ vim server.go
package pb

import (
    context "context"
    fmt "fmt"
    "net"
    "google.golang.org/grpc"
    "google.golang.org/grpc/reflection"
)

//Server 业务实现方法的容器
type Server struct{}

//Get 内部处理请求并返回结果
func (s *Server) Get(ctx context.Context, req *Request) (*Response, error) {
    msg := fmt.Sprintf("%v %v", req.Id, req.Name)

    return &Response{Value: []byte(msg)}, nil
}

func StartServer() {
    //创建RPC服务端
    rpcServer := grpc.NewServer()
    //注册接口服务
    RegisterWaiterServer(rpcServer, &Server{})
    //在服务器上注册反射服务
    reflection.Register(rpcServer)

    //监听端口连接
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        panic(err)
    }
    fmt.Printf("rpc server listen port 8080\n")

    //将监听交给服务处理
    err = rpcServer.Serve(listener)
    if err != nil {
        panic(err)
    }
    fmt.Printf("rpc server serve ok...\n")
}

编写客户端

$ vim client.go
package pb

import (
    "context"
    fmt "fmt"
    "os"

    "google.golang.org/grpc"
)

func StartClient() {
    //建立连接到RPC服务
    conn, err := grpc.Dial("127.0.0.1:8080", grpc.WithInsecure())
    if err != nil {
        panic(err)
    }
    defer conn.Close() //函数结束时关闭连接
    fmt.Printf("client connect...\n")

    //创建RPC客户端
    client := NewWaiterClient(conn)
    fmt.Printf("new waiter client\n")

    //获取模拟请求数据
    id := "id"
    name := "name"
    if len(os.Args) > 1 {
        id = os.Args[1]
        name = os.Args[2]
    }
    req := &Request{Id: id, Name: name}

    //调用RPC接口
    ctx := context.Background()
    obj, err := client.Get(ctx, req)
    if err != nil {
        panic(err)
    }
    fmt.Printf("client Get result: %v", obj.Value)
}
上一篇下一篇

猜你喜欢

热点阅读