安装 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;
一些说明:
- string、int32为字段的数据类型,还有其他数据类型,见下表
- 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
,可以看到一些变化
-
HelloRequest
结构体中多了Age
字段和func (m *HelloRequest) GetAge() int32
方法 -
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