gRPC 初探
- 前言
- 安装
- 使用
- 参考
前言
gRPC 出来很久了,很多地方都在使用中。因为是google 出品的所以一直受到很大的关注。
在实际的学习中,和其他的rpc框架还是有些特点:
- 跨语言,如果项目是跨语言通信的可以考虑使用gRPC。
- gRPC 基于 HTTP/2 标准设计,使其在移动设备上表现更好,更省电和节省空间占用。
- 通信格式默认使用protocolbuffer(是google 的一种数据交换的格式,它独立于语言,独立于平台),二进制,性能好,现在使用 proto3的新风格。
下面是使用中的一些笔记,已 golang 为基础
安装
我们先安装gRPC-Go:
#直接使用 get 安装,源码中包括了后面的examples
go get -u google.golang.org/grpc
现在还不能使用gRPC,还需要安装前面提到的protocolbuffer
protocolbuffer 安装,golang需要编译安装
git clone git@github.com:google/protobuf.git
cd protobuf/
#以防万一
brew install autoconf automake libtool
./autogen.sh
./configure
make
make check
sudo make install
#验证,命令
protoc
安装go的protobuf插件
#安装,提供golang运行protobuf的环境和go服务端源码生成功能(?)
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
#protoc-gen-go 命令需要直接能被执行到
export PATH=$PATH:$GOPATH/bin
使用
目录结构
helloworld/helloworld.proto
此为 protobuf 的IDL,定义了rpc服务的具体内容,内容不做解释了
helloworld/helloworld.pb.go
此为根据 helloworld.proto 生成golang的protobuf定义文件,客户端服务端同时需要引入并使用
我们直接看例子,先跑起来
#第一个例子目录
cd GOPAHT/src/google.golang.org/grpc/examples/helloworld
#运行go 服务端
go run greeter_server/main.go
#运行go 客户端
go run greeter_client/main.go haha
#客户端返回内容,成功!
2017/10/10 01:09:24 Greeting: Hello haha
使用代码生成插件
#修改proto文件时,需要使用命令重现生成go的protobuf依赖文件
protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld
修改我们的helloworld代码
下面我们修改下helloworld代码在完整的试一试
helloworld/helloworld.proto
package helloworld;
// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
// Sends another greeting
//我们新增了 SayHelloAgain rpc 方法
rpc SayHelloAgain (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;
}
greeter_server/main.go
type server struct{}
// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}
//我们对应增加了 服务端的 支持 SayHelloAgain
func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
return &pb.HelloReply{Message: "Hello again " + in.Name}, nil
}
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, &server{})
// Register reflection service on gRPC server.
reflection.Register(s)
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
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.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Message)
//我们又加了 客户端 的调用逻辑
r, err = c.SayHelloAgain(context.Background(), &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Message)
}
#使用protoc 重现生成 protobuf依赖文件
protoc -I helloworld/ helloworld/helloworld.proto --go_out=plugins=grpc:helloworld
#执行验证
go run greeter_client/main.go haha
#返回,调用了两次rpc
2017/10/10 01:48:20 Greeting: Hello haha
2017/10/10 01:48:20 Greeting: Hello again haha
这就是gRPC初探,后面会写一篇php做为客户端使用gRPC的小文章。