所谓RPC(remote procedure call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间能够进行通讯,并且也听从server/client模型。使用的时候客户端调用server端提供的接口就像是调用本地的函数同样。linux
与许多RPC系统同样,gRPC基于定义服务的思想,指定可使用其参数和返回类型远程调用的方法。默认状况下,gRPC使用协议缓冲区做为接口定义语言(IDL)来描述服务接口和有效负载消息的结构。git
既然是server/client模型,那么咱们直接用restful api不是也能够知足吗,为何还须要RPC呢?下面咱们就来看看RPC到底有哪些优点github
gRPC和restful API都提供了一套通讯机制,用于server/client模型通讯,并且它们都使用http做为底层的传输协议(严格地说, gRPC使用的http2.0,而restful api则不必定)。不过gRPC仍是有些特有的优点,以下:golang
可是,一般咱们不会去单独使用gRPC,而是将gRPC做为一个部件进行使用,这是由于在生产环境,咱们面对大并发的状况下,须要使用分布式系统来去处理,而gRPC并无提供分布式系统相关的一些必要组件。并且,真正的线上服务还须要提供包括负载均衡,限流熔断,监控报警,服务注册和发现等等必要的组件。不过,这就不属于本篇文章讨论的主题了,咱们仍是先继续看下如何使用gRPC。web
mac:brew install protobufwindows
windows:protoc 下载:官方地址,而后将 bin 路径添加到 path 环境变量下去api
linux:
安装须要的依赖包:
[root@localhost ~]# yum -y install autoconf automake libtool curl make g++ unzip
[root@localhost ~]# unzip protobuf-master.zip
[root@localhost ~]# cd protobuf-master
生成configure文件的脚本文件,若是不执行这步,如下操做将通不过
[root@localhost protobuf-master]# ./autogen.sh
[root@localhost protobuf-master]# ./configure
能够修改安装目录经过 ./configure --prefix=命令,统一安装在/usr/local/protobuf下
[root@localhost protobuf-master]# ./configure --prefix=/usr/local/protobuf
[root@localhost protobuf-master]# make
[root@localhost protobuf-master]# make check
[root@localhost protobuf-master]# make install
[root@localhost protobuf-master]# ldconfig # refresh shared library cache.
安装成功
[root@localhost protobuf-master]# protoc -I=./ --cpp_out=./ test.proto安全
go get -u github.com/golang/protobuf/{proto,protoc-gen-go} go get -u google.golang.org/grpc protoc --go_out=plugins=grpc:. *.proto
syntax = "proto3"; package rpc_package; // define a service service HelloWorldService { // define the interface and data type rpc SayHello (HelloRequest) returns (HelloReply) {} } // define the data type of request message HelloRequest { string name = 1; } // define the data type of response message HelloReply { string message = 1; }
protoc --go_out=plugins=grpc:. helloworld.proto
// server.go import ( "log" "net" "golang.org/x/net/context" "google.golang.org/grpc" pb "helloworld/helloworld" ) 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) }
package main //client.go import ( "log" "os" "golang.org/x/net/context" "google.golang.org/grpc" pb "helloworld/helloworld" ) 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) }