所謂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) }