RPC(Remote Procedure Call)遠程過程調用,關注筆者的同窗應該知道以前筆者出過關於Thrift對應的問題,此次主要來講的是Google開源的Grpc,和Thrift有很大的區別Grpc是基於HTTP2.0而且依賴protobuf,爲何又推出關於grpc的文章呢?請你們繼續往下看。php
附上:html
喵了個咪的博客:w-blog.cnjava
博文實例demo:GitHub - sunmi-OS/grpc-php-to-golang-demogit
grpc官網:grpc / grpc.iogithub
protobuf代碼倉庫:Releases · protocolbuffers/protobuf · GitHubgolang
一個高性能、通用的開源RPC框架,其由Google主要面向移動應用開發並基於HTTP/2協議標準而設計,基於ProtoBuf(Protocol Buffers)序列化協議開發,且支持衆多開發語言。 gRPC基於HTTP/2標準設計,帶來諸如雙向流控、頭部壓縮、單TCP鏈接上的多複用請求等特性。這些特性使得其在移動設備上表現更好,更省電和節省空間佔用。vim
性能 Grpc PK Thrift 借鑑:開源RPC(gRPC/Thrift)框架性能評測 - 滄海一滴 - 博客園框架
PS:筆者也作了對應的性能測試,後面的文章會附上詳細步驟,經過這個現有的結果一個簡單的結論tcp
從壓測的結果商米咱們能夠獲得如下重要結論:ide
這裏主要要回答的一個問題是既然已經用thrift而且性能仍是grpc的2倍爲何還要用grpc呢?
這裏主要要說到兩個Go的微服務框架,go-kit和istio
主要的致使這個問題的緣由在於thrift的傳輸方式是經過TCP的方式傳輸,對於這些框架想在傳輸過程當中加入些鏈路的ID是沒法實現的,istio連對於thrift的請求次數感知都作不到,對於grpc由於是基於http2在harder頭上能夠作不少補充參數,對於這類微服務框架很是友好。
安裝protobuf爲了生成對應語言的文件必須須要protoc的命名,protoc是c語言的protobuf的命名,有兩種訪問一個是本身編譯:
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.6.1/protobuf-cpp-3.6.1.tar.gz > tar -zxvf protobuf-cpp-3.6.1.tar.gz > cd protobuf-3.6.1 > ./configure > make > make install > protoc --version libprotoc 3.6.1
或者根據更具系統直接使用編譯好的bin文件運行protoc(這裏使用的是MAC OSX系統)
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.6.1/protoc-3.6.1-osx-x86_64.zip > tar -zxvf protoc-3.6.1-osx-x86_64.zip > cd protoc-3.6.1-osx-x86_6/bin > ./protoc --version > libprotoc 3.6.1
安裝好了咱們就要來運行下測試程序了
不得不說Go是Google的親兒子,天然Grpc的支持不會差依賴只須要一個命令就能夠(這裏使用的是go 1.11版本):
> go get google.golang.org/grpc
若是你們報錯,緣由是這個代碼已經轉移到github上面了,可是代碼裏面的包依賴仍是沒有修改,仍是google.golang.org這種,因此有的不能使用go get的方式安裝,可使用如下安裝方式:
> git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc > git clone https://github.com/golang/net.git $GOPATH/src/golang.org/x/net > git clone https://github.com/golang/text.git $GOPATH/src/golang.org/x/text > git clone https://github.com/golang/sys.git $GOPATH/src/golang.org/x/sys > go get -u github.com/golang/protobuf/{proto,protoc-gen-go} > git clone https://github.com/google/go-genproto.git $GOPATH/src/google.golang.org/genproto > cd $GOPATH/src/ > go install google.golang.org/grpc
先使用筆者的準備好的:
> cd $GOPATH/src > mkdir -p grpc-php-to-golang-demo/protobuf > cd grpc-php-to-golang-demo/protobuf > vim helloworld.proto
文件內容以下:
syntax = "proto3"; option java_multiple_files = true; option java_package = "io.grpc.examples.helloworld"; option java_outer_classname = "HelloWorldProto"; option objc_class_prefix = "HLW"; package helloworld; // The greeting 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; }
生成對應的文件:
> mkdir -p go-server/helloworld > protoc --go_out=plugins=grpc:./go-server/helloworld ./helloworld.proto > cd go-server/helloworld/ > ll total 16 drwxr-xr-x 3 wenzhenxi staff 96 2 15 14:24 ./ drwxr-xr-x 3 wenzhenxi staff 96 2 15 14:23 ../ -rw-r--r-- 1 wenzhenxi staff 6915 2 15 14:24 helloworld.pb.go
編寫服務端和客戶端Go程序:
> cd $GOPATH/src/grpc-php-to-golang-demo > mkdir -p golang/holleworld > cd golang/holleworld
服務端:
> vim server.go package main import ( "log" "net" pb "grpc-php-to-golang-demo/protobuf/go-server/helloworld" "google.golang.org/grpc" "golang.org/x/net/context" "google.golang.org/grpc/reflection" ) const ( port = ":50051" ) // server is used to implement helloworld.GreeterServer. 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 } 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) } }
客戶端:
> vim client.go package main import ( "log" "os" "time" pb "grpc-php-to-golang-demo/protobuf/go-server/helloworld" "google.golang.org/grpc" "golang.org/x/net/context" ) const ( address = "localhost:50051" defaultName = "world" ) 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] } go func() { 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) }() time.Sleep(10 * time.Second) }
運行測試:
> go build server.go > go build client.go ./server ./client 2019/02/15 14:35:35 Greeting: Hello world
此時在go to go的場景就調用通了
最終產物能夠參考demoGitHub - sunmi-OS/grpc-php-to-golang-demo