Go gRPC
2021-03-31 本文已影响0人
JunChow520
gRPC理念:定义一个服务,指定其能够被远程调用的方法(包含参数与返回类型)。在服务端实现此接口,并运行一个gRPC服务器来处理客户端调用,而在服务端拥有一个存根能够像服务端一样的方法。
gRPCrRPC默认使用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开发流程
- 编写Protobuf文件定义服务和接口
- 自动生成Golang代码
- 服务接口实现
- gRPC服务端实现
- 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)
}