go gRPC 初体验

安装 gRPC

go get google.golang.org/grpc

安装 protocal 环境

https://github.com/google/protobuf/releases下载安装包,例如:protobuf-cpp-3.6.1.zip,解压后

./configure make && make install

等待至安装完成

zhangqiangdeMac-mini:protobuf-3.6.1 zhqmac$ protoc --version

提示版本信息,表示安装成功

libprotoc 3.6.1

goland 安装 protoc 插件

插件名 用途
Protobuf Support protoc文件打开工具
ClangFormatIJ protoc 代码提示工具

安装GoLang protoc 插件

go get -a github.com/golang/protobuf/protoc-gen-go

定义Service

一个RPC service就是一个能够通过参数和返回值进行远程调用的method,我们可以简单地将它理解成一个函数。因为gRPC是通过将数据编码成protocal buffer来实现传输的。因此,我们通过protocal buffers interface definitioin language(IDL)来定义service method,同时将参数和返回值也定义成protocal buffer message类型。具体实现如下所示,包含下面代码的文件叫helloworld.proto:

syntax = "proto3";

option java_package = "io.grpc.examples";

package helloworld;

// The greeter service definition.
service Greeter {
    // Sends a greeting
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
    string name = 1;
}

// The response message containing the greetings
message HelloReply {
    string message = 1;
}

接着,根据上述定义的service,我们可以利用protocal buffer compiler ,即protoc生成相应的服务器端和客户端的GoLang代码。生成的代码中包含了客户端能够进行RPC的方法以及服务器端需要进行实现的接口

假设现在所在的目录是$GOPATH/src/helloworld/helloworld,我们将通过如下命令生成gRPC对应的GoLang代码:

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

此时,将在目录下生成helloworld.pb.go文件。

server.go

package main

// server.go

import (
	"log"
	"net"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	pb "zhqGo/gRPCDemo/proto"
)

const (
	port = ":50051"
)

type server struct {}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

func main() {
	lis, err := net.Listen("tcp", port)
	if err != nil {
		log.Fatal("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	pb.RegisterGreeterServer(s, &server{})
	s.Serve(lis)
}

client.go

package main

//client.go

import (
	"log"
	"os"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
	pb "zhqGo/gRPCDemo/proto"
)

const (
	address     = "localhost:50051"
	defaultName = "world"
)

func main() {
	conn, err := grpc.Dial(address, grpc.WithInsecure())
	if err != nil {
		log.Fatal("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewGreeterClient(conn)

	name := defaultName
	if len(os.Args) >1 {
		name = os.Args[1]
	}
	r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
	if err != nil {
		log.Fatal("could not greet: %v", err)
	}
	log.Printf("Greeting: %s", r.Message)
}

最后运行:

go run server.go

go run client.go

以上是grpc官网给出的一个demo,如果跑通了,表示环境已经没有问题了,接下来给它改一改

添加age字段

一、打开helloworld.proto文件,找到

message HelloRequest{
        string name = 1;
}

请求体,暂且就这么说吧,反正就是在client端调用时需要传入的参数,添加字段

     int32 age = 2;
 

一些说明:

  1. string、int32为字段的数据类型,还有其他数据类型,见下表
  2. name = 1,age=2,其中”1,2”表示字段tag值,tag值不可以重复
.proto Type Notes C++ Type Java Type
double   doubel doubel
float   float float
int32 Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead. int32 int
int64 Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead. int64 long
uint32 Uses variable-length encoding. uint32 int
uint64 Uses variable-length encoding. uint64 long
sint32 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s. int32 int
sint64 Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s. int64 long
fixed32 Always four bytes. More efficient than uint32 if values are often greater than 2^28. uint32 int
fixed64 Always eight bytes. More efficient than uint64 if values are often greater than 2^56. uint64 long
sfixed32 Always four bytes. int32 int
sfixed64 Always eight bytes. int64 long
bool   bool boolean
string A string must always contain UTF-8 encoded or 7-bit ASCII text. string string
bytes May contain any arbitrary sequence of bytes. string ByteString

二、添加响应字段

message HelloReply {
    string message = 1;
    //age字段
    int32 ageMessage = 2;

}

在当前工程目录下执行命令,将重新生成helloworld.pb.go

protoc –go_out=plugins=grpc:. proto/helloworld.proto

打开helloworld.pb.go,可以看到一些变化

  1. HelloRequest结构体中多了Age字段和func (m *HelloRequest) GetAge() int32 方法

  2. HelloReply结构体中多了AgeMessage字段和func (m *HelloReply) GetAgeMessage() int32 方法

三、调用

client.go

替换下面代码

	r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name,Age:25})
	if err != nil {
		log.Fatal("could not greet: %v", err)
	}
	log.Printf("Greeting: %s,%v", r.Message,r.AgeMessage)


server.go

替换下面代码

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	return &pb.HelloReply{Message:"123",AgeMessage:in.Age}, nil
}

执行:

go run server.go go run client.go

可以看到有age输出。

protobuf repeated

message中通过repeated关键字+数据类型,声明一个数组,如声明一个int32的数组

repeated int32 array = 3

注:在go调用方法时,repeated声明的字段为切片类型

package==true

package用于修饰 ``repeated` 声明的字段

1.作用

2.只能用于基本数据类型

添加方法

一、声明方法

打开helloworld.proto文件

service Greeter {
    // Sends a greeting
    rpc SayHello (HelloRequest) returns (HelloReply) {}
    //添加ZHQTest方法
    //形参 TestRequest对象
    //返回值 TestReply对象
    rpc ZHQTest (TestRequest) returns (TestReply){}
}
message TestRequest {
    repeated string users = 1 ;
}
message TestReply{
    repeated string users = 1 ;
}

在当前工程目录下执行命令,将重新生成helloworld.pb.go

protoc –go_out=plugins=grpc:. proto/helloworld.proto

二、调用方法

server.go

//方法名必须与Greeter声明的方法名一致
func (s *server)ZHQTest(ctx context.Context, in *pb.TestRequest) (*pb.TestReply, error) {

	return &pb.TestReply{Users:in.Users},nil
}

client.go

func myRPCRequest(c pb.GreeterClient)  {
	users := []string{"zhq", "sweetsmelon"}
	r, err := c.ZHQTest(context.Background(), &pb.TestRequest{Users: users})
	if err != nil {
		log.Fatal("could not greet: %v", err)
	}
	log.Printf("users is:%v,%s", r.Users[0],r.Users[1])
}


执行:

go run server.go

go run client.go

demo下载 https://github.com/sweetMegan/gRPCDemo

参考链接:

https://www.cnblogs.com/YaoDD/p/5504881.html

https://blog.csdn.net/weiwangchao_/article/details/16797763

https://www.jianshu.com/p/30ef9b3780d9

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦